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 possibility to specify reference or registry url for chePlugin/cheEditor type components #13297

Merged
merged 37 commits into from
Jun 10, 2019
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
77e53d7
Add registryUrl into editor/plugin components
mshaposhnik May 3, 2019
d238e59
Put reference into PluginFQN
mshaposhnik May 8, 2019
10b5e1b
Fixes for the components with references
mshaposhnik May 8, 2019
7fb6445
Fix typo
mshaposhnik May 8, 2019
337e76c
Fix in FQN parser
mshaposhnik May 10, 2019
bf2e2b2
FQN paresr fixes
mshaposhnik May 11, 2019
7adb88f
fixup! FQN paresr fixes
mshaposhnik May 13, 2019
9608e3d
Merge branch 'master' into registryUrl
mshaposhnik May 20, 2019
e1b5380
Prefetch plugins with references
mshaposhnik May 23, 2019
5fefb23
Merge with master
mshaposhnik May 24, 2019
b82ef32
More fixups
mshaposhnik May 24, 2019
849787a
Make default plugin resolving respect referenced pluins
mshaposhnik May 24, 2019
16b3780
Merge branch 'master' into registryUrl
mshaposhnik May 28, 2019
a793855
User FileContentProvider
mshaposhnik May 29, 2019
2adeba4
Move some classes to WS api
mshaposhnik May 29, 2019
b6b709d
Merge branch 'master' into registryUrl
mshaposhnik May 30, 2019
c28e5f5
Use FileContentProvider in tests
mshaposhnik May 30, 2019
e36e710
Use FileContentProvider in tests
mshaposhnik May 30, 2019
4a3a2fb
Merge witj latest master
mshaposhnik May 31, 2019
0111a48
Use per-request file content provider
mshaposhnik Jun 3, 2019
04dc344
Fixup test
mshaposhnik Jun 3, 2019
1997b6a
Fixup test
mshaposhnik Jun 3, 2019
a71d436
Code feractoring
mshaposhnik Jun 3, 2019
8d2f3dc
Code feractoring
mshaposhnik Jun 3, 2019
666e328
Code feractoring
mshaposhnik Jun 3, 2019
245428d
Merge branch 'master' into registryUrl
mshaposhnik Jun 5, 2019
d1e011c
Add doc example about references and registry url-s
mshaposhnik Jun 5, 2019
1ba01b5
Merge branch 'master' into registryUrl
mshaposhnik Jun 5, 2019
c232369
Change schema version
mshaposhnik Jun 6, 2019
34cac61
FIx review comments
mshaposhnik Jun 6, 2019
110f77b
Fix typos & comments
mshaposhnik Jun 6, 2019
2c179f9
Review fixes
mshaposhnik Jun 6, 2019
79fbde3
refactor FQN parsing
mshaposhnik Jun 6, 2019
0c13775
Code fix
mshaposhnik Jun 7, 2019
669f3ad
Javadoc fixup
mshaposhnik Jun 10, 2019
d736c7d
Review fixups & broker version
mshaposhnik Jun 10, 2019
7541cb1
Fixup regex
mshaposhnik Jun 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ public interface Component {
Map<String, String> getPreferences();

/**
* Returns absolute or devfile-relative location of Kubernetes list yaml file. It is mandatory and
* applicable only for 'kubernetes' and 'openshift' components types.
* For 'kubernetes' and 'openshift' components types, returns absolute or devfile-relative
* location of Kubernetes list yaml file.
*
* <p>For 'cheEditor' and 'chePlugin' components types, returns absolute location of plugin
* descriptor (typically, named meta.yaml). For those types this field is optional.
*/
String getReference();

/**
* Returns address of custom plugin registry. It is optional and applicable only for 'cheEditor'
* and 'chePlugin' components types.
*/
String getRegistryUrl();

/**
* Returns inlined content of a file specified in field 'reference'. It is optional and applicable
* only for 'kubernetes' and 'openshift' components types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import org.eclipse.che.api.workspace.server.devfile.convert.component.ComponentToWorkspaceApplier;
import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
Expand Down Expand Up @@ -123,8 +122,7 @@ public void apply(
k8sEnvProvisioner.provision(workspaceConfig, environmentType, componentObjects, emptyMap());
}

private String retrieveContent(
Component recipeComponent, @Nullable FileContentProvider fileContentProvider)
private String retrieveContent(Component recipeComponent, FileContentProvider fileContentProvider)
throws DevfileException {
checkArgument(fileContentProvider != null, "Content provider must not be null");
if (!isNullOrEmpty(recipeComponent.getReferenceContent())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public void shouldNoNothingIfWorkspaceDoesNotHaveEnvironmentsWithKubernetesOpenS
assertEquals(dockerimageComponent.getEndpoints().size(), 1);
EndpointImpl endpoint = dockerimageComponent.getEndpoints().get(0);
assertEquals(endpoint.getName(), "server");
assertEquals(endpoint.getPort(), new Integer(8080));
assertEquals(endpoint.getPort(), Integer.valueOf(8080));
assertEquals(endpoint.getAttributes().size(), 3);
assertEquals(endpoint.getAttributes().get("protocol"), "http");
assertEquals(endpoint.getAttributes().get("path"), "/api");
Expand Down Expand Up @@ -224,7 +224,7 @@ public void shouldNoNothingIfWorkspaceDoesNotHaveEnvironmentsWithKubernetesOpenS
assertEquals(dockerimageComponent.getEndpoints().size(), 1);
EndpointImpl endpoint = dockerimageComponent.getEndpoints().get(0);
assertEquals(endpoint.getName(), "server");
assertEquals(endpoint.getPort(), new Integer(8080));
assertEquals(endpoint.getPort(), Integer.valueOf(8080));
assertTrue(endpoint.getAttributes().isEmpty());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ public void shouldProvisionServiceForDiscoverableServer() throws Exception {
List<ServicePort> ports = service.getSpec().getPorts();
assertEquals(ports.size(), 1);
ServicePort port = ports.get(0);
assertEquals(port.getPort(), new Integer(4923));
assertEquals(port.getPort(), Integer.valueOf(4923));
assertEquals(port.getTargetPort(), new IntOrString(4923));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ public interface ComponentDto extends Component {

ComponentDto withId(String id);

// plugin
@Override
String getRegistryUrl();

void setRegistryUrl(String registryUrl);

ComponentDto withRegistryUrl(String registryUrl);

@Override
Map<String, String> getPreferences();
Expand All @@ -52,15 +57,14 @@ public interface ComponentDto extends Component {

ComponentDto withPreferences(Map<String, String> preferences);

// k8s/OS

@Override
String getReference();

void setReference(String reference);

ComponentDto withReference(String reference);

// k8s/OS
mshaposhnik marked this conversation as resolved.
Show resolved Hide resolved
@Override
String getReferenceContent();

Expand Down
28 changes: 28 additions & 0 deletions wsmaster/che-core-api-workspace/README-devfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,34 @@ It is allowed to have several `chePlugin` components.

Both types above using id, which is slash-separated publisher, name and version of plugin from Che Plugin registry.
List of available Che plugins and more information about registry can be found on https://github.com/eclipse/che-plugin-registry.

It is also possible to specify own registry for the cheEditor and chePlugin types, by using
`registryUrl` parameter as follows:

```
...
components:
- alias: exec-plugin
type: chePlugin
registryUrl: https://my-customregistry.com
id: eclipse/che-machine-exec-plugin/0.0.1
```

As an alternative way of specifying editor or plugin, instead of using plugin id (+ optional registry),
it is possible to provide direct link to the plugin descriptor (typically, named `meta.yaml`) by using
the reference field:

```
...
components:
- alias: exec-plugin
type: chePlugin
reference: https://raw.githubusercontent.com.../plugin/1.0.1/meta.yaml
```

Please note it's not possible to mix id and reference in single plugin definition, they are distinctive fields.
mshaposhnik marked this conversation as resolved.
Show resolved Hide resolved


For each of types above it is also possible to specify container(s) memory limit as follows:
```
...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@
*/
package org.eclipse.che.api.workspace.server.devfile.convert;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.che.api.workspace.server.devfile.Constants.EDITOR_COMPONENT_TYPE;
import static org.eclipse.che.api.workspace.server.devfile.Constants.EDITOR_FREE_DEVFILE_ATTRIBUTE;
import static org.eclipse.che.api.workspace.server.devfile.Constants.PLUGIN_COMPONENT_TYPE;

import com.google.common.base.Strings;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.che.api.core.model.workspace.devfile.Component;
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider;
import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl;
Expand All @@ -48,7 +49,7 @@ public DefaultEditorProvisioner(
@Named("che.workspace.devfile.default_editor.plugins") String[] defaultPluginsRefs,
PluginFQNParser fqnParser)
throws DevfileException {
this.defaultEditorRef = Strings.isNullOrEmpty(defaultEditorRef) ? null : defaultEditorRef;
this.defaultEditorRef = isNullOrEmpty(defaultEditorRef) ? null : defaultEditorRef;
this.fqnParser = fqnParser;
this.defaultEditor =
this.defaultEditorRef == null ? null : getPluginPublisherAndName(this.defaultEditorRef);
Expand All @@ -64,8 +65,10 @@ public DefaultEditorProvisioner(
* editor regardless whether it is provisioned or set by user.
*
* @param devfile devfile where editor and plugins should be provisioned
* @param contentProvider content provider for plugin references retrieval
*/
public void apply(DevfileImpl devfile) throws DevfileException {
public void apply(DevfileImpl devfile, FileContentProvider contentProvider)
throws DevfileException {
if (defaultEditorRef == null) {
// there is no default editor configured
return;
Expand All @@ -86,20 +89,23 @@ public void apply(DevfileImpl devfile) throws DevfileException {
isDefaultEditorUsed = true;
} else {
Component editor = editorOpt.get();
isDefaultEditorUsed = defaultEditor.equals(getPluginPublisherAndName(editor.getId()));
String editorPublisherAndName = getPluginPublisherAndName(editor, contentProvider);
isDefaultEditorUsed = defaultEditor.equals(editorPublisherAndName);
}

if (isDefaultEditorUsed) {
provisionDefaultPlugins(components);
provisionDefaultPlugins(components, contentProvider);
}
}

private void provisionDefaultPlugins(List<ComponentImpl> components) throws DevfileException {
private void provisionDefaultPlugins(
List<ComponentImpl> components, FileContentProvider contentProvider) throws DevfileException {
Map<String, String> missingPluginsIdToRef = new HashMap<>(defaultPluginsToRefs);

for (ComponentImpl t : components) {
if (PLUGIN_COMPONENT_TYPE.equals(t.getType())) {
missingPluginsIdToRef.remove(getPluginPublisherAndName(t.getId()));
String pluginPublisherAndName = getPluginPublisherAndName(t, contentProvider);
missingPluginsIdToRef.remove(pluginPublisherAndName);
}
}

Expand All @@ -108,9 +114,24 @@ private void provisionDefaultPlugins(List<ComponentImpl> components) throws Devf
.forEach(pluginRef -> components.add(new ComponentImpl(PLUGIN_COMPONENT_TYPE, pluginRef)));
}

private String getPluginPublisherAndName(String reference) throws DevfileException {
private String getPluginPublisherAndName(Component component, FileContentProvider contentProvider)
throws DevfileException {
try {
if (component.getId() != null) {
return getPluginPublisherAndName(component.getId());
} else {
return fqnParser
.evaluateFqn(component.getReference(), contentProvider)
.getPublisherAndName();
}
} catch (InfrastructureException e) {
throw new DevfileException(e.getMessage(), e);
}
}

private String getPluginPublisherAndName(String pluginId) throws DevfileException {
try {
ExtendedPluginFQN meta = fqnParser.parsePluginFQN(reference);
ExtendedPluginFQN meta = fqnParser.parsePluginFQN(pluginId);
return meta.getPublisherAndName();
} catch (InfrastructureException e) {
throw new DevfileException(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.che.api.core.model.workspace.devfile.Devfile;
import org.eclipse.che.api.workspace.server.devfile.DevfileRecipeFormatException;
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider;
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider.CachingProvider;
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
import org.eclipse.che.api.workspace.server.devfile.URLFileContentProvider;
import org.eclipse.che.api.workspace.server.devfile.convert.component.ComponentProvisioner;
Expand Down Expand Up @@ -114,7 +115,8 @@ public DevfileImpl workspaceToDevFile(WorkspaceConfigImpl wsConfig)

public WorkspaceConfig convert(Devfile devfile) throws ServerException {
try {
return devFileToWorkspaceConfig(new DevfileImpl(devfile), urlFileContentProvider);
return devFileToWorkspaceConfig(
new DevfileImpl(devfile), new CachingProvider(urlFileContentProvider));
mshaposhnik marked this conversation as resolved.
Show resolved Hide resolved
} catch (DevfileException e) {
throw new ServerException(e.getMessage(), e);
}
Expand All @@ -124,7 +126,7 @@ public WorkspaceConfig convert(Devfile devfile) throws ServerException {
* Converts given {@link Devfile} into {@link WorkspaceConfigImpl workspace config}.
*
* @param devfile initial devfile
* @param contentProvider content provider for recipe-type component
* @param contentProvider content provider for recipe-type component or plugin references
* @return constructed workspace config
* @throws DevfileException when general devfile error occurs
* @throws DevfileException when devfile requires additional files content but the specified
Expand All @@ -143,7 +145,7 @@ public WorkspaceConfigImpl devFileToWorkspaceConfig(

validateCurrentVersion(devfile);

defaultEditorProvisioner.apply(devfile);
defaultEditorProvisioner.apply(devfile, contentProvider);

WorkspaceConfigImpl config = new WorkspaceConfigImpl();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
package org.eclipse.che.api.workspace.server.devfile.convert.component.editor;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static org.eclipse.che.api.core.model.workspace.config.Command.PLUGIN_ATTRIBUTE;
import static org.eclipse.che.api.workspace.server.devfile.Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE;
Expand Down Expand Up @@ -66,11 +67,11 @@ public void apply(
EDITOR_COMPONENT_TYPE.equals(editorComponent.getType()),
format("Plugin must have `%s` type", EDITOR_COMPONENT_TYPE));

String editorComponentAlias = editorComponent.getAlias();
String editorId = editorComponent.getId();
String memoryLimit = editorComponent.getMemoryLimit();

workspaceConfig.getAttributes().put(WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, editorId);
final String editorComponentAlias = editorComponent.getAlias();
final String editorId = editorComponent.getId();
final String registryUrl = editorComponent.getRegistryUrl();
final String reference = editorComponent.getReference();
final String memoryLimit = editorComponent.getMemoryLimit();

if (editorComponentAlias != null) {
workspaceConfig
Expand All @@ -80,7 +81,14 @@ public void apply(

final ExtendedPluginFQN fqn;
try {
fqn = fqnParser.parsePluginFQN(editorId);
if (!isNullOrEmpty(reference)) {
workspaceConfig.getAttributes().put(WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, reference);
fqn = fqnParser.evaluateFqn(reference, contentProvider);
} else {
String compositeId = registryUrl != null ? registryUrl + "#" + editorId : editorId;
workspaceConfig.getAttributes().put(WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, compositeId);
fqn = fqnParser.parsePluginFQN(compositeId);
}
} catch (InfrastructureException e) {
throw new DevfileException(e.getMessage(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,27 @@ public void apply(

String workspacePluginsAttribute =
workspaceConfig.getAttributes().get(WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE);
workspaceConfig
.getAttributes()
.put(
WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE,
append(workspacePluginsAttribute, pluginComponent.getId()));

String pluginsAliases =
workspaceConfig.getAttributes().get(PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE);
if (pluginComponent.getAlias() != null) {
workspaceConfig
.getAttributes()
.put(
PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE,
append(pluginsAliases, pluginComponent.getId() + "=" + pluginComponent.getAlias()));
}
final String reference = pluginComponent.getReference();
final String pluginId = pluginComponent.getId();
final String registryUrl = pluginComponent.getRegistryUrl();
final String compositeId = registryUrl != null ? registryUrl + "#" + pluginId : pluginId;
mshaposhnik marked this conversation as resolved.
Show resolved Hide resolved

ExtendedPluginFQN fqn;
try {
fqn = fqnParser.parsePluginFQN(pluginComponent.getId());
if (!isNullOrEmpty(reference)) {
workspaceConfig
.getAttributes()
.put(WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE, append(workspacePluginsAttribute, reference));
fqn = fqnParser.evaluateFqn(reference, contentProvider);
} else {
workspaceConfig
.getAttributes()
.put(
WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE,
append(workspacePluginsAttribute, compositeId));
fqn = fqnParser.parsePluginFQN(compositeId);
}
} catch (InfrastructureException e) {
throw new DevfileException(e.getMessage(), e);
}
Expand Down Expand Up @@ -125,6 +127,16 @@ public void apply(

command.getAttributes().put(PLUGIN_ATTRIBUTE, fqn.getId());
}

String pluginsAliases =
workspaceConfig.getAttributes().get(PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE);
if (pluginComponent.getAlias() != null) {
workspaceConfig
.getAttributes()
.put(
PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE,
append(pluginsAliases, compositeId + "=" + pluginComponent.getAlias()));
}
}

private String append(String source, String toAppend) {
Expand Down
Loading