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

Add an ability to try Workspace.Next features #9774

Merged
merged 10 commits into from
Jun 5, 2018

Conversation

garagatyi
Copy link

@garagatyi garagatyi commented May 22, 2018

This PR is designed to be reviewed in a commit by commit manner.

It is in WIP state because not all the unit tests are finished.

What does this PR do?

Add an ability to try Workspace.Next features.
To try it out user needs to add an attribute to a workspace with name features and a list of features as a value.
An example of value: "org.eclipse.che.che-theia-hello/0.0.1,org.eclipse.che.che-theia-ssh/0.0.1"
This PR contains code to use Workspace.Next with the kubernetes recipe only.
Support of other recipes should be added additionally.

What issues does this PR fix or reference?

Release Notes

Docs PR

@garagatyi garagatyi requested a review from riuvshin as a code owner May 22, 2018 14:31
@benoitf benoitf added the status/code-review This issue has a pull request posted for it and is awaiting code review completion by the community. label May 22, 2018
Copy link
Member

@sleshchenko sleshchenko left a comment

Choose a reason for hiding this comment

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

In general, looks good to me 👍
I'll clone your changes locally and review in details.

* Should be set/read from {@link Workspace#getAttributes}.
*
* <p/>Value is comma separated list of features in a format:
* '< feature1Name >/< feature1Version >,< feature2Name >/< feature2Version >'
Copy link
Member

Choose a reason for hiding this comment

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

Why is / symbol chosen as a separator of name and version? Wouldn't : symbol more conventional?

Copy link
Author

Choose a reason for hiding this comment

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

It is better to ask @skabashnyuk - it is Feature API that declares format.

Copy link
Contributor

Choose a reason for hiding this comment

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

The format is still under discussion. I do like : Fill free to comment. #9895

Copy link
Member

Choose a reason for hiding this comment

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

Looks like examples specified by the shared link contain : as separator but Feature API is implemented with /

LOG.error(
"Response doesn't contain any data, though it was expected to contain some.");
throw new IOException(
"Internal server error. Unexpected response body received.");
Copy link
Member

Choose a reason for hiding this comment

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

I would say that empty response body would be more accurate message.

Copy link
Author

Choose a reason for hiding this comment

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

Does message Response contains an empty body, though it was expected to contain data looks better to you?

Copy link
Member

Choose a reason for hiding this comment

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

If the message will contain that this response is from "Feature API" then it would be even more clear and helpful.

Copy link
Author

Choose a reason for hiding this comment

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

ok

@@ -270,6 +270,8 @@ items:
configMapKeyRef:
key: CHE_INFRA_KUBERNETES_SERVER__STRATEGY
name: che
- name: CHE_WORKSPACE_FEATURE_API
value: "http://feature-api-service:3000"
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it better to move a value to the config map?

Copy link
Author

Choose a reason for hiding this comment

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

Agree, will update this

Copy link
Member

@sleshchenko sleshchenko left a comment

Choose a reason for hiding this comment

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

Good job. Please ping me one more time when PR won't be WIP.

"Features format is illegal. Problematic feature entry:" + feature);
}
String key = featureAndVersion[0] + '/' + featureAndVersion[1];
if (featuresNameVersion.containsKey(key)) {
Copy link
Member

Choose a reason for hiding this comment

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

I guess you can use feature here instead of contacting separated values.

String parameterKey =
serviceName + "/" + serviceVersion + "/${" + cheServiceParameter.getName() + "}";
parameters.putIfAbsent(parameterKey, new ArrayList<>());
List<String> cheServiceParameters = parameters.get(parameterKey);
Copy link
Member

Choose a reason for hiding this comment

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

parameters.putIfAbsent(parameterKey, new ArrayList<>());
List<String> cheServiceParameters = parameters.get(parameterKey);

May be rewritten in Java 8 style

List<String> cheServiceParameters = parameters.computeIfAbsent(parameterKey, (key) -> new ArrayList<>());


/**
* Returns map where key is concatenation of service name, version and parameter name separated by slash symbol.
* < serviceName/serviceVersion/parameter > to < parameterValue >
Copy link
Member

Choose a reason for hiding this comment

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

Looks like it's outdated format since the format is < serviceName/serviceVersion/${parameter} >. Am I right?

Copy link
Author

Choose a reason for hiding this comment

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

yes, thanks for pointing it out

String envVarValue = envVar.getValue();
String parameterKey = serviceKey + '/' + envVarValue;
List<String> remove = parameters.remove(parameterKey);
if (remove != null) {
Copy link
Member

Choose a reason for hiding this comment

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

Just idea to discuss, maybe we should set empty value if there is not the corresponding parameter value in a feature?

Copy link
Author

Choose a reason for hiding this comment

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

maybe, I'm not sure here

// for now we match whole env variable value against '${<parameter name>}'
service.getSpec()
.getContainers()
.forEach(container -> container.getEnv()
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it would be better(maybe not =)) to rewrite it in the following manner

      service.getSpec()
          .getContainers()
          .stream()
          .flatMap(c -> c.getEnv().stream())
          .forEach(envVar -> {...});

Copy link
Author

Choose a reason for hiding this comment

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

Right now this code throws an exception, so I can't do like that. Actually, this code looked like that before)

/**
* Applies Workspace.Next configuration to an internal runtime object that represents workspace
* runtime configuration on an infrastructure level.
*
Copy link
Member

Choose a reason for hiding this comment

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

I think it may be helpful to add a note that implementations must be bound with map binder and maybe add an example of binding.

Copy link
Author

Choose a reason for hiding this comment

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

Not sure that class should know what DI container is used and declare it. I'll think about it.

@@ -270,6 +270,8 @@ items:
configMapKeyRef:
key: CHE_INFRA_KUBERNETES_SERVER__STRATEGY
name: che
- name: CHE_WORKSPACE_FEATURE_API
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it makes sense to add the same configuration into OS deployment

Copy link
Author

Choose a reason for hiding this comment

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

I didn't check workspace next on OS infra, so don't want to add it for the time

@Override
public void apply(InternalEnvironment internalEnvironment, Collection<CheService> cheServices)
throws InfrastructureException {
KubernetesEnvironment kubernetesEnvironment = (KubernetesEnvironment) internalEnvironment;
Copy link
Member

Choose a reason for hiding this comment

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

It makes sense to move this line lower since it is not needed to cast environment if Che services list is empty

Copy link
Author

Choose a reason for hiding this comment

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

ur right, thanks

io.fabric8.kubernetes.api.model.Container container =
new ContainerBuilder()
.withImage(image)
.withName(Names.generateName(""))
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it makes sense to add some meaningful prefix like "tooling"

Copy link
Author

Choose a reason for hiding this comment

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

ok

Oleksandr Garagatyi added 7 commits June 4, 2018 14:48
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Add missing override annotations.
Cleanup the code.
Use existing getters instead of a field to prevent bugs with
inheritance.
Move public methods to the beggining of classes.
Fix incorrect javadocs and misleading parameters names.
Add a comment that explains why a compiler warning should be
ignored.
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
…l environment

Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
@garagatyi
Copy link
Author

@sleshchenko I've updated PR with fixes, unit tests and rebased it against master to resolve conflicts. Please, take a look one more time.

@l0rd @skabashnyuk Looks like this PR is not successful in acquiring new code reviewers, so I'll merge it as soon as @sleshchenko approves it unless other reviews appear.

@garagatyi garagatyi changed the title [WIP] Add an ability to try Workspace.Next features Add an ability to try Workspace.Next features Jun 4, 2018
Copy link
Member

@sleshchenko sleshchenko left a comment

Choose a reason for hiding this comment

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

Good job 👍

}
}

private void validateFeature(CheFeature feature, String name, String version)
Copy link
Member

Choose a reason for hiding this comment

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

Just proposal. Maybe it would be better to move validation private methods to new Validator class to make this class a bit smaller.

Copy link
Author

Choose a reason for hiding this comment

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

I would not want to create a separate class for that. At least for now.

}
}

private void requireEqual(String version, String version1, String error, String... errorArgs)
Copy link
Member

Choose a reason for hiding this comment

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

I guess you used Refactor functionality and it's why the arguments are named version and version1. Am I right?

Copy link
Author

Choose a reason for hiding this comment

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

Looks like, I don't really remember, to be honest.

return;
}
KubernetesEnvironment kubernetesEnvironment = (KubernetesEnvironment) internalEnvironment;
Map<String, Pod> pods = ((KubernetesEnvironment) internalEnvironment).getPods();
Copy link
Member

Choose a reason for hiding this comment

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

Looks like you don't need to cast it for the second time and you can reuse kubernetesEnvironment

Copy link
Author

Choose a reason for hiding this comment

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

thanks



@Mock
Pod pod;
Copy link
Member

Choose a reason for hiding this comment

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

Looks like unformatted. Please don't forget to execute mvn fmt:format before merge.
Also, I would make these variable private. It doesn't really matter while it is test class but still.

Copy link
Author

Choose a reason for hiding this comment

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

ok

app: feature-api
name: feature-api
data:
CHE_REGISTRY_UPDATE_INTERVAL: "60"
Copy link
Member

Choose a reason for hiding this comment

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

Is it value in seconds?

Copy link
Author

Choose a reason for hiding this comment

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

yes

@@ -0,0 +1,85 @@
---
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to have few words in Deploy Che.md about deploying feature-api

Copy link
Author

Choose a reason for hiding this comment

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

ok

@benoitf benoitf added the kind/enhancement A feature request - must adhere to the feature request template. label Jun 4, 2018
@garagatyi garagatyi requested a review from vparfonov as a code owner June 4, 2018 14:17
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
@garagatyi
Copy link
Author

ci-build

@codenvy-ci
Copy link

Build # 4548 - FAILED

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

Copy link
Contributor

@l0rd l0rd left a comment

Choose a reason for hiding this comment

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

Sorry my review comes really late. That's a great PR and the code is clean and easy to read/review but I think we should still discuss if a Container should have a list of Servers.

@@ -33,3 +33,7 @@ and clean redeploy of Che.
- Create namespace `che`: `kubectl create namespace che`
- Deploy Che: `kubectl --namespace=che apply -f che-kubernetes.yaml`
- Check Che pod status until it become `Running`: `kubectl get --namespace=che pods`

### Workspace Next:
There is a file `wsnext/feature-api.yaml` which contains kubesrb service needed to test Workspace Next on kubernetes infrastructure.
Copy link
Contributor

Choose a reason for hiding this comment

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

You may want to s/kubesrb/kubesrv/

Copy link
Author

Choose a reason for hiding this comment

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

thanks

private List<EnvVar> env = new ArrayList<EnvVar>();
private ResourceRequirements resources = null;
private List<Command> commands = new ArrayList<Command>();
private List<Server> servers = new ArrayList<Server>();
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't remember that Container had a list of servers as an attribute in the original model. And I don't think that we should do that:

  • A CheService that has a list of Container and each Container has a list of Servers is something difficult to understand (what's the difference between a CheService and a Server?)
  • Moreover one of workspace.next goals was to extract the list servers that originally ran in on container into multiple containers (sidecars). So it doesn't make sense to have a list of Server for each Container.

I would suggest to move higher (at CheService level) the attributes of the Server.

Copy link
Author

Choose a reason for hiding this comment

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

I clearly see servers field in one of the model versions, in particular, #9292 (comment).

what's the difference between a CheService and a Server

As we discussed before usage of Service word is confusing and brings misunderstanding like this one.

Moreover one of workspace.next goals was to extract the list servers that originally ran in on container into multiple containers (sidecars). So it doesn't make sense to have a list of Server for each Container.

It make sense. We should, probably, discuss it with @skabashnyuk.

I would suggest to move higher (at CheService level) the attributes of the Server.

I don't own Workspace.Next model, so I would discuss it with Sergii first. In any case I think it makes sense to do that in a separate PR.

import java.util.List;
import java.util.Objects;

public class Container {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be more consistent to call it CheContainer (as CheService or CheFeature)? In the issue where the model is described it is called Container but that's weird. WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

Maybe. I reused already generated files by Swagger model because I don't want to bring new changes that I would have to redo after regeneration of the model classes.
So, I believe, it is rather a suggestion for @skabashnyuk

Oleksandr Garagatyi added 2 commits June 5, 2018 10:02
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
@garagatyi
Copy link
Author

ci-build

@codenvy-ci
Copy link

Build # 4549 - FAILED

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

@riuvshin
Copy link
Contributor

riuvshin commented Jun 5, 2018

ci-build

@codenvy-ci
Copy link

@garagatyi garagatyi merged commit ddb86c4 into eclipse-che:master Jun 5, 2018
@garagatyi garagatyi deleted the wsnext_infra_clean branch June 5, 2018 17:40
@benoitf benoitf removed the status/code-review This issue has a pull request posted for it and is awaiting code review completion by the community. label Jun 5, 2018
@benoitf benoitf added this to the 6.7.0 milestone Jun 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement A feature request - must adhere to the feature request template.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants