diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/Command.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/Command.java index 08e86c19d4..238a6d368d 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/Command.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/Command.java @@ -41,6 +41,15 @@ public interface Command { */ String PLUGIN_ATTRIBUTE = "plugin"; + /** + * An attribute of the command to store the original path to the file that contains the editor + * specific configuration. + */ + String COMMAND_ACTION_REFERENCE_ATTRIBUTE = "actionReference"; + + /** The contents of editor-specific content. */ + String COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE = "actionReferenceContent"; + /** * Returns command name (i.e. 'start tomcat') The name should be unique per user in one workspace, * which means that user may create only one command with the same name in the same workspace diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Action.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Action.java index c794df6162..6550e969d3 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Action.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/devfile/Action.java @@ -15,12 +15,18 @@ public interface Action { /** Returns action type. Is is mandatory. */ String getType(); - /** Returns component to which given action relates. It is mandatory. */ + /** Returns component to which given action relates. */ String getComponent(); - /** Returns the actual action command-line string. It is mandatory. */ + /** Returns the actual action command-line string. */ String getCommand(); /** Returns the working directory where the command should be executed. It is optional. */ String getWorkdir(); + + /** Returns the name of the referenced IDE-specific configuration file. */ + String getReference(); + + /** Returns the content of the referenced IDE-specific configuration file. */ + String getReferenceContent(); } diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/CommandConverter.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/CommandConverter.java index f77560cfca..d383651446 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/CommandConverter.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/CommandConverter.java @@ -12,11 +12,16 @@ package org.eclipse.che.api.devfile.server.convert; import static java.lang.String.format; +import static org.eclipse.che.api.core.model.workspace.config.Command.COMMAND_ACTION_REFERENCE_ATTRIBUTE; +import static org.eclipse.che.api.core.model.workspace.config.Command.COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE; import static org.eclipse.che.api.core.model.workspace.config.Command.WORKING_DIRECTORY_ATTRIBUTE; +import java.io.IOException; import org.eclipse.che.api.core.model.workspace.devfile.Action; import org.eclipse.che.api.core.model.workspace.devfile.Command; import org.eclipse.che.api.devfile.server.Constants; +import org.eclipse.che.api.devfile.server.FileContentProvider; +import org.eclipse.che.api.devfile.server.exception.DevfileException; import org.eclipse.che.api.devfile.server.exception.DevfileFormatException; import org.eclipse.che.api.devfile.server.exception.WorkspaceExportException; import org.eclipse.che.api.workspace.server.model.impl.devfile.ActionImpl; @@ -71,7 +76,7 @@ public class CommandConverter { * @throws DevfileFormatException if devfile command has more than one action */ public org.eclipse.che.api.workspace.server.model.impl.CommandImpl toWorkspaceCommand( - Command devfileCommand) throws DevfileFormatException { + Command devfileCommand, FileContentProvider fileContentProvider) throws DevfileException { if (devfileCommand.getActions().size() != 1) { throw new DevfileFormatException( format("Command `%s` MUST has one and only one action", devfileCommand.getName())); @@ -79,11 +84,12 @@ public class CommandConverter { Action commandAction = devfileCommand.getActions().get(0); - return toWorkspaceCommand(devfileCommand, commandAction); + return toWorkspaceCommand(devfileCommand, commandAction, fileContentProvider); } private org.eclipse.che.api.workspace.server.model.impl.CommandImpl toWorkspaceCommand( - Command devCommand, Action commandAction) { + Command devCommand, Action commandAction, FileContentProvider contentProvider) + throws DevfileException { org.eclipse.che.api.workspace.server.model.impl.CommandImpl command = new org.eclipse.che.api.workspace.server.model.impl.CommandImpl(); command.setName(devCommand.getName()); @@ -94,9 +100,32 @@ public class CommandConverter { command.getAttributes().put(WORKING_DIRECTORY_ATTRIBUTE, commandAction.getWorkdir()); } - command - .getAttributes() - .put(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE, commandAction.getComponent()); + if (commandAction.getComponent() != null) { + command + .getAttributes() + .put(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE, commandAction.getComponent()); + } + + if (commandAction.getReference() != null) { + command.getAttributes().put(COMMAND_ACTION_REFERENCE_ATTRIBUTE, commandAction.getReference()); + } + + if (commandAction.getReferenceContent() != null) { + command + .getAttributes() + .put(COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE, commandAction.getReferenceContent()); + } else if (commandAction.getReference() != null) { + try { + String referenceContent = contentProvider.fetchContent(commandAction.getReference()); + command.getAttributes().put(COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE, referenceContent); + } catch (IOException e) { + throw new DevfileException( + format( + "Failed to fetch content of action from reference %s: %s", + commandAction.getReference(), e.getMessage()), + e); + } + } command.getAttributes().putAll(devCommand.getAttributes()); diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/DevfileConverter.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/DevfileConverter.java index 00976a1e05..beb5ccae7e 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/DevfileConverter.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/DevfileConverter.java @@ -152,7 +152,10 @@ public class DevfileConverter implements DevfileToWorkspaceConfigConverter { config.setName(devfile.getName()); for (Command command : devfile.getCommands()) { - config.getCommands().add(commandConverter.toWorkspaceCommand(command)); + CommandImpl com = commandConverter.toWorkspaceCommand(command, contentProvider); + if (com != null) { + config.getCommands().add(com); + } } // note that component applier modifies commands in workspace config diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/dockerimage/DockerimageComponentToWorkspaceApplier.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/dockerimage/DockerimageComponentToWorkspaceApplier.java index 0f4ba1f491..7880e93aef 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/dockerimage/DockerimageComponentToWorkspaceApplier.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/dockerimage/DockerimageComponentToWorkspaceApplier.java @@ -165,9 +165,9 @@ public class DockerimageComponentToWorkspaceApplier implements ComponentToWorksp .stream() .filter( c -> - c.getAttributes() - .get(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE) - .equals(componentAlias)) + componentAlias != null + && componentAlias.equals( + c.getAttributes().get(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE))) .forEach(c -> c.getAttributes().put(MACHINE_NAME_ATTRIBUTE, machineName)); } diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/editor/EditorComponentToWorkspaceApplier.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/editor/EditorComponentToWorkspaceApplier.java index 88d80ce7f2..80b1df48a8 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/editor/EditorComponentToWorkspaceApplier.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/editor/EditorComponentToWorkspaceApplier.java @@ -94,9 +94,9 @@ public class EditorComponentToWorkspaceApplier implements ComponentToWorkspaceAp .stream() .filter( c -> - c.getAttributes() - .get(COMPONENT_ALIAS_COMMAND_ATTRIBUTE) - .equals(editorComponentAlias)) + editorComponentAlias != null + && editorComponentAlias.equals( + c.getAttributes().get(COMPONENT_ALIAS_COMMAND_ATTRIBUTE))) .forEach(c -> c.getAttributes().put(PLUGIN_ATTRIBUTE, fqn.getId())); } } diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/kubernetes/KubernetesComponentToWorkspaceApplier.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/kubernetes/KubernetesComponentToWorkspaceApplier.java index 7056d1a415..3ae594abca 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/kubernetes/KubernetesComponentToWorkspaceApplier.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/convert/component/kubernetes/KubernetesComponentToWorkspaceApplier.java @@ -159,9 +159,11 @@ public class KubernetesComponentToWorkspaceApplier implements ComponentToWorkspa .stream() .filter( c -> - c.getAttributes() - .get(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE) - .equals(component.getAlias())) + component.getAlias() != null + && component + .getAlias() + .equals( + c.getAttributes().get(Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE))) .collect(toList()); if (componentCommands.isEmpty()) { return; diff --git a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/validator/DevfileIntegrityValidator.java b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/validator/DevfileIntegrityValidator.java index df378c14d0..ebac323363 100644 --- a/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/validator/DevfileIntegrityValidator.java +++ b/wsmaster/che-core-api-devfile/src/main/java/org/eclipse/che/api/devfile/server/validator/DevfileIntegrityValidator.java @@ -188,8 +188,16 @@ public class DevfileIntegrityValidator { throw new DevfileFormatException( format("Multiple actions in command '%s' are not supported yet.", command.getName())); } + Action action = command.getActions().get(0); + if (action.getComponent() == null + && (action.getReference() != null || action.getReferenceContent() != null)) { + // ok, this action contains a reference to the file containing the definition. Such + // actions don't have to have component alias defined. + continue; + } + if (!knownAliases.contains(action.getComponent())) { throw new DevfileFormatException( format( diff --git a/wsmaster/che-core-api-devfile/src/main/resources/schema/devfile.json b/wsmaster/che-core-api-devfile/src/main/resources/schema/devfile.json index 05594c60a5..e5dbfe3c02 100644 --- a/wsmaster/che-core-api-devfile/src/main/resources/schema/devfile.json +++ b/wsmaster/che-core-api-devfile/src/main/resources/schema/devfile.json @@ -516,12 +516,47 @@ "minItems": 1, "maxItems": 1, "items": { - "type": "object", - "required": [ - "type", - "component", - "command" + "oneOf": [ + { + "properties": { + "type": {}, + "component": {}, + "command": {}, + "workdir": {} + }, + "required": [ + "type", + "component", + "command" + ], + "additionalProperties": false + }, + { + "properties": { + "type": {}, + "reference": {}, + "referenceContent": {} + }, + "anyOf": [ + { + "required": [ + "type", + "reference" + ], + "additionalProperties": true + }, + { + "required": [ + "type", + "referenceContent" + ], + "additionalProperties": true + } + ], + "additionalProperties": false + } ], + "type": "object", "properties": { "type": { "description": "Describes action type", @@ -550,6 +585,20 @@ "examples": [ "/projects/spring-petclinic" ] + }, + "reference": { + "type": "string", + "description": "the path relative to the location of the devfile to the configuration file defining one or more actions in the editor-specific format", + "examples": [ + "../ide-config/launch.json" + ] + }, + "referenceContent": { + "type": "string", + "description": "The content of the referenced configuration file that defines one or more actions in the editor-specific format", + "examples": [ + "{\"version\": \"2.0.0\",\n \"tasks\": [\n {\n \"type\": \"typescript\",\n \"tsconfig\": \"tsconfig.json\",\n \"problemMatcher\": [\n \"$tsc\"\n ],\n \"group\": {\n \"kind\": \"build\",\n \"isDefault\": true\n }\n }\n ]}" + ] } } } diff --git a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/CommandConverterTest.java b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/CommandConverterTest.java index 661a79321e..b5928f4c8a 100644 --- a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/CommandConverterTest.java +++ b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/CommandConverterTest.java @@ -16,9 +16,11 @@ import static org.eclipse.che.api.devfile.server.Constants.COMPONENT_ALIAS_COMMA import static org.eclipse.che.api.devfile.server.Constants.EXEC_ACTION_TYPE; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; import com.google.common.collect.ImmutableMap; import java.util.HashMap; +import org.eclipse.che.api.core.model.workspace.config.Command; import org.eclipse.che.api.devfile.server.exception.DevfileFormatException; import org.eclipse.che.api.devfile.server.exception.WorkspaceExportException; import org.eclipse.che.api.workspace.server.model.impl.devfile.ActionImpl; @@ -91,7 +93,7 @@ public class CommandConverterTest { // when org.eclipse.che.api.workspace.server.model.impl.CommandImpl workspaceCommand = - commandConverter.toWorkspaceCommand(devfileCommand); + commandConverter.toWorkspaceCommand(devfileCommand, null); // then assertEquals(workspaceCommand.getName(), "build"); @@ -118,7 +120,7 @@ public class CommandConverterTest { // when org.eclipse.che.api.workspace.server.model.impl.CommandImpl workspaceCommand = - commandConverter.toWorkspaceCommand(devfileCommand); + commandConverter.toWorkspaceCommand(devfileCommand, null); // then assertFalse(workspaceCommand.getAttributes().containsKey(WORKING_DIRECTORY_ATTRIBUTE)); @@ -136,6 +138,70 @@ public class CommandConverterTest { devfileCommand.getActions().add(new ActionImpl()); // when - commandConverter.toWorkspaceCommand(devfileCommand); + commandConverter.toWorkspaceCommand(devfileCommand, null); + } + + @Test + public void shouldAcceptActionWithCommand() throws Exception { + // given + CommandImpl devfileCommand = new CommandImpl(); + devfileCommand.setName("build"); + + ActionImpl action = new ActionImpl(); + action.setType("exec"); + action.setCommand("blah"); + + devfileCommand.getActions().add(action); + + // when + Command command = commandConverter.toWorkspaceCommand(devfileCommand, null); + + // then + assertEquals(command.getCommandLine(), "blah"); + } + + @Test + public void shouldAcceptActionWithReference() throws Exception { + // given + CommandImpl devfileCommand = new CommandImpl(); + devfileCommand.setName("build"); + + ActionImpl action = new ActionImpl(); + action.setType("exec"); + action.setReference("blah"); + + devfileCommand.getActions().add(action); + + // when + Command command = commandConverter.toWorkspaceCommand(devfileCommand, fileURL -> "content"); + + // then + assertNull(command.getCommandLine()); + assertEquals("blah", command.getAttributes().get(Command.COMMAND_ACTION_REFERENCE_ATTRIBUTE)); + assertEquals( + "content", command.getAttributes().get(Command.COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE)); + } + + @Test + public void shouldAcceptActionWithReferenceContent() throws Exception { + // given + CommandImpl devfileCommand = new CommandImpl(); + devfileCommand.setName("build"); + + ActionImpl action = new ActionImpl(); + action.setType("exec"); + action.setReference("blah"); + action.setReferenceContent("content"); + + devfileCommand.getActions().add(action); + + // when + Command command = commandConverter.toWorkspaceCommand(devfileCommand, null); + + // then + assertNull(command.getCommandLine()); + assertEquals("blah", command.getAttributes().get(Command.COMMAND_ACTION_REFERENCE_ATTRIBUTE)); + assertEquals( + "content", command.getAttributes().get(Command.COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE)); } } diff --git a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/DevfileConverterTest.java b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/DevfileConverterTest.java index 133c07f697..c189983fd0 100644 --- a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/DevfileConverterTest.java +++ b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/convert/DevfileConverterTest.java @@ -226,7 +226,7 @@ public class DevfileConverterTest { org.eclipse.che.api.workspace.server.model.impl.CommandImpl workspaceCommand = mock(org.eclipse.che.api.workspace.server.model.impl.CommandImpl.class); - when(commandConverter.toWorkspaceCommand(any())).thenReturn(workspaceCommand); + when(commandConverter.toWorkspaceCommand(any(), any())).thenReturn(workspaceCommand); // when WorkspaceConfigImpl workspaceConfig = diff --git a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/validator/DevfileSchemaValidatorTest.java b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/validator/DevfileSchemaValidatorTest.java index 84953d1235..88ed0dd14d 100644 --- a/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/validator/DevfileSchemaValidatorTest.java +++ b/wsmaster/che-core-api-devfile/src/test/java/org/eclipse/che/api/devfile/server/validator/DevfileSchemaValidatorTest.java @@ -66,14 +66,14 @@ public class DevfileSchemaValidatorTest { @Test(dataProvider = "invalidDevfiles") public void shouldThrowExceptionOnValidationOfNonValidDevfile( - String resourceFilePath, String expectedMessageRegexp) throws Exception { + String resourceFilePath, String expectedMessage) throws Exception { try { schemaValidator.validateBySchema(getResource(resourceFilePath)); } catch (DevfileFormatException e) { assertEquals( e.getMessage(), - format("Devfile schema validation failed. Error: %s", expectedMessageRegexp), - "DevfileFormatException thrown with message that doesn't match expected pattern:"); + format("Devfile schema validation failed. Error: %s", expectedMessage), + "DevfileFormatException thrown with message that doesn't match expected message:"); return; } fail("DevfileFormatException expected to be thrown but is was not"); @@ -121,6 +121,10 @@ public class DevfileSchemaValidatorTest { "command/devfile_multiple_commands_actions.yaml", "(/commands/0/actions):The array must have at most 1 element(s), but actual number is 2." }, + { + "command/devfile_action_without_commandline_and_reference.yaml", + "Exactly one of the following sets of problems must be resolved.: [(/commands/0/actions/0):The object must have a property whose name is \"component\".(/commands/0/actions/0):The object must have a property whose name is \"command\".At least one of the following sets of problems must be resolved.: [(/commands/0/actions/0):The object must have a property whose name is \"reference\".(/commands/0/actions/0):The object must have a property whose name is \"referenceContent\".]]" + }, // cheEditor/chePlugin component model testing { "editor_plugin_component/devfile_editor_component_with_missing_id.yaml", diff --git a/wsmaster/che-core-api-devfile/src/test/resources/schema_test/command/devfile_action_without_commandline_and_reference.yaml b/wsmaster/che-core-api-devfile/src/test/resources/schema_test/command/devfile_action_without_commandline_and_reference.yaml new file mode 100644 index 0000000000..b8073a9639 --- /dev/null +++ b/wsmaster/che-core-api-devfile/src/test/resources/schema_test/command/devfile_action_without_commandline_and_reference.yaml @@ -0,0 +1,23 @@ +# +# Copyright (c) 2012-2018 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation +# + +--- +specVersion: 0.0.1 +name: petclinic-dev-environment +components: + - alias: theia + type: cheEditor + id: eclipse/chetheia/0.0.3 +commands: + - name: build + actions: + - type: vscode-task diff --git a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/DevfileActionDto.java b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/DevfileActionDto.java index 87a9f512fa..665043ca7e 100644 --- a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/DevfileActionDto.java +++ b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/devfile/DevfileActionDto.java @@ -44,4 +44,18 @@ public interface DevfileActionDto extends Action { void setWorkdir(String workdir); DevfileActionDto withWorkdir(String workdir); + + @Override + String getReference(); + + void setReference(String reference); + + DevfileActionDto withReference(String reference); + + @Override + String getReferenceContent(); + + void setReferenceContent(String referenceContent); + + DevfileActionDto withReferenceContent(String referenceContent); } diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java index 2d535d4b09..3b2fb81f04 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java @@ -78,8 +78,10 @@ public class WorkspaceValidator { "Workspace %s contains command with null or empty name", config.getName()); check( - !isNullOrEmpty(command.getCommandLine()), - "Command line required for command '%s' in workspace '%s'", + !isNullOrEmpty(command.getCommandLine()) + || !isNullOrEmpty( + command.getAttributes().get(Command.COMMAND_ACTION_REFERENCE_CONTENT_ATTRIBUTE)), + "Command line or content required for command '%s' in workspace '%s'.", command.getName(), config.getName()); } diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ActionImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ActionImpl.java index 9079b491b2..98f930c633 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ActionImpl.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/devfile/ActionImpl.java @@ -41,17 +41,37 @@ public class ActionImpl implements Action { @Column(name = "workdir") private String workdir; + @Column(name = "reference") + private String reference; + + @Column(name = "reference_content") + private String referenceContent; + public ActionImpl() {} - public ActionImpl(String type, String component, String command, String workdir) { + public ActionImpl( + String type, + String component, + String command, + String workdir, + String reference, + String referenceContent) { this.type = type; this.component = component; this.command = command; this.workdir = workdir; + this.reference = reference; + this.referenceContent = referenceContent; } public ActionImpl(Action action) { - this(action.getType(), action.getComponent(), action.getCommand(), action.getWorkdir()); + this( + action.getType(), + action.getComponent(), + action.getCommand(), + action.getWorkdir(), + action.getReference(), + action.getReferenceContent()); } @Override @@ -90,6 +110,24 @@ public class ActionImpl implements Action { this.workdir = workdir; } + @Override + public String getReference() { + return reference; + } + + public void setReference(String reference) { + this.reference = reference; + } + + @Override + public String getReferenceContent() { + return referenceContent; + } + + public void setReferenceContent(String referenceContent) { + this.referenceContent = referenceContent; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java index 569a65d920..49fa2b2889 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java @@ -240,7 +240,8 @@ public class WorkspaceValidatorTest { @Test( expectedExceptions = ValidationException.class, - expectedExceptionsMessageRegExp = "Command line required for command '.*'") + expectedExceptionsMessageRegExp = + "Command line or content required for command '.*' in workspace '.*'\\.") public void shouldFailValidationIfCommandLineIsNull() throws Exception { final WorkspaceConfigDto config = createConfig(); config.getCommands().get(0).withCommandLine(null); @@ -250,7 +251,8 @@ public class WorkspaceValidatorTest { @Test( expectedExceptions = ValidationException.class, - expectedExceptionsMessageRegExp = "Command line required for command '.*'") + expectedExceptionsMessageRegExp = + "Command line or content required for command '.*' in workspace '.*'\\.") public void shouldFailValidationIfCommandLineIsEmpty() throws Exception { final WorkspaceConfigDto config = createConfig(); config.getCommands().get(0).withCommandLine(""); diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java index d4b8deda2c..750d0a9d3c 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java @@ -550,8 +550,10 @@ public class WorkspaceDaoTest { // Remove an existing command workspace.getDevfile().getCommands().remove(1); - ActionImpl action3 = new ActionImpl("exec3", "component3", "run.sh", "/home/user/3"); - ActionImpl action4 = new ActionImpl("exec4", "component4", "run.sh", "/home/user/4"); + ActionImpl action3 = + new ActionImpl("exec3", "component3", "run.sh", "/home/user/3", null, null); + ActionImpl action4 = + new ActionImpl("exec4", "component4", "run.sh", "/home/user/4", null, null); // Add a new command final org.eclipse.che.api.workspace.server.model.impl.devfile.CommandImpl newCmd = new org.eclipse.che.api.workspace.server.model.impl.devfile.CommandImpl( @@ -856,8 +858,10 @@ public class WorkspaceDaoTest { new SourceImpl("type2", "http://location", "branch2", "point2", "tag2", "commit2"); ProjectImpl project2 = new ProjectImpl("project2", source2, "path2"); - ActionImpl action1 = new ActionImpl("exec1", "component1", "run.sh", "/home/user/1"); - ActionImpl action2 = new ActionImpl("exec2", "component2", "run.sh", "/home/user/2"); + ActionImpl action1 = + new ActionImpl("exec1", "component1", "run.sh", "/home/user/1", null, null); + ActionImpl action2 = + new ActionImpl("exec2", "component2", "run.sh", "/home/user/2", null, null); org.eclipse.che.api.workspace.server.model.impl.devfile.CommandImpl command1 = new org.eclipse.che.api.workspace.server.model.impl.devfile.CommandImpl( diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/1__devfile_command_reference.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/1__devfile_command_reference.sql new file mode 100644 index 0000000000..a644b4af0b --- /dev/null +++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/1__devfile_command_reference.sql @@ -0,0 +1,17 @@ +-- +-- Copyright (c) 2012-2019 Red Hat, Inc. +-- This program and the accompanying materials are made +-- available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Contributors: +-- Red Hat, Inc. - initial API and implementation +-- + +-- devfile command action references +ALTER TABLE devfile_action ALTER COLUMN component DROP NOT NULL; +ALTER TABLE devfile_action ALTER COLUMN command DROP NOT NULL; +ALTER TABLE devfile_action ADD COLUMN reference TEXT; +ALTER TABLE devfile_action ADD COLUMN reference_content TEXT; diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/mysql/1__devfile_command_reference.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/mysql/1__devfile_command_reference.sql new file mode 100644 index 0000000000..f620134d37 --- /dev/null +++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/7.0.0-beta5.0/mysql/1__devfile_command_reference.sql @@ -0,0 +1,17 @@ +-- +-- Copyright (c) 2012-2019 Red Hat, Inc. +-- This program and the accompanying materials are made +-- available under the terms of the Eclipse Public License 2.0 +-- which is available at https://www.eclipse.org/legal/epl-2.0/ +-- +-- SPDX-License-Identifier: EPL-2.0 +-- +-- Contributors: +-- Red Hat, Inc. - initial API and implementation +-- + +-- devfile command action references +ALTER TABLE devfile_action MODIFY COLUMN component VARCHAR(255) NULL DEFAULT NULL; +ALTER TABLE devfile_action MODIFY COLUMN command TEXT NULL DEFAULT NULL; +ALTER TABLE devfile_action ADD COLUMN reference TEXT; +ALTER TABLE devfile_action ADD COLUMN reference_content TEXT; diff --git a/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/TestObjectsFactory.java b/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/TestObjectsFactory.java index 5c7b690fa4..c0f4d1a288 100644 --- a/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/TestObjectsFactory.java +++ b/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/TestObjectsFactory.java @@ -146,7 +146,7 @@ public final class TestObjectsFactory { } private static ActionImpl createAction() { - return new ActionImpl("exec", "component", "run.sh", "/home/user"); + return new ActionImpl("exec", "component", "run.sh", "/home/user", null, null); } private static ProjectImpl createDevfileProject(String name) {