Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CHE-2369: add a mechanism which checks state of the ws agent #2530

Merged
merged 1 commit into from
Oct 10, 2016
Merged

Conversation

svor
Copy link
Contributor

@svor svor commented Sep 21, 2016

What does this PR do?

Adds a service which periodically pings ws agent and notify a user when something is happened.

What issues does this PR fix or reference?

#2369

Previous behavior

When ws agent stops responding a user don't get any response about this and don't know what is happened.

PR type

  • Minor change = no change to existing features or docs
  • Major change = changes existing features or docs

Minor change checklist

  • New API required?
  • API updated
  • Tests provided / updated
  • Tests passed

@vparfonov please take a look

dialogFactory.createMessageDialog(infoWindowTitle,
"Your workspace is not responding. To fix the problem, verify you have a good " +
"network connection and restart the workspace.",
new ConfirmCallback() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use use null instead empty ConfirmCallback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thx!

@codenvy-ci
Copy link

Log.warn(getClass(), "Parse root resources failed.");
}

if (object != null && object.containsKey("rootResources")) {
Copy link
Member

@azatsarynnyy azatsarynnyy Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you move this if-block inside the upper try-block
checking object != null will be unnecessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thx!

dialogFactory.createMessageDialog(infoWindowTitle,
"Your workspace has stopped responding. To fix the problem, " +
"restart the workspace in the dashboard.",
new ConfirmCallback() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConfirmCallback is nullable so no need to create this ConfirmCallback that does nothing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thx!

@codenvy-ci
Copy link

@vparfonov
Copy link
Contributor

@garagatyi pls review

AgentHealthStateDto withAgentId(String agentId);

/** Returns id of the agent */
String getAgentId();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is Agent ID?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some id of agent or reference, what problem here ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern is in addition of new terminology -agent ID

import java.io.IOException;

/**
* Interface which describes mechanism for checking agent's state.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not mandatory to explain purpose of interface with interface term

* Verify if the agent is alive.
*
* @param devMachine
* development machine instance

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it for development machine only?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep good catch, it can be any machine

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose and life cycle of it has to be properly documented.
In particular:

  • why it needed
  • what and when calls check method

* if internal server error occurred
* @throws ForbiddenException
* if the user is not workspace owner
* @throws BadRequestException

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add explanation for this exception

* @throws UnauthorizedException
* if the user is not authorized
* @throws IOException
* @throws ConflictException
Copy link

@garagatyi garagatyi Sep 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add explanation for these exceptions

*/
@Api(value = "/workspace-agent-health", description = "Workspace Agent Health Checker")
@Path("/workspace-agent-health")
public class AgentHealthCheckerService extends Service {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tests for this class

@codenvy-ci
Copy link

@codenvy-ci
Copy link

@codenvy-ci
Copy link

Build # 514 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/514/ to view the results.

@codenvy-ci
Copy link

Build # 515 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/515/ to view the results.

@codenvy-ci
Copy link

@codenvy-ci
Copy link

@codenvy-ci
Copy link

Build # 528 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/528/ to view the results.

import static org.eclipse.che.ide.api.machine.WsAgentState.STARTED;
import static org.eclipse.che.ide.api.machine.WsAgentState.STOPPED;
import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;

/**
* @author Roman Nikitenko
* @author Valeriy Svydenko
*/
@Singleton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No single word about purpose of this class, the same for public methods.
Please add java docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
}

private void checkWsAgentState() {
final String url = restContext + "/workspace/" + devMachine.getWorkspace() + "/check";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can not we put and take this URL from DevMachine?
Such a string concatenation looks bad.
BTW, DevMachine is initialized not in constructor, what if DevMachine == null by any reason?


WsAgentHealthStateDto withCode(int code);

void setReason(String reason);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could not we remove set methods in DTO (in general)?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

}

final WsAgentHealthStateDto check = agentHealthChecker.check(devMachine);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space

final WsAgentHealthStateDto check = agentHealthChecker.check(devMachine);

check.setWorkspaceStatus(workspace.getStatus());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space


void setCode(int code);

/** Returns status code. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where to see possible values for the code?
(java docs)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it just HTTP status code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to say it is java-docs and name the parameter accordingly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated jdoc

* well configured proxy server or other problems which are not related to our responsibility.
*
* @author Vitalii Parfonov
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we really have several implementations of it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes for codenvy it require authorization token

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt it worth another implementation. I'd say we need a policy for it - like if there are no token it is taken as "allowed". I suppose Codenvy always includes token and Che always does not. Is not it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we include token in other implementation that provided in codenvy repository. Or i don't understand your notes

Server wsAgent = null;
for (Server server : servers.values()) {
if (WSAGENT_REFERENCE.equals(server.getRef())) {
wsAgent = server;
Copy link
Contributor

@mshaposhnik mshaposhnik Sep 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we stop iterations here ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, we can

@Produces(APPLICATION_JSON)
@ApiOperation(value = "Get state of the workspace agent by the workspace id and agent id")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested workspace entity"),
@ApiResponse(code = 404, message = "The workspace with specified id does not exist"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLs add status codes for BadRequest (400), Conflict(409), Unauthrorized(401) (btw who is throwing unauthorized?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok for 400 and I think don't need to add for other two (409 and 401),we don't have situations where it can be threw.

UnauthorizedException,
IOException,
ConflictException {
validateKey(key);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is not needed if we accept oly ID's (and no composite keys)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@codenvy-ci
Copy link

Build # 536 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/536/ to view the results.

Copy link

@garagatyi garagatyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR requires some fixes. Also, please, clarify questions in comments

@@ -89,6 +91,8 @@ protected void configure() {
new org.eclipse.che.api.machine.server.model.impl.ServerConfImpl(Constants.WSAGENT_DEBUG_REFERENCE, "4403/tcp", "http",
null));

bind(WsAgentHealthChecker.class).to(WsAgentHealthCheckerImpl.class);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use FQNs in modules

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* @throws ServerException
* if internal server error occurred
* @throws ForbiddenException
* if the user is not workspace owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about workspace workers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* if internal server error occurred
* @throws ForbiddenException
* if the user is not workspace owner
* @throws BadRequestException

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exception should not be used outside of REST services.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not reason to expose that exception

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* if the user is not workspace owner
* @throws BadRequestException
* if has invalid parameters
* @throws UnauthorizedException

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How it it possible? Is this functionality behind the login filter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not reason to expose that exception

* if has invalid parameters
* @throws UnauthorizedException
* if the user is not authorized
* @throws ConflictException

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain in which situation this exception might be thrown?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not reason to expose that exception

ForbiddenException,
BadRequestException,
UnauthorizedException,
IOException,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IOException should not be exposed here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

ServerException,
ForbiddenException,
BadRequestException,
UnauthorizedException,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this method behind login filter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be thrown by REST this service, so should not be exposed in this method

@PathParam("id") String key) throws NotFoundException,
ServerException,
ForbiddenException,
BadRequestException,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see the case when this exception can be thrown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be thrown by REST this service, so should not be exposed in this method

BadRequestException,
UnauthorizedException,
IOException,
ConflictException {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case this exception can be thrown?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be thrown by REST this service, so should not be exposed in this method

return newDto(WsAgentHealthStateDto.class)
.withWorkspaceStatus(workspace.getStatus())
.withCode(NOT_FOUND.getStatusCode())
.withReason("Workspace Agent isn't available if Dev machine isn't RUNNING");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if term dev-machine is blessed for error messages

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most modern term ws-machine, but I'm not sure. @eivantsov can you help with that?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dev-machine is what's it's called in consoles panel right now

final HttpJsonRequest pingRequest = createPingRequest(machine);
final HttpJsonResponse response = pingRequest.request();
agentHealthStateDto.withCode(response.getResponseCode())
.withReason(response.asString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have a reason as strigified json?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no

@codenvy-ci
Copy link

Build # 546 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/546/ to view the results.

@codenvy-ci
Copy link

@@ -15,6 +15,7 @@
import com.google.inject.name.Names;
import com.google.inject.persist.jpa.JpaPersistModule;

import org.eclipse.che.api.agent.server.WsAgentHealthChecker;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove unneeded imports

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed, thx


@Override
public WsAgentHealthStateDto check(Machine machine) throws NotFoundException, ServerException {
final Map<String, ? extends Server> servers = machine.getRuntime().getServers();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving of this line to getWsAgent method since it is not used anywhere else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

@svor
Copy link
Contributor Author

svor commented Sep 29, 2016

@garagatyi I've applied your remarks, take a look please again!

String wsAgentPingUrl = wsAgent.getUrl();
// since everrest mapped on the slash in case of it absence
// we will always obtain not found response
if (!wsAgentPingUrl.endsWith("/")) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is theoretically possible that URL will be null, so please add check that prevents NPE

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@Produces(APPLICATION_JSON)
@ApiOperation(value = "Get state of the workspace agent by the workspace id and agent id")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested workspace entity"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't throw 400 anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@ApiOperation(value = "Get state of the workspace agent by the workspace id and agent id")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested workspace entity"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 404, message = "The workspace with specified id does not exist"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another case is connected to ws agent check - please mention that also

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case it's internal server error

@GET
@Path("/{id}/check")
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Get state of the workspace agent by the workspace id and agent id")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove agent id

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

}
try {
final HttpJsonRequest pingRequest = createPingRequest(machine, wsAgent);
final HttpJsonResponse response = pingRequest.request();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this method throws NotFoundException. If request to ws-agent returns 404 it looks like internal server error. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with internal server error

* @throws ServerException
* if internal server error occurred
*/
WsAgentHealthStateDto check(Machine machine) throws NotFoundException, ServerException;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove not found exception from method declaration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError arg) throws OperationException {
Log.error(getClass(), arg.getMessage());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will it handle internal server error in appropriate way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

}
try {
final HttpJsonRequest pingRequest = createPingRequest(machine, wsAgent);
final HttpJsonResponse response = pingRequest.request();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pinging miss super new feature of internal/external urls of agents contributed by Mario. So if it is possible please create single component for pinging and use it here and in WsAgentlauncherImpl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@codenvy-ci
Copy link

Build # 560 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/560/ to view the results.

Copy link

@garagatyi garagatyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

@codenvy-ci
Copy link

Build # 567 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/567/ to view the results.

@codenvy-ci
Copy link

Build # 621 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/621/ to view the results.

@codenvy-ci
Copy link

Build # 625 - FAILED

Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/625/ to view the results.

@vparfonov vparfonov added this to the 5.0.0-M6 milestone Oct 6, 2016
@svor svor merged commit 3309540 into master Oct 10, 2016
@svor svor deleted the CHE-1988 branch October 10, 2016 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.