diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/MachineConfig.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/MachineConfig.java index 34e8e86690..b0212d87da 100644 --- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/MachineConfig.java +++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/config/MachineConfig.java @@ -31,6 +31,9 @@ public interface MachineConfig { /** Returns mapping of references to configurations of servers deployed into machine. */ Map getServers(); + /** Returns environment variables of machine. */ + Map getEnv(); + /** Returns attributes of resources of machine. */ Map getAttributes(); } diff --git a/dashboard/src/app/stacks/stack-details/stack-validation.service.ts b/dashboard/src/app/stacks/stack-details/stack-validation.service.ts index 3a295fc9f5..707bc479ff 100644 --- a/dashboard/src/app/stacks/stack-details/stack-validation.service.ts +++ b/dashboard/src/app/stacks/stack-details/stack-validation.service.ts @@ -198,7 +198,7 @@ export class StackValidationService { */ getMachineValidation(machine: che.IEnvironmentMachine): che.IValidation { let mandatoryKeys: Array = ['attributes']; - let additionalKeys: Array = ['installers', 'servers', 'source']; + let additionalKeys: Array = ['installers', 'servers', 'source', 'env']; let validKeys: Array = mandatoryKeys.concat(additionalKeys); let errors: Array = []; let isValid: boolean = true; diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/workspace/model/MachineConfigImpl.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/workspace/model/MachineConfigImpl.java index 119e464c01..7e119c1338 100644 --- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/workspace/model/MachineConfigImpl.java +++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/workspace/model/MachineConfigImpl.java @@ -21,12 +21,14 @@ import org.eclipse.che.api.core.model.workspace.config.ServerConfig; public class MachineConfigImpl implements MachineConfig { private List installers; + private Map env; private Map attributes; private Map servers; public MachineConfigImpl( List installers, Map servers, + Map env, Map attributes) { if (installers != null) { this.installers = new ArrayList<>(installers); @@ -40,13 +42,16 @@ public class MachineConfigImpl implements MachineConfig { Collectors.toMap( Map.Entry::getKey, entry -> new ServerConfigImpl(entry.getValue()))); } + if (env != null) { + this.env = new HashMap<>(env); + } if (attributes != null) { this.attributes = new HashMap<>(attributes); } } public MachineConfigImpl(MachineConfig machine) { - this(machine.getInstallers(), machine.getServers(), machine.getAttributes()); + this(machine.getInstallers(), machine.getServers(), machine.getEnv(), machine.getAttributes()); } @Override @@ -65,6 +70,14 @@ public class MachineConfigImpl implements MachineConfig { return servers; } + @Override + public Map getEnv() { + if (env == null) { + env = new HashMap<>(); + } + return env; + } + @Override public Map getAttributes() { if (attributes == null) { @@ -83,6 +96,7 @@ public class MachineConfigImpl implements MachineConfig { } final MachineConfigImpl that = (MachineConfigImpl) obj; return getInstallers().equals(that.getInstallers()) + && getEnv().equals(that.getEnv()) && getAttributes().equals(that.getAttributes()) && getServers().equals(that.getServers()); } @@ -91,6 +105,7 @@ public class MachineConfigImpl implements MachineConfig { public int hashCode() { int hash = 7; hash = 31 * hash + getInstallers().hashCode(); + hash = 31 * hash + getEnv().hashCode(); hash = 31 * hash + getAttributes().hashCode(); hash = 31 * hash + getServers().hashCode(); return hash; @@ -101,6 +116,8 @@ public class MachineConfigImpl implements MachineConfig { return "MachineConfigImpl{" + "installers=" + installers + + ", env=" + + env + ", attributes=" + attributes + ", servers=" diff --git a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/EnvironmentParser.java b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/EnvironmentParser.java index fba6d636e0..a5b163d000 100644 --- a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/EnvironmentParser.java +++ b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/EnvironmentParser.java @@ -109,5 +109,7 @@ public class EnvironmentParser { container.getExpose().add(normalizedPort); } container.setExpose(container.getExpose().stream().distinct().collect(Collectors.toList())); + + container.getEnvironment().putAll(machineConfig.getEnv()); } } diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentParser.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentParser.java index ef52ba9edd..4e600c5577 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentParser.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentParser.java @@ -14,6 +14,7 @@ import static java.lang.String.format; import static org.eclipse.che.workspace.infrastructure.openshift.Constants.CHE_POD_NAME_LABEL; import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.EnvVar; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.ObjectMeta; @@ -26,7 +27,9 @@ import io.fabric8.openshift.api.model.Route; import io.fabric8.openshift.client.OpenShiftClient; import java.io.ByteArrayInputStream; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.inject.Inject; import org.eclipse.che.api.core.ValidationException; import org.eclipse.che.api.workspace.server.model.impl.WarningImpl; @@ -163,6 +166,10 @@ public class OpenShiftEnvironmentParser { ServerExposer serverExposer = new ServerExposer(machineName, containerConfig, openShiftEnvironment); serverExposer.expose(machineConfig.getServers()); + + for (Entry envEntry : machineConfig.getEnv().entrySet()) { + putEnv(containerConfig.getEnv(), envEntry.getKey(), envEntry.getValue()); + } } } } @@ -201,4 +208,9 @@ public class OpenShiftEnvironmentParser { throw new ValidationException(errorMessage); } } + + private void putEnv(List envs, String key, String value) { + envs.removeIf(env -> key.equals(env.getName())); + envs.add(new EnvVar(key, value, null)); + } } diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/spi/tck/FactoryDaoTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/spi/tck/FactoryDaoTest.java index 44ea5496a2..7013992e95 100644 --- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/spi/tck/FactoryDaoTest.java +++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/spi/tck/FactoryDaoTest.java @@ -331,6 +331,7 @@ public class FactoryDaoTest { exMachine1.setServers(ImmutableMap.of("ref1", serverConf1, "ref2", serverConf2)); exMachine1.setInstallers(ImmutableList.of("agent5", "agent4")); exMachine1.setAttributes(singletonMap("att1", "val")); + exMachine1.setEnv(singletonMap("CHE_ENV", "value")); final MachineConfigImpl exMachine2 = new MachineConfigImpl(); final ServerConfigImpl serverConf3 = new ServerConfigImpl("2333", "https", "/path1"); @@ -338,12 +339,14 @@ public class FactoryDaoTest { exMachine2.setServers(ImmutableMap.of("ref1", serverConf3, "ref2", serverConf4)); exMachine2.setInstallers(ImmutableList.of("agent2", "agent1")); exMachine2.setAttributes(singletonMap("att1", "val")); + exMachine2.setEnv(singletonMap("CHE_ENV2", "value")); final MachineConfigImpl exMachine3 = new MachineConfigImpl(); final ServerConfigImpl serverConf5 = new ServerConfigImpl("2333", "https", "/path3"); exMachine3.setServers(singletonMap("ref1", serverConf5)); exMachine3.setInstallers(ImmutableList.of("agent6", "agent2")); exMachine3.setAttributes(singletonMap("att1", "val")); + exMachine3.setEnv(singletonMap("CHE_ENV3", "value")); // Environments final RecipeImpl recipe1 = new RecipeImpl(); diff --git a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/MachineConfigDto.java b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/MachineConfigDto.java index 198c0591da..d34ce3cc82 100644 --- a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/MachineConfigDto.java +++ b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/MachineConfigDto.java @@ -37,6 +37,14 @@ public interface MachineConfigDto extends MachineConfig { MachineConfigDto withServers(Map servers); + @Override + @FactoryParameter(obligation = OPTIONAL) + Map getEnv(); + + void setEnv(Map env); + + MachineConfigDto withEnv(Map env); + @Override @FactoryParameter(obligation = OPTIONAL) Map getAttributes(); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/MachineConfigImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/MachineConfigImpl.java index c19d214cf5..0d978a2b07 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/MachineConfigImpl.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/MachineConfigImpl.java @@ -58,6 +58,15 @@ public class MachineConfigImpl implements MachineConfig { @Column(name = "attributes") private Map attributes; + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable( + name = "externalmachine_env", + joinColumns = @JoinColumn(name = "externalmachine_id") + ) + @MapKeyColumn(name = "env_key") + @Column(name = "env_value") + private Map env; + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @JoinColumn(name = "servers_id") @MapKeyColumn(name = "servers_key") @@ -68,6 +77,7 @@ public class MachineConfigImpl implements MachineConfig { public MachineConfigImpl( List installers, Map servers, + Map env, Map attributes) { if (installers != null) { this.installers = new ArrayList<>(installers); @@ -81,13 +91,16 @@ public class MachineConfigImpl implements MachineConfig { Collectors.toMap( Map.Entry::getKey, entry -> new ServerConfigImpl(entry.getValue()))); } + if (env != null) { + this.env = new HashMap<>(env); + } if (attributes != null) { this.attributes = new HashMap<>(attributes); } } public MachineConfigImpl(MachineConfig machine) { - this(machine.getInstallers(), machine.getServers(), machine.getAttributes()); + this(machine.getInstallers(), machine.getServers(), machine.getEnv(), machine.getAttributes()); } @Override @@ -124,6 +137,23 @@ public class MachineConfigImpl implements MachineConfig { return this; } + @Override + public Map getEnv() { + if (env == null) { + env = new HashMap<>(); + } + return env; + } + + public void setEnv(Map env) { + this.env = env; + } + + public MachineConfigImpl withEnv(Map env) { + this.env = env; + return this; + } + @Override public Map getAttributes() { if (attributes == null) { @@ -152,6 +182,7 @@ public class MachineConfigImpl implements MachineConfig { final MachineConfigImpl that = (MachineConfigImpl) obj; return Objects.equals(id, that.id) && getInstallers().equals(that.getInstallers()) + && getEnv().equals(that.getEnv()) && getAttributes().equals(that.getAttributes()) && getServers().equals(that.getServers()); } @@ -161,6 +192,7 @@ public class MachineConfigImpl implements MachineConfig { int hash = 7; hash = 31 * hash + Objects.hashCode(id); hash = 31 * hash + getInstallers().hashCode(); + hash = 31 * hash + getEnv().hashCode(); hash = 31 * hash + getAttributes().hashCode(); hash = 31 * hash + getServers().hashCode(); return hash; @@ -173,6 +205,8 @@ public class MachineConfigImpl implements MachineConfig { + id + ", installers=" + installers + + ", env=" + + env + ", attributes=" + attributes + ", servers=" diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalMachineConfig.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalMachineConfig.java index 483b0edccb..1f82cf978b 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalMachineConfig.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalMachineConfig.java @@ -35,14 +35,27 @@ public class InternalMachineConfig { private final List installers; // set of servers including ones configured by installers private final Map servers; + private final Map env; private final Map attributes; InternalMachineConfig(MachineConfig originalConfig, InstallerRegistry installerRegistry) throws InfrastructureException { - this.installers = new ArrayList<>(); - this.servers = new HashMap<>(originalConfig.getServers()); - this.attributes = new HashMap<>(originalConfig.getAttributes()); + this.servers = new HashMap<>(); + if (originalConfig.getServers() != null) { + this.servers.putAll(originalConfig.getServers()); + } + this.env = new HashMap<>(); + if (originalConfig.getEnv() != null) { + this.env.putAll(originalConfig.getEnv()); + } + + this.attributes = new HashMap<>(); + if (originalConfig.getAttributes() != null) { + this.attributes.putAll(originalConfig.getAttributes()); + } + + this.installers = new ArrayList<>(); initInstallers(originalConfig.getInstallers(), installerRegistry); } @@ -60,6 +73,11 @@ public class InternalMachineConfig { return Collections.unmodifiableList(installers); } + /** Returns unmodifiable map of machine environment variables. */ + public Map getEnv() { + return Collections.unmodifiableMap(env); + } + /** Returns unmodifiable map of machine attributes. */ public Map getAttributes() { return Collections.unmodifiableMap(attributes); diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java index 94590288f1..0d2f1e10d9 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceManagerTest.java @@ -556,6 +556,7 @@ public class WorkspaceManagerTest { new MachineConfigImpl( singletonList("org.eclipse.che.ws-agent"), null, + singletonMap("CHE_ENV", "value"), singletonMap("memoryLimitBytes", "10000")); EnvironmentImpl environment = new EnvironmentImpl( diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java index 80427bece1..bd7f7387e1 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java @@ -916,6 +916,7 @@ public class WorkspaceServiceTest { new MachineConfigImpl( singletonList("org.eclipse.che.ws-agent"), null, + singletonMap("CHE_ENV", "value"), singletonMap("memoryLimitBytes", "10000")); return DtoConverter.asDto( 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 12b23f7b76..902bea0403 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 @@ -385,6 +385,7 @@ public class WorkspaceDaoTest { newMachine.setServers(ImmutableMap.of("ref1", serverConf1, "ref2", serverConf2)); newMachine.setInstallers(ImmutableList.of("agent5", "agent4")); newMachine.setAttributes(singletonMap("att1", "val")); + newMachine.setAttributes(singletonMap("CHE_ENV", "value")); final EnvironmentImpl newEnv = new EnvironmentImpl(); newEnv.setMachines(ImmutableMap.of("new-machine", newMachine)); newEnv.setRecipe(newRecipe); @@ -552,6 +553,7 @@ public class WorkspaceDaoTest { exMachine1.setServers(ImmutableMap.of("ref1", serverConf1, "ref2", serverConf2)); exMachine1.setInstallers(ImmutableList.of("agent5", "agent4")); exMachine1.setAttributes(singletonMap("att1", "val")); + exMachine1.setEnv(ImmutableMap.of("CHE_ENV1", "value", "CHE_ENV2", "value")); final MachineConfigImpl exMachine2 = new MachineConfigImpl(); final ServerConfigImpl serverConf3 = new ServerConfigImpl("2333", "https", "path3"); @@ -559,12 +561,14 @@ public class WorkspaceDaoTest { exMachine2.setServers(ImmutableMap.of("ref1", serverConf3, "ref2", serverConf4)); exMachine2.setInstallers(ImmutableList.of("agent2", "agent1")); exMachine2.setAttributes(singletonMap("att1", "val")); + exMachine2.setEnv(singletonMap("CHE_ENV2", "value")); final MachineConfigImpl exMachine3 = new MachineConfigImpl(); final ServerConfigImpl serverConf5 = new ServerConfigImpl("2333", "https", "path5"); exMachine3.setServers(singletonMap("ref1", serverConf5)); exMachine3.setInstallers(ImmutableList.of("agent6", "agent2")); exMachine3.setAttributes(singletonMap("att1", "val")); + exMachine3.setEnv(singletonMap("CHE_ENV3", "value")); // Environments final RecipeImpl recipe1 = new RecipeImpl(); diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/5.20.0/2__add_machine_env.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/5.20.0/2__add_machine_env.sql new file mode 100644 index 0000000000..5d966d1f8c --- /dev/null +++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/5.20.0/2__add_machine_env.sql @@ -0,0 +1,22 @@ +-- +-- Copyright (c) 2012-2017 Red Hat, Inc. +-- All rights reserved. This program and the accompanying materials +-- are made available under the terms of the Eclipse Public License v1.0 +-- which accompanies this distribution, and is available at +-- http://www.eclipse.org/legal/epl-v10.html +-- +-- Contributors: +-- Red Hat, Inc. - initial API and implementation +-- + +-- Machine env ---------------------------------------------- +CREATE TABLE externalmachine_env ( + externalmachine_id BIGINT, + env_value VARCHAR(255), + env_key VARCHAR(255) +); +--constraints +ALTER TABLE externalmachine_env ADD CONSTRAINT fk_externalmachine_env_externalmachine_id FOREIGN KEY (externalmachine_id) REFERENCES externalmachine (id); +--indexes +CREATE INDEX index_externalmachine_env_externalmachine_id ON externalmachine_env (externalmachine_id); +-------------------------------------------------------------------------------- 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 753e1fcf62..cbd2c2e8fe 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 @@ -118,6 +118,7 @@ public final class TestObjectsFactory { newMachine.setServers(ImmutableMap.of("ref1", serverConf1, "ref2", serverConf2)); newMachine.setInstallers(ImmutableList.of("agent5", "agent4")); newMachine.setAttributes(singletonMap("att1", "val")); + newMachine.setEnv(singletonMap("CHE_ENV", "value")); final EnvironmentImpl newEnv = new EnvironmentImpl(); newEnv.setMachines(ImmutableMap.of("new-machine", newMachine));