CHE-6124: Do not publish exposed ports in Docker machines
Publish port in Docker machines only in case there is a server in the workspace config that represents the port. Refactor OpenShift infrastructure code. Refactor Docker infrastructure code. Add constant of memory attribute and reuse it everywhere it is hardcoded. Add constant for installer environment attribute and reuse it everywhere it is hardcoded. Add machine memory attribute validation to workspace validation. Move provisioning of servers, environment variables from infrastructure implementations to runtime SPI abstract level. Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>6.19.x
parent
a8aae87905
commit
cd1301d115
|
|
@ -19,6 +19,14 @@ import java.util.Map;
|
|||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public interface MachineConfig {
|
||||
|
||||
/**
|
||||
* Name of the attribute from {@link #getAttributes()} which if present sets memory limit of the
|
||||
* machine in bytes. If memory limit is set in environment specific recipe this attribute should
|
||||
* override value from recipe.
|
||||
*/
|
||||
String MEMORY_LIMIT_ATTRIBUTE = "memoryLimitBytes";
|
||||
|
||||
/**
|
||||
* Returns configured installers.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ teardown() {
|
|||
check_che_state
|
||||
#create a workspace
|
||||
|
||||
ws_create=$(curl 'http://'${ip_address}':8080/api/workspace?namespace=che&attribute=stackId:java-default' -H 'Content-Type: application/json;charset=UTF-8' -H 'Accept: application/json, text/plain, */*' --data-binary '{"defaultEnv":"wksp-1p0b","environments":{"wksp-1p0b":{"recipe":{"location":"eclipse/ubuntu_jdk8","type":"dockerimage"},"machines":{"dev-machine":{"servers":{},"agents":["org.eclipse.che.exec","org.eclipse.che.terminal","org.eclipse.che.ws-agent","org.eclipse.che.ssh"],"attributes":{"memoryLimitBytes":"2147483648"}}}}},"projects":[],"commands":[{"commandLine":"mvn clean install -f ${current.project.path}","name":"build","type":"mvn","attributes":{"goal":"Build","previewUrl":""}}],"name":"backup-restore","links":[]}' --compressed)
|
||||
ws_create=$(curl 'http://'${ip_address}':8080/api/workspace?namespace=che&attribute=stackId:java-default' -H 'Content-Type: application/json;charset=UTF-8' -H 'Accept: application/json, text/plain, */*' --data-binary '{"defaultEnv":"wksp-1p0b","environments":{"wksp-1p0b":{"recipe":{"location":"eclipse/ubuntu_jdk8","type":"dockerimage"},"machines":{"dev-machine":{"servers":{},"installers":["org.eclipse.che.exec","org.eclipse.che.terminal","org.eclipse.che.ws-agent","org.eclipse.che.ssh"],"attributes":{"memoryLimitBytes":"2147483648"}}}}},"projects":[],"commands":[{"commandLine":"mvn clean install -f ${current.project.path}","name":"build","type":"mvn","attributes":{"goal":"Build","previewUrl":""}}],"name":"backup-restore","links":[]}' --compressed)
|
||||
[[ "$ws_create" == *"created"* ]]
|
||||
[[ "$ws_create" == *"STOPPED"* ]]
|
||||
#stop che
|
||||
|
|
|
|||
|
|
@ -63,10 +63,10 @@ export class Workspace {
|
|||
*/
|
||||
getWorkspaceConfigDto(createWorkspaceConfig:CreateWorkspaceConfig) : org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto {
|
||||
let devMachine : org.eclipse.che.api.workspace.shared.dto.ExtendedMachineDto = new org.eclipse.che.api.workspace.shared.dto.ExtendedMachineDtoImpl();
|
||||
devMachine.getAgents().push("org.eclipse.che.exec");
|
||||
devMachine.getAgents().push("org.eclipse.che.terminal");
|
||||
devMachine.getAgents().push("org.eclipse.che.ws-agent");
|
||||
devMachine.getAgents().push("org.eclipse.che.ssh");
|
||||
devMachine.getInstallers().push("org.eclipse.che.exec");
|
||||
devMachine.getInstallers().push("org.eclipse.che.terminal");
|
||||
devMachine.getInstallers().push("org.eclipse.che.ws-agent");
|
||||
devMachine.getInstallers().push("org.eclipse.che.ssh");
|
||||
devMachine.getAttributes().set("memoryLimitBytes", "2147483648");
|
||||
|
||||
let defaultEnvironment : org.eclipse.che.api.workspace.shared.dto.EnvironmentDto = new org.eclipse.che.api.workspace.shared.dto.EnvironmentDtoImpl();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export class GetSshDataAction {
|
|||
|
||||
// Check ssh agent is there
|
||||
let defaultEnv:string = workspaceDto.getConfig().getDefaultEnv();
|
||||
let agents:Array<string> = workspaceDto.getConfig().getEnvironments().get(defaultEnv).getMachines().get("dev-machine").getAgents();
|
||||
let agents:Array<string> = workspaceDto.getConfig().getEnvironments().get(defaultEnv).getMachines().get("dev-machine").getInstallers();
|
||||
|
||||
if (agents.indexOf('org.eclipse.che.ssh') === -1) {
|
||||
return Promise.reject("The SSH agent (org.eclipse.che.ssh) has been disabled for this workspace.")
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export class WorkspaceSshAction {
|
|||
throw new Error("Unable to find a machine named " + this.machineName + " in the workspace '" + this.workspaceName)
|
||||
}
|
||||
|
||||
let agents:Array<string> = machineConfig.getAgents();
|
||||
let agents:Array<string> = machineConfig.getInstallers();
|
||||
|
||||
if (agents.indexOf('org.eclipse.che.ssh') === -1) {
|
||||
return Promise.reject("The SSH agent (org.eclipse.che.ssh) has been disabled for this workspace.")
|
||||
|
|
|
|||
|
|
@ -830,7 +830,7 @@ setupSSHKeys(workspaceDto: org.eclipse.che.api.workspace.shared.dto.WorkspaceDto
|
|||
|
||||
// Check ssh agent is there
|
||||
let defaultEnv : string = workspaceDto.getConfig().getDefaultEnv();
|
||||
let agents : Array<string> = workspaceDto.getConfig().getEnvironments().get(defaultEnv).getMachines().get("dev-machine").getAgents();
|
||||
let agents : Array<string> = workspaceDto.getConfig().getEnvironments().get(defaultEnv).getMachines().get("dev-machine").getInstallers();
|
||||
|
||||
if (agents.indexOf('org.eclipse.che.ssh') === - 1) {
|
||||
return Promise.reject("The SSH agent (org.eclipse.che.ssh) has been disabled for this workspace.")
|
||||
|
|
|
|||
|
|
@ -86,10 +86,6 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-installer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-installer-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
|
|
|
|||
|
|
@ -463,8 +463,6 @@ public class DockerMachineStarter {
|
|||
hostConfig.setBinds(bindMountVolumes.toArray(new String[bindMountVolumes.size()]));
|
||||
config.setVolumes(nonBindMountVolumes);
|
||||
|
||||
config.getHostConfig().withPublishAllPorts(true);
|
||||
|
||||
setNonExitingContainerCommandIfNeeded(config);
|
||||
|
||||
return docker
|
||||
|
|
@ -479,12 +477,15 @@ public class DockerMachineStarter {
|
|||
Map<String, PortBinding[]> portsBindings = Maps.newHashMapWithExpectedSize(portsSpecs.size());
|
||||
for (String portSpec : portsSpecs) {
|
||||
String[] portMapping = portSpec.split(":");
|
||||
if (portMapping.length != 2) {
|
||||
if (portMapping.length == 1) {
|
||||
portsBindings.put(portMapping[0], new PortBinding[] {new PortBinding()});
|
||||
} else if (portMapping.length == 2) {
|
||||
portsBindings.put(
|
||||
portMapping[0], new PortBinding[] {new PortBinding().withHostPort(portMapping[1])});
|
||||
} else {
|
||||
throw new InternalInfrastructureException(
|
||||
format("Invalid port specification '%s' found machine '%s'", portsSpecs, machineName));
|
||||
}
|
||||
portsBindings.put(
|
||||
portMapping[0], new PortBinding[] {new PortBinding().withHostPort(portMapping[1])});
|
||||
}
|
||||
return portsBindings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,9 @@ import static org.eclipse.che.workspace.infrastructure.docker.ArgumentsValidator
|
|||
|
||||
import com.google.common.base.Joiner;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.core.ValidationException;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Environment;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment.InternalRecipe;
|
||||
|
|
@ -75,41 +73,19 @@ public class EnvironmentParser {
|
|||
|
||||
InternalMachineConfig machineConfig = environment.getMachines().get(entry.getKey());
|
||||
if (machineConfig != null) {
|
||||
normalizeMachine(entry.getKey(), entry.getValue(), machineConfig);
|
||||
entry
|
||||
.getValue()
|
||||
.setExpose(
|
||||
entry
|
||||
.getValue()
|
||||
.getExpose()
|
||||
.stream()
|
||||
.map(expose -> expose.contains("/") ? expose : expose + "/tcp")
|
||||
.distinct()
|
||||
.collect(toList()));
|
||||
}
|
||||
}
|
||||
|
||||
return dockerEnvironment;
|
||||
}
|
||||
|
||||
private void normalizeMachine(
|
||||
String name, DockerContainerConfig container, InternalMachineConfig machineConfig)
|
||||
throws ValidationException {
|
||||
if (machineConfig.getAttributes().containsKey("memoryLimitBytes")) {
|
||||
try {
|
||||
container.setMemLimit(
|
||||
Long.parseLong(machineConfig.getAttributes().get("memoryLimitBytes")));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ValidationException(
|
||||
format("Value of attribute 'memoryLimitBytes' of machine '%s' is illegal", name));
|
||||
}
|
||||
}
|
||||
container.setExpose(
|
||||
container
|
||||
.getExpose()
|
||||
.stream()
|
||||
.map(expose -> expose.contains("/") ? expose : expose + "/tcp")
|
||||
.collect(toList()));
|
||||
for (ServerConfig serverConfig : machineConfig.getServers().values()) {
|
||||
String normalizedPort =
|
||||
serverConfig.getPort().contains("/")
|
||||
? serverConfig.getPort()
|
||||
: serverConfig.getPort() + "/tcp";
|
||||
|
||||
container.getExpose().add(normalizedPort);
|
||||
}
|
||||
container.setExpose(container.getExpose().stream().distinct().collect(Collectors.toList()));
|
||||
|
||||
container.getEnvironment().putAll(machineConfig.getEnv());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
package org.eclipse.che.workspace.infrastructure.docker.environment;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.che.workspace.infrastructure.docker.ArgumentsValidator.checkArgument;
|
||||
|
||||
|
|
@ -233,23 +232,6 @@ public class EnvironmentValidator {
|
|||
|
||||
private void validateExtendedMachine(InternalMachineConfig machineConfig, String machineName)
|
||||
throws ValidationException {
|
||||
if (machineConfig.getAttributes() != null
|
||||
&& machineConfig.getAttributes().get("memoryLimitBytes") != null) {
|
||||
|
||||
try {
|
||||
long memoryLimitBytes =
|
||||
Long.parseLong(machineConfig.getAttributes().get("memoryLimitBytes"));
|
||||
checkArgument(
|
||||
memoryLimitBytes > 0,
|
||||
"Value of attribute 'memoryLimitBytes' of machine '%s' in environment is illegal",
|
||||
machineName);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ValidationException(
|
||||
format(
|
||||
"Value of attribute 'memoryLimitBytes' of machine '%s' in environment is illegal",
|
||||
machineName));
|
||||
}
|
||||
}
|
||||
|
||||
if (machineConfig.getServers() != null) {
|
||||
for (Map.Entry<String, ? extends ServerConfig> serverEntry :
|
||||
|
|
|
|||
|
|
@ -17,12 +17,15 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.InfrastructureProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.dod.DockerApiHostEnvVariableProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersBinariesVolumeProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.WsAgentServerConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.projects.ProjectsVolumeProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.ContainerSystemSettingsProvisionersApplier;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.labels.LabelsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.env.EnvVarsConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.labels.RuntimeLabelsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.memory.MemoryAttributeConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.server.ServersConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.server.ToolingServersEnvVarsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.snapshot.ExcludeFoldersFromSnapshotProvisioner;
|
||||
|
||||
|
|
@ -34,34 +37,44 @@ import org.eclipse.che.workspace.infrastructure.docker.provisioner.snapshot.Excl
|
|||
*/
|
||||
@Singleton
|
||||
public class LocalCheInfrastructureProvisioner implements InfrastructureProvisioner {
|
||||
private final ContainerSystemSettingsProvisionersApplier settingsProvisioners;
|
||||
private final ExcludeFoldersFromSnapshotProvisioner snapshotProvisioner;
|
||||
|
||||
private final ContainerSystemSettingsProvisionersApplier dockerSettingsProvisioners;
|
||||
private final ExcludeFoldersFromSnapshotProvisioner snapshotVolumeProvisioner;
|
||||
private final ProjectsVolumeProvisioner projectsVolumeProvisioner;
|
||||
private final LocalInstallersConfigProvisioner installerConfigProvisioner;
|
||||
private final LabelsProvisioner labelsProvisioner;
|
||||
private final LocalInstallersBinariesVolumeProvisioner installersBinariesVolumeProvisioner;
|
||||
private final RuntimeLabelsProvisioner runtimeLabelsProvisioner;
|
||||
private final DockerApiHostEnvVariableProvisioner dockerApiEnvProvisioner;
|
||||
private final ToolingServersEnvVarsProvisioner toolingServersEnvVarsProvisioner;
|
||||
private final ToolingServersEnvVarsProvisioner agentsServersEnvVarsProvisioner;
|
||||
private final WsAgentServerConfigProvisioner wsAgentServerConfigProvisioner;
|
||||
private final ServersConverter serversConverter;
|
||||
private final EnvVarsConverter envVarsConverter;
|
||||
private final MemoryAttributeConverter memoryAttributeConverter;
|
||||
|
||||
@Inject
|
||||
public LocalCheInfrastructureProvisioner(
|
||||
ContainerSystemSettingsProvisionersApplier settingsProvisioners,
|
||||
ExcludeFoldersFromSnapshotProvisioner snapshotProvisioner,
|
||||
ContainerSystemSettingsProvisionersApplier dockerSettingsProvisioners,
|
||||
ExcludeFoldersFromSnapshotProvisioner snapshotVolumeProvisioner,
|
||||
ProjectsVolumeProvisioner projectsVolumeProvisioner,
|
||||
LocalInstallersConfigProvisioner installerConfigProvisioner,
|
||||
LabelsProvisioner labelsProvisioner,
|
||||
LocalInstallersBinariesVolumeProvisioner installersBinariesVolumeProvisioner,
|
||||
RuntimeLabelsProvisioner runtimeLabelsProvisioner,
|
||||
DockerApiHostEnvVariableProvisioner dockerApiEnvProvisioner,
|
||||
ToolingServersEnvVarsProvisioner toolingServersEnvVarsProvisioner,
|
||||
WsAgentServerConfigProvisioner wsAgentServerConfigProvisioner) {
|
||||
ToolingServersEnvVarsProvisioner agentsServersEnvVarsProvisioner,
|
||||
WsAgentServerConfigProvisioner wsAgentServerConfigProvisioner,
|
||||
ServersConverter serversConverter,
|
||||
EnvVarsConverter envVarsConverter,
|
||||
MemoryAttributeConverter memoryAttributeConverter) {
|
||||
|
||||
this.settingsProvisioners = settingsProvisioners;
|
||||
this.snapshotProvisioner = snapshotProvisioner;
|
||||
this.dockerSettingsProvisioners = dockerSettingsProvisioners;
|
||||
this.snapshotVolumeProvisioner = snapshotVolumeProvisioner;
|
||||
this.projectsVolumeProvisioner = projectsVolumeProvisioner;
|
||||
this.installerConfigProvisioner = installerConfigProvisioner;
|
||||
this.labelsProvisioner = labelsProvisioner;
|
||||
this.installersBinariesVolumeProvisioner = installersBinariesVolumeProvisioner;
|
||||
this.runtimeLabelsProvisioner = runtimeLabelsProvisioner;
|
||||
this.dockerApiEnvProvisioner = dockerApiEnvProvisioner;
|
||||
this.toolingServersEnvVarsProvisioner = toolingServersEnvVarsProvisioner;
|
||||
this.agentsServersEnvVarsProvisioner = agentsServersEnvVarsProvisioner;
|
||||
this.wsAgentServerConfigProvisioner = wsAgentServerConfigProvisioner;
|
||||
this.serversConverter = serversConverter;
|
||||
this.envVarsConverter = envVarsConverter;
|
||||
this.memoryAttributeConverter = memoryAttributeConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -69,13 +82,20 @@ public class LocalCheInfrastructureProvisioner implements InfrastructureProvisio
|
|||
InternalEnvironment envConfig, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
snapshotProvisioner.provision(envConfig, internalEnv, identity);
|
||||
installerConfigProvisioner.provision(envConfig, internalEnv, identity);
|
||||
// 1 stage - add Che business logic items to Che model env
|
||||
// 2 stage - converting Che model env to docker env
|
||||
serversConverter.provision(envConfig, internalEnv, identity);
|
||||
envVarsConverter.provision(envConfig, internalEnv, identity);
|
||||
memoryAttributeConverter.provision(envConfig, internalEnv, identity);
|
||||
// 3 stage - add docker env items
|
||||
runtimeLabelsProvisioner.provision(envConfig, internalEnv, identity);
|
||||
snapshotVolumeProvisioner.provision(envConfig, internalEnv, identity);
|
||||
installersBinariesVolumeProvisioner.provision(envConfig, internalEnv, identity);
|
||||
projectsVolumeProvisioner.provision(envConfig, internalEnv, identity);
|
||||
settingsProvisioners.provision(envConfig, internalEnv, identity);
|
||||
labelsProvisioner.provision(envConfig, internalEnv, identity);
|
||||
dockerApiEnvProvisioner.provision(envConfig, internalEnv, identity);
|
||||
toolingServersEnvVarsProvisioner.provision(envConfig, internalEnv, identity);
|
||||
wsAgentServerConfigProvisioner.provision(envConfig, internalEnv, identity);
|
||||
dockerSettingsProvisioners.provision(envConfig, internalEnv, identity);
|
||||
dockerApiEnvProvisioner.provision(envConfig, internalEnv, identity);
|
||||
// TODO move to abstract code
|
||||
agentsServersEnvVarsProvisioner.provision(envConfig, internalEnv, identity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.local;
|
||||
|
||||
import static org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersConfigProvisioner.LOCAL_INSTALLERS_PROVISIONERS;
|
||||
import static org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersBinariesVolumeProvisioner.LOCAL_INSTALLERS_PROVISIONERS;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
|
|
|
|||
|
|
@ -18,27 +18,23 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.ConfigurationProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.installer.InstallerConfigApplier;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.installer.InstallersConfigProvisioner;
|
||||
|
||||
/**
|
||||
* Provisions an environment with configuration and binaries that comes from installers of machines
|
||||
* in the environment.
|
||||
* Provisions an environment with binaries that comes from installers of machines in the
|
||||
* environment.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class LocalInstallersConfigProvisioner extends InstallersConfigProvisioner {
|
||||
public class LocalInstallersBinariesVolumeProvisioner implements ConfigurationProvisioner {
|
||||
public static final String LOCAL_INSTALLERS_PROVISIONERS =
|
||||
"infrastructure.docker.local_installers_provisioners";
|
||||
|
||||
private final Set<ConfigurationProvisioner> localInstallerProvisioners;
|
||||
|
||||
@Inject
|
||||
public LocalInstallersConfigProvisioner(
|
||||
InstallerConfigApplier installerConfigApplier,
|
||||
public LocalInstallersBinariesVolumeProvisioner(
|
||||
@Named(LOCAL_INSTALLERS_PROVISIONERS)
|
||||
Set<ConfigurationProvisioner> localInstallerProvisioners) {
|
||||
super(installerConfigApplier);
|
||||
this.localInstallerProvisioners = localInstallerProvisioners;
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +43,6 @@ public class LocalInstallersConfigProvisioner extends InstallersConfigProvisione
|
|||
InternalEnvironment envConfig, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
super.provision(envConfig, internalEnv, identity);
|
||||
for (ConfigurationProvisioner infrastructureProvisioner : localInstallerProvisioners) {
|
||||
infrastructureProvisioner.provision(envConfig, internalEnv, identity);
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.env;
|
||||
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.InfrastructureProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
|
||||
/**
|
||||
* Converts environment variables in {@link MachineConfig} to Docker environment variables.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class EnvVarsConverter implements InfrastructureProvisioner {
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
environment
|
||||
.getMachines()
|
||||
.forEach(
|
||||
(machineName, machineConfig) ->
|
||||
internalEnv
|
||||
.getContainers()
|
||||
.get(machineName)
|
||||
.getEnvironment()
|
||||
.putAll(machineConfig.getEnv()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.installer;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.workspace.infrastructure.docker.provisioner.installer.InstallerConfigApplier.PROPERTIES.ENVIRONMENT;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.installer.server.exception.InstallerException;
|
||||
import org.eclipse.che.api.installer.shared.model.Installer;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.Labels;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerContainerConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Applies docker specific properties of the installers to {@link DockerContainerConfig} or {@link
|
||||
* DockerEnvironment}. Dependencies between installers are respected. This class must be called
|
||||
* before machines represented by {@link DockerContainerConfig} is started, otherwise changing
|
||||
* configuration has no effect. </br> The list of supported properties are:
|
||||
* <li>environment The {@code environment} property contains command separated environment variables
|
||||
* to set respecting the following format: "name=value".
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
* @author Alexander Garagatyi
|
||||
* @see Installer#getProperties()
|
||||
* @see DockerContainerConfig#getEnvironment()
|
||||
* @see DockerContainerConfig#getPorts()
|
||||
* @see DockerContainerConfig#getLabels()
|
||||
*/
|
||||
public class InstallerConfigApplier {
|
||||
private static final Logger LOG = getLogger(InstallerConfigApplier.class);
|
||||
|
||||
/**
|
||||
* Applies docker specific properties to an environment of machines.
|
||||
*
|
||||
* @param envConfig environment config with the list of installers that should be injected into
|
||||
* machine
|
||||
* @param dockerEnvironment affected environment of machines
|
||||
* @throws InstallerException if any error occurs
|
||||
*/
|
||||
public void apply(InternalEnvironment envConfig, DockerEnvironment dockerEnvironment)
|
||||
throws InstallerException {
|
||||
for (Map.Entry<String, InternalMachineConfig> machineEntry :
|
||||
envConfig.getMachines().entrySet()) {
|
||||
String machineName = machineEntry.getKey();
|
||||
InternalMachineConfig machineConf = machineEntry.getValue();
|
||||
DockerContainerConfig dockerContainer = dockerEnvironment.getContainers().get(machineName);
|
||||
|
||||
apply(machineConf, dockerContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies docker specific properties to a machine.
|
||||
*
|
||||
* @param machineConf machine config with the list of installer that should be injected into
|
||||
* machine
|
||||
* @param machine affected machine
|
||||
* @throws InstallerException if any error occurs
|
||||
*/
|
||||
public void apply(@Nullable InternalMachineConfig machineConf, DockerContainerConfig machine)
|
||||
throws InstallerException {
|
||||
if (machineConf != null) {
|
||||
for (Installer installer : machineConf.getInstallers()) {
|
||||
addEnv(machine, installer.getProperties());
|
||||
addExposedPorts(machine, installer.getServers());
|
||||
addLabels(machine, installer.getServers());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addLabels(
|
||||
DockerContainerConfig container, Map<String, ? extends ServerConfig> servers) {
|
||||
container.getLabels().putAll(Labels.newSerializer().servers(servers).labels());
|
||||
}
|
||||
|
||||
private void addEnv(DockerContainerConfig container, Map<String, String> properties) {
|
||||
String environment = properties.get(ENVIRONMENT.toString());
|
||||
if (isNullOrEmpty(environment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> newEnv = new HashMap<>();
|
||||
if (container.getEnvironment() != null) {
|
||||
newEnv.putAll(container.getEnvironment());
|
||||
}
|
||||
|
||||
for (String env : environment.split(",")) {
|
||||
String[] items = env.split("=");
|
||||
if (items.length != 2) {
|
||||
LOG.warn(format("Illegal environment variable '%s' format", env));
|
||||
continue;
|
||||
}
|
||||
String var = items[0];
|
||||
String name = items[1];
|
||||
|
||||
newEnv.put(var, name);
|
||||
}
|
||||
|
||||
container.setEnvironment(newEnv);
|
||||
}
|
||||
|
||||
private void addExposedPorts(
|
||||
DockerContainerConfig container, Map<String, ? extends ServerConfig> servers) {
|
||||
for (ServerConfig server : servers.values()) {
|
||||
container.getExpose().add(server.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
public enum PROPERTIES {
|
||||
ENVIRONMENT("environment");
|
||||
|
||||
private final String value;
|
||||
|
||||
PROPERTIES(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.installer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.installer.server.exception.InstallerException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
* Provisions an environment with configuration that comes from installers of machines in the
|
||||
* environment.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class InstallersConfigProvisioner implements ConfigurationProvisioner {
|
||||
private final InstallerConfigApplier installerConfigApplier;
|
||||
|
||||
@Inject
|
||||
public InstallersConfigProvisioner(InstallerConfigApplier installerConfigApplier) {
|
||||
this.installerConfigApplier = installerConfigApplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment envConfig, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
try {
|
||||
installerConfigApplier.apply(envConfig, internalEnv);
|
||||
} catch (InstallerException e) {
|
||||
throw new InfrastructureException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,11 +21,11 @@ import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
|||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
* Provision labels related to workspace configuration to docker environment.
|
||||
* Provision labels related to workspace runtime to docker environment.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class LabelsProvisioner implements ConfigurationProvisioner {
|
||||
public class RuntimeLabelsProvisioner implements ConfigurationProvisioner {
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment envConfig, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
|
|
@ -36,12 +36,7 @@ public class LabelsProvisioner implements ConfigurationProvisioner {
|
|||
DockerContainerConfig container = internalEnv.getContainers().get(name);
|
||||
container
|
||||
.getLabels()
|
||||
.putAll(
|
||||
Labels.newSerializer()
|
||||
.machineName(name)
|
||||
.runtimeId(identity)
|
||||
.servers(entry.getValue().getServers())
|
||||
.labels());
|
||||
.putAll(Labels.newSerializer().machineName(name).runtimeId(identity).labels());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.memory;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.InfrastructureProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
|
||||
/** @author Alexander Garagatyi */
|
||||
public class MemoryAttributeConverter implements InfrastructureProvisioner {
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
for (Entry<String, ? extends InternalMachineConfig> machineEntry :
|
||||
environment.getMachines().entrySet()) {
|
||||
String machineName = machineEntry.getKey();
|
||||
InternalMachineConfig machineConfig = machineEntry.getValue();
|
||||
|
||||
String memory = machineConfig.getAttributes().get(MachineConfig.MEMORY_LIMIT_ATTRIBUTE);
|
||||
if (memory != null) {
|
||||
try {
|
||||
internalEnv.getContainers().get(machineName).setMemLimit(Long.parseLong(memory));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InfrastructureException(
|
||||
format(
|
||||
"Value of attribute 'memoryLimitBytes' of machine '%s' is illegal", machineName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.server;
|
||||
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.Server;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.InfrastructureProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.Labels;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerContainerConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
|
||||
/**
|
||||
* Converts {@link ServerConfig} to Docker related objects to add a server into Docker runtime.
|
||||
*
|
||||
* <p>Adds ports mapping, exposes, labels to Docker container config to be able to evaluate {@link
|
||||
* Server}.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class ServersConverter implements InfrastructureProvisioner {
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, DockerEnvironment internalEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
environment
|
||||
.getMachines()
|
||||
.forEach(
|
||||
(machineName, machineConfig) -> {
|
||||
DockerContainerConfig container = internalEnv.getContainers().get(machineName);
|
||||
|
||||
container
|
||||
.getLabels()
|
||||
.putAll(Labels.newSerializer().servers(machineConfig.getServers()).labels());
|
||||
|
||||
machineConfig
|
||||
.getServers()
|
||||
.forEach(
|
||||
(key, value) -> {
|
||||
container.getPorts().add(value.getPort());
|
||||
container.getExpose().add(value.getPort());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ public class ServersMapper {
|
|||
ports
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getValue().size() == 1)
|
||||
.filter(entry -> entry.getValue() != null && entry.getValue().size() == 1)
|
||||
.map(entry -> toContainerPort(entry.getKey(), entry.getValue().get(0)))
|
||||
.toArray(ContainerPort[]::new),
|
||||
configs);
|
||||
|
|
|
|||
|
|
@ -18,11 +18,9 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertEqualsNoOrder;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -133,70 +131,6 @@ public class EnvironmentParserTest {
|
|||
verify(envParser).parse(environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOverrideMemoryLimitFromExtendedMachineInAnEnv() throws Exception {
|
||||
// given
|
||||
Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(
|
||||
"machine1", mockMachine(singletonMap("memoryLimitBytes", "101010")),
|
||||
"machine2", mockMachine());
|
||||
when(environment.getMachines()).thenReturn(machines);
|
||||
|
||||
DockerEnvironment dockerEnv = new DockerEnvironment();
|
||||
dockerEnv.getContainers().put("machine1", new DockerContainerConfig());
|
||||
dockerEnv.getContainers().put("machine2", new DockerContainerConfig());
|
||||
when(envParser.parse(environment)).thenReturn(dockerEnv);
|
||||
|
||||
DockerEnvironment expected = new DockerEnvironment();
|
||||
expected.getContainers().put("machine1", new DockerContainerConfig().setMemLimit(101010L));
|
||||
expected.getContainers().put("machine2", new DockerContainerConfig());
|
||||
|
||||
// when
|
||||
DockerEnvironment actual = parser.parse(environment);
|
||||
|
||||
// then
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@Test(
|
||||
expectedExceptions = ValidationException.class,
|
||||
expectedExceptionsMessageRegExp =
|
||||
"Value of attribute 'memoryLimitBytes' of machine '.*' is illegal"
|
||||
)
|
||||
public void shouldThrowExceptionInCaseFailedParseMemoryLimit() throws Exception {
|
||||
// given
|
||||
when(machine.getAttributes()).thenReturn(singletonMap("memoryLimitBytes", "AF"));
|
||||
|
||||
// when
|
||||
parser.parse(environment);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "environmentWithServersProvider")
|
||||
public void shouldAddExposesFromExtendedMachineServers(
|
||||
InternalMachineConfig machineConfig,
|
||||
DockerContainerConfig parsedContainer,
|
||||
List<String> expectedExposes)
|
||||
throws Exception {
|
||||
|
||||
// given
|
||||
when(environment.getMachines()).thenReturn(singletonMap(DEFAULT_MACHINE_NAME, machineConfig));
|
||||
when(dockerEnv.getContainers()).thenReturn(singletonMap(DEFAULT_MACHINE_NAME, parsedContainer));
|
||||
|
||||
// when
|
||||
DockerEnvironment actual = parser.parse(environment);
|
||||
|
||||
// then
|
||||
// prevent failures because of reordered entries of expose field
|
||||
assertEquals(actual.getContainers().size(), 1);
|
||||
assertEqualsNoOrder(
|
||||
actual.getContainers().get(DEFAULT_MACHINE_NAME).getExpose().toArray(),
|
||||
expectedExposes.toArray(),
|
||||
String.format(
|
||||
"Arrays are not equal. Actual: '%s'. Expected: '%s'",
|
||||
Arrays.toString(actual.getContainers().get(DEFAULT_MACHINE_NAME).getExpose().toArray()),
|
||||
Arrays.toString(expectedExposes.toArray())));
|
||||
}
|
||||
|
||||
@DataProvider(name = "environmentWithServersProvider")
|
||||
public static Object[][] environmentWithServersProvider() {
|
||||
// Format of result array:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import static java.util.Collections.emptyList;
|
|||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ public class EnvironmentValidatorTest {
|
|||
when(machineConfig.getServers())
|
||||
.thenReturn(singletonMap(Constants.SERVER_WS_AGENT_HTTP_REFERENCE, server));
|
||||
Map<String, String> attributes =
|
||||
ImmutableMap.of("testKey", "value", "memoryLimitBytes", "1000000000");
|
||||
ImmutableMap.of("testKey", "value", MEMORY_LIMIT_ATTRIBUTE, "1000000000");
|
||||
when(machineConfig.getAttributes()).thenReturn(attributes);
|
||||
when(container.getExpose()).thenReturn(asList("8090", "9090/tcp", "7070/udp"));
|
||||
when(container.getLinks()).thenReturn(singletonList(machine2Name + ":alias1"));
|
||||
|
|
@ -277,27 +278,6 @@ public class EnvironmentValidatorTest {
|
|||
environmentValidator.validate(environment, dockerEnvironment);
|
||||
}
|
||||
|
||||
@Test(
|
||||
expectedExceptions = ValidationException.class,
|
||||
expectedExceptionsMessageRegExp =
|
||||
"Value of attribute 'memoryLimitBytes' of machine '.*' in environment is illegal",
|
||||
dataProvider = "memoryAttributeValue"
|
||||
)
|
||||
public void shouldFailIfMemoryAttributeIsIllegal(String memoryAttributeValue) throws Exception {
|
||||
// given
|
||||
Map<String, String> attributes =
|
||||
ImmutableMap.of("testKey", "value", "memoryLimitBytes", memoryAttributeValue);
|
||||
when(machineConfig.getAttributes()).thenReturn(attributes);
|
||||
|
||||
// when
|
||||
environmentValidator.validate(environment, dockerEnvironment);
|
||||
}
|
||||
|
||||
@DataProvider(name = "memoryAttributeValue")
|
||||
public static Object[][] memoryAttributeValue() {
|
||||
return new Object[][] {{"aa"}, {""}, {"!"}, {"156a"}, {"0"}, {"-1"}};
|
||||
}
|
||||
|
||||
@Test(
|
||||
expectedExceptions = ValidationException.class,
|
||||
expectedExceptionsMessageRegExp =
|
||||
|
|
|
|||
|
|
@ -15,16 +15,18 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.dod.DockerApiHostEnvVariableProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.LocalInstallersBinariesVolumeProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.installer.WsAgentServerConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.local.projects.ProjectsVolumeProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.ContainerSystemSettingsProvisionersApplier;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.labels.LabelsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.env.EnvVarsConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.labels.RuntimeLabelsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.memory.MemoryAttributeConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.server.ServersConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.server.ToolingServersEnvVarsProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.provisioner.snapshot.ExcludeFoldersFromSnapshotProvisioner;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
|
|
@ -35,23 +37,42 @@ import org.testng.annotations.Test;
|
|||
/** @author Alexander Garagatyi */
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class LocalCheInfrastructureProvisionerTest {
|
||||
|
||||
@Mock private ContainerSystemSettingsProvisionersApplier settingsProvisioners;
|
||||
@Mock private ExcludeFoldersFromSnapshotProvisioner snapshotProvisioner;
|
||||
@Mock private ProjectsVolumeProvisioner projectsVolumeProvisioner;
|
||||
@Mock private LocalInstallersConfigProvisioner installerConfigProvisioner;
|
||||
@Mock private LabelsProvisioner labelsProvisioner;
|
||||
@Mock private LocalInstallersBinariesVolumeProvisioner installerConfigProvisioner;
|
||||
@Mock private RuntimeLabelsProvisioner labelsProvisioner;
|
||||
@Mock private DockerApiHostEnvVariableProvisioner dockerApiEnvProvisioner;
|
||||
@Mock private ToolingServersEnvVarsProvisioner toolingServersEnvVarsProvisioner;
|
||||
@Mock private InternalEnvironment environment;
|
||||
@Mock private DockerEnvironment dockerEnvironment;
|
||||
@Mock private RuntimeIdentity runtimeIdentity;
|
||||
@Mock private WsAgentServerConfigProvisioner wsAgentServerConfigProvisioner;
|
||||
@InjectMocks private LocalCheInfrastructureProvisioner provisioner;
|
||||
@Mock private ServersConverter serversConverter;
|
||||
@Mock private EnvVarsConverter envVarsConverter;
|
||||
@Mock private MemoryAttributeConverter memoryAttributeConverter;
|
||||
|
||||
private LocalCheInfrastructureProvisioner provisioner;
|
||||
|
||||
private Object[] allInnerProvisioners;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
provisioner =
|
||||
new LocalCheInfrastructureProvisioner(
|
||||
settingsProvisioners,
|
||||
snapshotProvisioner,
|
||||
projectsVolumeProvisioner,
|
||||
installerConfigProvisioner,
|
||||
labelsProvisioner,
|
||||
dockerApiEnvProvisioner,
|
||||
toolingServersEnvVarsProvisioner,
|
||||
wsAgentServerConfigProvisioner,
|
||||
serversConverter,
|
||||
envVarsConverter,
|
||||
memoryAttributeConverter);
|
||||
|
||||
allInnerProvisioners =
|
||||
new Object[] {
|
||||
settingsProvisioners,
|
||||
|
|
@ -61,7 +82,10 @@ public class LocalCheInfrastructureProvisionerTest {
|
|||
labelsProvisioner,
|
||||
dockerApiEnvProvisioner,
|
||||
toolingServersEnvVarsProvisioner,
|
||||
wsAgentServerConfigProvisioner
|
||||
wsAgentServerConfigProvisioner,
|
||||
serversConverter,
|
||||
envVarsConverter,
|
||||
memoryAttributeConverter
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +96,18 @@ public class LocalCheInfrastructureProvisionerTest {
|
|||
|
||||
// then
|
||||
InOrder inOrder = Mockito.inOrder((Object[]) allInnerProvisioners);
|
||||
inOrder
|
||||
.verify(serversConverter)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(envVarsConverter)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(memoryAttributeConverter)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(labelsProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(snapshotProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
|
|
@ -82,10 +118,10 @@ public class LocalCheInfrastructureProvisionerTest {
|
|||
.verify(projectsVolumeProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(settingsProvisioners)
|
||||
.verify(wsAgentServerConfigProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(labelsProvisioner)
|
||||
.verify(settingsProvisioners)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(dockerApiEnvProvisioner)
|
||||
|
|
@ -93,9 +129,6 @@ public class LocalCheInfrastructureProvisionerTest {
|
|||
inOrder
|
||||
.verify(toolingServersEnvVarsProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder
|
||||
.verify(wsAgentServerConfigProvisioner)
|
||||
.provision(eq(environment), eq(dockerEnvironment), eq(runtimeIdentity));
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.docker.provisioner.installer;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.installer.server.model.impl.InstallerImpl;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.docker.model.DockerContainerConfig;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** @author Anatolii Bazko */
|
||||
@Listeners(value = {MockitoTestNGListener.class})
|
||||
public class InstallerConfigApplierTest {
|
||||
@Mock private InstallerImpl installer1;
|
||||
@Mock private InstallerImpl installer2;
|
||||
@Mock private InstallerImpl installer3;
|
||||
|
||||
private InstallerConfigApplier installerConfigApplier;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
installerConfigApplier = new InstallerConfigApplier();
|
||||
|
||||
when(installer1.getScript()).thenReturn("script1");
|
||||
when(installer1.getDependencies()).thenReturn(singletonList("installer3"));
|
||||
|
||||
when(installer2.getScript()).thenReturn("script2");
|
||||
when(installer2.getDependencies()).thenReturn(singletonList("installer2"));
|
||||
|
||||
when(installer3.getScript()).thenReturn("script3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAddLabels() throws Exception {
|
||||
final ServerConfig serverConf1 = mock(ServerConfig.class);
|
||||
when(serverConf1.getPort()).thenReturn("1111/udp");
|
||||
when(serverConf1.getProtocol()).thenReturn("http");
|
||||
when(serverConf1.getPath()).thenReturn("b");
|
||||
|
||||
when(installer1.getServers()).thenAnswer(invocation -> singletonMap("a", serverConf1));
|
||||
DockerContainerConfig containerConf = new DockerContainerConfig();
|
||||
InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getInstallers()).thenReturn(singletonList(installer1));
|
||||
|
||||
installerConfigApplier.apply(machineConfig, containerConf);
|
||||
|
||||
Map<String, String> labels = containerConf.getLabels();
|
||||
assertEquals(labels.size(), 3);
|
||||
assertEquals(labels.get("org.eclipse.che.server.a.port"), "1111/udp");
|
||||
assertEquals(labels.get("org.eclipse.che.server.a.protocol"), "http");
|
||||
assertEquals(labels.get("org.eclipse.che.server.a.path"), "b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAddExposedPorts() throws Exception {
|
||||
final ServerConfig serverConf1 = mock(ServerConfig.class);
|
||||
final ServerConfig serverConfig = mock(ServerConfig.class);
|
||||
when(serverConf1.getPort()).thenReturn("1111/udp");
|
||||
when(serverConfig.getPort()).thenReturn("2222/tcp");
|
||||
|
||||
when(installer1.getServers()).thenAnswer(invocation -> singletonMap("a", serverConf1));
|
||||
when(installer2.getServers()).thenAnswer(invocation -> singletonMap("b", serverConfig));
|
||||
when(installer3.getServers()).thenReturn(emptyMap());
|
||||
DockerContainerConfig containerConf = new DockerContainerConfig();
|
||||
InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getInstallers()).thenReturn(asList(installer1, installer2, installer3));
|
||||
|
||||
installerConfigApplier.apply(machineConfig, containerConf);
|
||||
|
||||
List<String> exposedPorts = containerConf.getExpose();
|
||||
assertTrue(exposedPorts.contains("1111/udp"));
|
||||
assertTrue(exposedPorts.contains("2222/tcp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAddEnvVariables() throws Exception {
|
||||
when(installer1.getProperties()).thenReturn(singletonMap("environment", "p1=v1,p2=v2"));
|
||||
when(installer2.getProperties()).thenReturn(singletonMap("environment", "p3=v3"));
|
||||
DockerContainerConfig containerConf = new DockerContainerConfig();
|
||||
InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getInstallers()).thenReturn(asList(installer1, installer2));
|
||||
|
||||
installerConfigApplier.apply(machineConfig, containerConf);
|
||||
|
||||
Map<String, String> env = containerConf.getEnvironment();
|
||||
assertEquals(env.size(), 3);
|
||||
assertEquals(env.get("p1"), "v1");
|
||||
assertEquals(env.get("p2"), "v2");
|
||||
assertEquals(env.get("p3"), "v3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreEnvironmentIfIllegalFormat() throws Exception {
|
||||
when(installer1.getProperties()).thenReturn(singletonMap("environment", "p1"));
|
||||
DockerContainerConfig containerConf = new DockerContainerConfig();
|
||||
InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getInstallers()).thenReturn(singletonList(installer1));
|
||||
|
||||
installerConfigApplier.apply(machineConfig, containerConf);
|
||||
|
||||
Map<String, String> env = containerConf.getEnvironment();
|
||||
assertEquals(env.size(), 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -74,10 +74,6 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-installer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-installer-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.UniqueNamesProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.env.EnvVarsConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.installer.InstallerConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.labels.PodNameLabelProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.restartpolicy.RestartPolicyRewriter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.route.TlsRouteProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.server.ServersConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.volume.PersistentVolumeClaimProvisioner;
|
||||
|
||||
/**
|
||||
|
|
@ -26,33 +30,54 @@ import org.eclipse.che.workspace.infrastructure.openshift.provision.volume.Persi
|
|||
* the desired order, which corresponds to the needs of the OpenShift infrastructure.
|
||||
*
|
||||
* @author Anton Korneta
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Singleton
|
||||
public class OpenShiftInfrastructureProvisioner {
|
||||
|
||||
private final InstallerConfigProvisioner installerConfigProvisioner;
|
||||
private final PersistentVolumeClaimProvisioner persistentVolumeClaimProvisioner;
|
||||
private final UniqueNamesProvisioner uniqueNamesProvisioner;
|
||||
private final TlsRouteProvisioner tlsRouteProvisioner;
|
||||
private final ServersConverter serversConverter;
|
||||
private final EnvVarsConverter envVarsConverter;
|
||||
private final RestartPolicyRewriter restartPolicyRewriter;
|
||||
private final PodNameLabelProvisioner podNameLabelProvisioner;
|
||||
|
||||
@Inject
|
||||
public OpenShiftInfrastructureProvisioner(
|
||||
InstallerConfigProvisioner installerConfigProvisioner,
|
||||
PersistentVolumeClaimProvisioner projectVolumeProvisioner,
|
||||
UniqueNamesProvisioner uniqueNamesProvisioner,
|
||||
TlsRouteProvisioner tlsRouteProvisioner) {
|
||||
TlsRouteProvisioner tlsRouteProvisioner,
|
||||
ServersConverter serversConverter,
|
||||
EnvVarsConverter envVarsConverter,
|
||||
RestartPolicyRewriter restartPolicyRewriter,
|
||||
PodNameLabelProvisioner podNameLabelProvisioner) {
|
||||
this.installerConfigProvisioner = installerConfigProvisioner;
|
||||
this.persistentVolumeClaimProvisioner = projectVolumeProvisioner;
|
||||
this.uniqueNamesProvisioner = uniqueNamesProvisioner;
|
||||
this.tlsRouteProvisioner = tlsRouteProvisioner;
|
||||
this.serversConverter = serversConverter;
|
||||
this.envVarsConverter = envVarsConverter;
|
||||
this.restartPolicyRewriter = restartPolicyRewriter;
|
||||
this.podNameLabelProvisioner = podNameLabelProvisioner;
|
||||
}
|
||||
|
||||
public void provision(
|
||||
InternalEnvironment environment, OpenShiftEnvironment osEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
// 1 stage - add Che business logic items to Che model env
|
||||
installerConfigProvisioner.provision(environment, osEnv, identity);
|
||||
// 2 stage - converting Che model env to OpenShift env
|
||||
serversConverter.provision(environment, osEnv, identity);
|
||||
envVarsConverter.provision(environment, osEnv, identity);
|
||||
// 3 stage - add OpenShift env items
|
||||
podNameLabelProvisioner.provision(environment, osEnv, identity);
|
||||
restartPolicyRewriter.provision(environment, osEnv, identity);
|
||||
persistentVolumeClaimProvisioner.provision(environment, osEnv, identity);
|
||||
uniqueNamesProvisioner.provision(environment, osEnv, identity);
|
||||
tlsRouteProvisioner.provision(environment, osEnv, identity);
|
||||
}
|
||||
|
||||
// TODO memory attribute provisioner
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,34 +11,25 @@
|
|||
package org.eclipse.che.workspace.infrastructure.openshift.environment;
|
||||
|
||||
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;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.openshift.api.model.DeploymentConfig;
|
||||
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;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment.InternalRecipe;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.ServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment.Builder;
|
||||
|
||||
/**
|
||||
|
|
@ -64,8 +55,6 @@ public class OpenShiftEnvironmentParser {
|
|||
static final String PVC_IGNORED_WARNING_MESSAGE =
|
||||
"Persistent volume claims specified in OpenShift recipe are ignored.";
|
||||
|
||||
static final String DEFAULT_RESTART_POLICY = "Never";
|
||||
|
||||
private final OpenShiftClientFactory clientFactory;
|
||||
|
||||
@Inject
|
||||
|
|
@ -144,63 +133,7 @@ public class OpenShiftEnvironmentParser {
|
|||
new WarningImpl(PVC_IGNORED_WARNING_CODE, PVC_IGNORED_WARNING_MESSAGE));
|
||||
}
|
||||
|
||||
OpenShiftEnvironment openShiftEnv = openShiftEnvBuilder.build();
|
||||
|
||||
normalizeEnvironment(openShiftEnv, environment);
|
||||
|
||||
return openShiftEnv;
|
||||
}
|
||||
|
||||
private void normalizeEnvironment(
|
||||
OpenShiftEnvironment openShiftEnvironment, InternalEnvironment environment)
|
||||
throws ValidationException {
|
||||
for (Pod podConfig : openShiftEnvironment.getPods().values()) {
|
||||
final String podName = podConfig.getMetadata().getName();
|
||||
getLabels(podConfig).put(CHE_POD_NAME_LABEL, podName);
|
||||
final PodSpec podSpec = podConfig.getSpec();
|
||||
rewriteRestartPolicy(podSpec, podName, environment);
|
||||
for (Container containerConfig : podSpec.getContainers()) {
|
||||
String machineName = podName + '/' + containerConfig.getName();
|
||||
InternalMachineConfig machineConfig = environment.getMachines().get(machineName);
|
||||
if (machineConfig != null && !machineConfig.getServers().isEmpty()) {
|
||||
ServerExposer serverExposer =
|
||||
new ServerExposer(machineName, containerConfig, openShiftEnvironment);
|
||||
serverExposer.expose(machineConfig.getServers());
|
||||
|
||||
for (Entry<String, String> envEntry : machineConfig.getEnv().entrySet()) {
|
||||
putEnv(containerConfig.getEnv(), envEntry.getKey(), envEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getLabels(Pod pod) {
|
||||
ObjectMeta metadata = pod.getMetadata();
|
||||
if (metadata == null) {
|
||||
metadata = new ObjectMeta();
|
||||
pod.setMetadata(metadata);
|
||||
}
|
||||
|
||||
Map<String, String> labels = metadata.getLabels();
|
||||
if (labels == null) {
|
||||
labels = new HashMap<>();
|
||||
metadata.setLabels(labels);
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
private void rewriteRestartPolicy(PodSpec podSpec, String podName, InternalEnvironment env) {
|
||||
final String restartPolicy = podSpec.getRestartPolicy();
|
||||
|
||||
if (restartPolicy != null && !DEFAULT_RESTART_POLICY.equalsIgnoreCase(restartPolicy)) {
|
||||
final String warnMsg =
|
||||
format(
|
||||
"Restart policy '%s' for pod '%s' is rewritten with %s",
|
||||
restartPolicy, podName, DEFAULT_RESTART_POLICY);
|
||||
env.addWarning(new WarningImpl(101, warnMsg));
|
||||
}
|
||||
podSpec.setRestartPolicy(DEFAULT_RESTART_POLICY);
|
||||
return openShiftEnvBuilder.build();
|
||||
}
|
||||
|
||||
private void checkNotNull(Object object, String errorMessage) throws ValidationException {
|
||||
|
|
@ -208,9 +141,4 @@ public class OpenShiftEnvironmentParser {
|
|||
throw new ValidationException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void putEnv(List<EnvVar> envs, String key, String value) {
|
||||
envs.removeIf(env -> key.equals(env.getName()));
|
||||
envs.add(new EnvVar(key, value, null));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.env;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
* Converts environment variables in {@link MachineConfig} to OpenShift environment variables.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Singleton
|
||||
public class EnvVarsConverter implements ConfigurationProvisioner {
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, OpenShiftEnvironment osEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
for (Pod pod : osEnv.getPods().values()) {
|
||||
String podName = pod.getMetadata().getName();
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
String containerName = container.getName();
|
||||
String machineName = podName + "/" + containerName;
|
||||
InternalMachineConfig machineConf = environment.getMachines().get(machineName);
|
||||
|
||||
if (machineConf != null) {
|
||||
machineConf
|
||||
.getEnv()
|
||||
.forEach(
|
||||
(key, value) -> {
|
||||
container.getEnv().removeIf(env -> key.equals(env.getName()));
|
||||
container.getEnv().add(new EnvVar(key, value, null));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,19 +10,11 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.installer;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.installer.shared.model.Installer;
|
||||
import org.eclipse.che.api.workspace.server.WsAgentMachineFinderUtil;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
|
|
@ -30,30 +22,15 @@ import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
|||
import org.eclipse.che.api.workspace.server.token.MachineTokenProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.ConfigurationProvisioner;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Applies OpenShift specific properties of the installers to {@link OpenShiftEnvironment}.
|
||||
*
|
||||
* <p>This class must be called before OpenShift environment is started, otherwise changing
|
||||
* configuration has no effect.
|
||||
*
|
||||
* <p>This class performs following changes to environment: <br>
|
||||
* - adds environment variable to {@link Container containers} that are required by installers or
|
||||
* agents. <br>
|
||||
* - adds environment variables which are specified in properties of installer configuration. The
|
||||
* environment property contains environment variables in the following format:
|
||||
* "env1=value1,env2=value2,..."; <br>
|
||||
* - performs all required changes that are needed for exposing installers' servers.
|
||||
* Adds environment variable to {@link MachineConfig} that are required by installers or agents.
|
||||
*
|
||||
* @author Sergii Leshchenko
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class InstallerConfigProvisioner implements ConfigurationProvisioner {
|
||||
|
||||
private static final Logger LOG = getLogger(InstallerConfigProvisioner.class);
|
||||
|
||||
private static final String ENVIRONMENT_PROPERTY = "environment";
|
||||
|
||||
private final MachineTokenProvider machineTokenProvider;
|
||||
private final String cheServerEndpoint;
|
||||
|
||||
|
|
@ -73,56 +50,20 @@ public class InstallerConfigProvisioner implements ConfigurationProvisioner {
|
|||
WsAgentMachineFinderUtil.getWsAgentServerMachine(environment)
|
||||
.orElseThrow(() -> new InfrastructureException("Machine with wsagent not found"));
|
||||
|
||||
for (Pod pod : osEnv.getPods().values()) {
|
||||
String podName = pod.getMetadata().getName();
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
String containerName = container.getName();
|
||||
String machineName = podName + "/" + containerName;
|
||||
InternalMachineConfig machineConf = environment.getMachines().get(machineName);
|
||||
for (Entry<String, InternalMachineConfig> machineEntry : environment.getMachines().entrySet()) {
|
||||
InternalMachineConfig config = machineEntry.getValue();
|
||||
|
||||
for (Installer installer : machineConf.getInstallers()) {
|
||||
provisionEnv(container, installer.getProperties());
|
||||
}
|
||||
// CHE_API is used by installers for agent binary downloading
|
||||
config.getEnv().put("CHE_API", cheServerEndpoint);
|
||||
|
||||
// CHE_API is used by installers for agent binary downloading
|
||||
putEnv(container.getEnv(), "CHE_API", cheServerEndpoint);
|
||||
config.getEnv().put("USER_TOKEN", machineTokenProvider.getToken(identity.getWorkspaceId()));
|
||||
|
||||
putEnv(
|
||||
container.getEnv(),
|
||||
"USER_TOKEN",
|
||||
machineTokenProvider.getToken(identity.getWorkspaceId()));
|
||||
|
||||
// TODO incorrect place for env variable addition. workspace ID is needed for wsagent
|
||||
// server, not installer
|
||||
// WORKSPACE_ID is required only by workspace agent
|
||||
if (devMachineName.equals(machineName)) {
|
||||
putEnv(container.getEnv(), "CHE_WORKSPACE_ID", identity.getWorkspaceId());
|
||||
}
|
||||
// TODO incorrect place for env variable addition. workspace ID is needed for wsagent
|
||||
// server, not installer
|
||||
// WORKSPACE_ID is required only by workspace agent
|
||||
if (devMachineName.equals(machineEntry.getKey())) {
|
||||
config.getEnv().put("CHE_WORKSPACE_ID", identity.getWorkspaceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putEnv(List<EnvVar> envs, String key, String value) {
|
||||
envs.removeIf(env -> key.equals(env.getName()));
|
||||
envs.add(new EnvVar(key, value, null));
|
||||
}
|
||||
|
||||
private void provisionEnv(Container container, Map<String, String> properties) {
|
||||
String environment = properties.get(ENVIRONMENT_PROPERTY);
|
||||
if (isNullOrEmpty(environment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String env : environment.split(",")) {
|
||||
String[] items = env.split("=");
|
||||
if (items.length != 2) {
|
||||
LOG.warn(format("Illegal environment variable '%s' format", env));
|
||||
continue;
|
||||
}
|
||||
String name = items[0];
|
||||
String value = items[1];
|
||||
|
||||
container.getEnv().add(new EnvVar(name, value, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.labels;
|
||||
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.Constants.CHE_POD_NAME_LABEL;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.ConfigurationProvisioner;
|
||||
|
||||
/** @author Alexander Garagatyi */
|
||||
public class PodNameLabelProvisioner implements ConfigurationProvisioner {
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, OpenShiftEnvironment osEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
for (Pod podConfig : osEnv.getPods().values()) {
|
||||
final String podName = podConfig.getMetadata().getName();
|
||||
getLabels(podConfig).put(CHE_POD_NAME_LABEL, podName);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getLabels(Pod pod) {
|
||||
ObjectMeta metadata = pod.getMetadata();
|
||||
if (metadata == null) {
|
||||
metadata = new ObjectMeta();
|
||||
pod.setMetadata(metadata);
|
||||
}
|
||||
|
||||
Map<String, String> labels = metadata.getLabels();
|
||||
if (labels == null) {
|
||||
labels = new HashMap<>();
|
||||
metadata.setLabels(labels);
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.restartpolicy;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
* Rewrites restart policy to supported one - 'Never'.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class RestartPolicyRewriter implements ConfigurationProvisioner {
|
||||
static final String DEFAULT_RESTART_POLICY = "Never";
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, OpenShiftEnvironment osEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
for (Pod podConfig : osEnv.getPods().values()) {
|
||||
final String podName = podConfig.getMetadata().getName();
|
||||
final PodSpec podSpec = podConfig.getSpec();
|
||||
rewriteRestartPolicy(podSpec, podName, environment);
|
||||
}
|
||||
}
|
||||
|
||||
private void rewriteRestartPolicy(PodSpec podSpec, String podName, InternalEnvironment env) {
|
||||
final String restartPolicy = podSpec.getRestartPolicy();
|
||||
|
||||
if (restartPolicy != null && !DEFAULT_RESTART_POLICY.equalsIgnoreCase(restartPolicy)) {
|
||||
final String warnMsg =
|
||||
format(
|
||||
"Restart policy '%s' for pod '%s' is rewritten with %s",
|
||||
restartPolicy, podName, DEFAULT_RESTART_POLICY);
|
||||
env.addWarning(new WarningImpl(101, warnMsg));
|
||||
}
|
||||
podSpec.setRestartPolicy(DEFAULT_RESTART_POLICY);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.server;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import java.util.Map;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.ServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
* Converts {@link ServerConfig} to OpenShift related objects to add a server into OpenShift
|
||||
* runtime.
|
||||
*
|
||||
* <p>Adds OpenShift objects by calling {@link ServerExposer#expose(Map)} on each machine with
|
||||
* servers.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Singleton
|
||||
public class ServersConverter implements ConfigurationProvisioner {
|
||||
|
||||
@Override
|
||||
public void provision(
|
||||
InternalEnvironment environment, OpenShiftEnvironment osEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
|
||||
for (Pod podConfig : osEnv.getPods().values()) {
|
||||
final String podName = podConfig.getMetadata().getName();
|
||||
final PodSpec podSpec = podConfig.getSpec();
|
||||
for (Container containerConfig : podSpec.getContainers()) {
|
||||
String machineName = podName + '/' + containerConfig.getName();
|
||||
InternalMachineConfig machineConfig = environment.getMachines().get(machineName);
|
||||
if (machineConfig != null && !machineConfig.getServers().isEmpty()) {
|
||||
ServerExposer serverExposer = new ServerExposer(machineName, containerConfig, osEnv);
|
||||
serverExposer.expose(machineConfig.getServers());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,12 @@ import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
|||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.UniqueNamesProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.env.EnvVarsConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.installer.InstallerConfigProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.labels.PodNameLabelProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.restartpolicy.RestartPolicyRewriter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.route.TlsRouteProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.server.ServersConverter;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.provision.volume.PersistentVolumeClaimProvisioner;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -42,6 +46,10 @@ public class OpenShiftInfrastructureProvisionerTest {
|
|||
@Mock private OpenShiftEnvironment osEnv;
|
||||
@Mock private RuntimeIdentity runtimeIdentity;
|
||||
@Mock private TlsRouteProvisioner tlsRouteProvisioner;
|
||||
@Mock private EnvVarsConverter envVarsProvisioner;
|
||||
@Mock private ServersConverter serversProvisioner;
|
||||
@Mock private RestartPolicyRewriter restartPolicyRewriter;
|
||||
@Mock private PodNameLabelProvisioner labelsProvisioner;
|
||||
|
||||
private OpenShiftInfrastructureProvisioner osInfraProvisioner;
|
||||
|
||||
|
|
@ -51,9 +59,24 @@ public class OpenShiftInfrastructureProvisionerTest {
|
|||
public void setUp() {
|
||||
osInfraProvisioner =
|
||||
new OpenShiftInfrastructureProvisioner(
|
||||
installerProvisioner, pvcProvisioner, uniqueNamesProvisioner, tlsRouteProvisioner);
|
||||
installerProvisioner,
|
||||
pvcProvisioner,
|
||||
uniqueNamesProvisioner,
|
||||
tlsRouteProvisioner,
|
||||
serversProvisioner,
|
||||
envVarsProvisioner,
|
||||
restartPolicyRewriter,
|
||||
labelsProvisioner);
|
||||
provisionOrder =
|
||||
inOrder(installerProvisioner, pvcProvisioner, uniqueNamesProvisioner, tlsRouteProvisioner);
|
||||
inOrder(
|
||||
installerProvisioner,
|
||||
pvcProvisioner,
|
||||
uniqueNamesProvisioner,
|
||||
tlsRouteProvisioner,
|
||||
serversProvisioner,
|
||||
envVarsProvisioner,
|
||||
restartPolicyRewriter,
|
||||
labelsProvisioner);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -63,6 +86,18 @@ public class OpenShiftInfrastructureProvisionerTest {
|
|||
provisionOrder
|
||||
.verify(installerProvisioner)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
provisionOrder
|
||||
.verify(serversProvisioner)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
provisionOrder
|
||||
.verify(envVarsProvisioner)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
provisionOrder
|
||||
.verify(labelsProvisioner)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
provisionOrder
|
||||
.verify(restartPolicyRewriter)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
provisionOrder
|
||||
.verify(pvcProvisioner)
|
||||
.provision(eq(environment), eq(osEnv), eq(runtimeIdentity));
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.environment;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentParser.DEFAULT_RESTART_POLICY;
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentParser.PVC_IGNORED_WARNING_CODE;
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentParser.PVC_IGNORED_WARNING_MESSAGE;
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentParser.ROUTES_IGNORED_WARNING_MESSAGE;
|
||||
|
|
@ -26,17 +24,10 @@ import static org.testng.Assert.assertEquals;
|
|||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.DoneableKubernetesList;
|
||||
import io.fabric8.kubernetes.api.model.HasMetadata;
|
||||
import io.fabric8.kubernetes.api.model.KubernetesList;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodSpecBuilder;
|
||||
import io.fabric8.kubernetes.client.dsl.KubernetesListMixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.RecreateFromServerGettable;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
|
|
@ -64,8 +55,6 @@ import org.testng.annotations.Test;
|
|||
public class OpenShiftEnvironmentParserTest {
|
||||
|
||||
private static final String YAML_RECIPE = "application/x-yaml";
|
||||
private static final String TEST_POD_NAME = "app";
|
||||
private static final String ALWAYS_RESTART_POLICY = "Always";
|
||||
|
||||
private OpenShiftEnvironmentParser osEnvironmentParser;
|
||||
|
||||
|
|
@ -95,23 +84,6 @@ public class OpenShiftEnvironmentParserTest {
|
|||
when(internalRecipe.getContent()).thenReturn("recipe content");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rewritesRestartPolicyWhenItsDifferentWithDefaultOne() throws Exception {
|
||||
final List<HasMetadata> pods = singletonList(newPod(TEST_POD_NAME, ALWAYS_RESTART_POLICY));
|
||||
when(validatedObjects.getItems()).thenReturn(pods);
|
||||
|
||||
final OpenShiftEnvironment parsed = osEnvironmentParser.parse(internalEnvironment);
|
||||
|
||||
assertEquals(
|
||||
parsed.getPods().get(TEST_POD_NAME).getSpec().getRestartPolicy(), DEFAULT_RESTART_POLICY);
|
||||
verifyWarnings(
|
||||
new WarningImpl(
|
||||
101,
|
||||
format(
|
||||
"Restart policy '%s' for pod '%s' is rewritten with %s",
|
||||
ALWAYS_RESTART_POLICY, TEST_POD_NAME, DEFAULT_RESTART_POLICY)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoreRoutesWhenRecipeContainsThem() throws Exception {
|
||||
final List<HasMetadata> objects = asList(new Route(), new Route());
|
||||
|
|
@ -152,11 +124,4 @@ public class OpenShiftEnvironmentParserTest {
|
|||
verify(internalEnvironment, atLeastOnce()).addWarning(warningCaptor.capture());
|
||||
return warningCaptor.getAllValues();
|
||||
}
|
||||
|
||||
private static Pod newPod(String podName, String restartPolicy, Container... containers) {
|
||||
final ObjectMeta podMetadata = new ObjectMetaBuilder().withName(podName).build();
|
||||
final PodSpec podSpec =
|
||||
new PodSpecBuilder().withRestartPolicy(restartPolicy).withContainers(containers).build();
|
||||
return new PodBuilder().withMetadata(podMetadata).withSpec(podSpec).build();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.che.workspace.infrastructure.openshift.provision.installer;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
|
@ -18,21 +19,10 @@ import static org.testng.Assert.assertFalse;
|
|||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.installer.server.model.impl.InstallerImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
|
||||
import org.eclipse.che.api.workspace.server.token.MachineTokenProvider;
|
||||
|
|
@ -49,6 +39,7 @@ import org.testng.annotations.Test;
|
|||
*
|
||||
* @author Anton Korneta
|
||||
* @author Sergii Leshchenko
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class InstallerConfigProvisionerTest {
|
||||
|
|
@ -57,6 +48,7 @@ public class InstallerConfigProvisionerTest {
|
|||
|
||||
@Mock private MachineTokenProvider machineTokenProvider;
|
||||
@Mock private RuntimeIdentity runtimeIdentity;
|
||||
@Mock protected OpenShiftEnvironment osEnvironment;
|
||||
|
||||
private InstallerConfigProvisioner installerConfigProvisioner;
|
||||
|
||||
|
|
@ -68,68 +60,16 @@ public class InstallerConfigProvisionerTest {
|
|||
when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void provisionWithEnvsFromInstallersAttributes() throws Exception {
|
||||
// given
|
||||
final Pod pod = new PodBuilder().setName("test").setContainers("machine").build();
|
||||
OpenShiftEnvironment osEnvironment =
|
||||
OpenShiftEnvironment.builder()
|
||||
.setPods(ImmutableMap.of(pod.getMetadata().getName(), pod))
|
||||
.build();
|
||||
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(
|
||||
"test/machine",
|
||||
new MachineConfigBuilder()
|
||||
.setInstallers(
|
||||
new InstallerImpl()
|
||||
.withProperties(ImmutableMap.of("environment", "INSTALLER1=localhost")),
|
||||
new InstallerImpl()
|
||||
.withProperties(ImmutableMap.of("environment", "INSTALLER2=agent")))
|
||||
.setServer(Constants.SERVER_WS_AGENT_HTTP_REFERENCE, new ServerConfigImpl())
|
||||
.build());
|
||||
|
||||
InternalEnvironment environment = createEnvironment(machines);
|
||||
|
||||
// when
|
||||
installerConfigProvisioner.provision(environment, osEnvironment, runtimeIdentity);
|
||||
|
||||
// then
|
||||
Container container = pod.getSpec().getContainers().get(0);
|
||||
List<EnvVar> envs = container.getEnv();
|
||||
verifyContainsEnv(envs, "INSTALLER1", "localhost");
|
||||
verifyContainsEnv(envs, "INSTALLER2", "agent");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void provisionWithAgentsRequiredEnvs() throws Exception {
|
||||
// given
|
||||
when(machineTokenProvider.getToken(WORKSPACE_ID)).thenReturn("superToken");
|
||||
|
||||
final Pod podWithAgent = new PodBuilder().setName("pod1").setContainers("wsagent").build();
|
||||
|
||||
final Pod pod = new PodBuilder().setName("pod2").setContainers("machine").build();
|
||||
|
||||
OpenShiftEnvironment osEnvironment =
|
||||
OpenShiftEnvironment.builder()
|
||||
.setPods(
|
||||
ImmutableMap.of(
|
||||
podWithAgent.getMetadata().getName(),
|
||||
podWithAgent,
|
||||
pod.getMetadata().getName(),
|
||||
pod))
|
||||
.build();
|
||||
|
||||
InternalMachineConfig machine1 =
|
||||
createMachine(new HashMap<>(singletonMap("env1", "val1")), true);
|
||||
InternalMachineConfig machine2 = createMachine(new HashMap<>(), false);
|
||||
final Map<String, InternalMachineConfig> machines =
|
||||
ImmutableMap.of(
|
||||
"pod1/wsagent",
|
||||
new MachineConfigBuilder()
|
||||
.setServer(Constants.SERVER_WS_AGENT_HTTP_REFERENCE, new ServerConfigImpl())
|
||||
.build(),
|
||||
"pod2/machine",
|
||||
new MachineConfigBuilder()
|
||||
.setServer(Constants.SERVER_TERMINAL_REFERENCE, new ServerConfigImpl())
|
||||
.build());
|
||||
ImmutableMap.of("pod1/wsagent", machine1, "pod2/machine", machine2);
|
||||
|
||||
InternalEnvironment environment = createEnvironment(machines);
|
||||
|
||||
|
|
@ -137,17 +77,27 @@ public class InstallerConfigProvisionerTest {
|
|||
installerConfigProvisioner.provision(environment, osEnvironment, runtimeIdentity);
|
||||
|
||||
// then
|
||||
Container container = podWithAgent.getSpec().getContainers().get(0);
|
||||
List<EnvVar> envs = container.getEnv();
|
||||
verifyContainsEnv(envs, "CHE_API", CHE_SERVER_ENDPOINT);
|
||||
verifyContainsEnv(envs, "USER_TOKEN", "superToken");
|
||||
verifyContainsEnv(envs, "CHE_WORKSPACE_ID", WORKSPACE_ID);
|
||||
Map<String, String> env = machine1.getEnv();
|
||||
verifyContainsEnv(env, "CHE_API", CHE_SERVER_ENDPOINT);
|
||||
verifyContainsEnv(env, "USER_TOKEN", "superToken");
|
||||
verifyContainsEnv(env, "CHE_WORKSPACE_ID", WORKSPACE_ID);
|
||||
|
||||
Container container2 = pod.getSpec().getContainers().get(0);
|
||||
List<EnvVar> envs2 = container2.getEnv();
|
||||
verifyContainsEnv(envs2, "CHE_API", CHE_SERVER_ENDPOINT);
|
||||
verifyContainsEnv(envs, "USER_TOKEN", "superToken");
|
||||
verifyDoesNotContainEnv(envs2, "CHE_WORKSPACE_ID");
|
||||
env = machine2.getEnv();
|
||||
verifyContainsEnv(env, "CHE_API", CHE_SERVER_ENDPOINT);
|
||||
verifyContainsEnv(env, "USER_TOKEN", "superToken");
|
||||
assertFalse(
|
||||
env.containsKey("CHE_WORKSPACE_ID"), "Environment variable '%s' found CHE_WORKSPACE_ID");
|
||||
}
|
||||
|
||||
private InternalMachineConfig createMachine(Map<String, String> env, boolean isDev) {
|
||||
InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getEnv()).thenReturn(env);
|
||||
if (isDev) {
|
||||
when(machineConfig.getServers())
|
||||
.thenReturn(
|
||||
singletonMap(Constants.SERVER_WS_AGENT_HTTP_REFERENCE, mock(ServerConfig.class)));
|
||||
}
|
||||
return machineConfig;
|
||||
}
|
||||
|
||||
private InternalEnvironment createEnvironment(Map<String, InternalMachineConfig> machines) {
|
||||
|
|
@ -156,18 +106,10 @@ public class InstallerConfigProvisionerTest {
|
|||
return environment;
|
||||
}
|
||||
|
||||
private void verifyDoesNotContainEnv(List<EnvVar> envs, String name) {
|
||||
Optional<EnvVar> env = envs.stream().filter(e -> e.getName().equals(name)).findAny();
|
||||
private void verifyContainsEnv(Map<String, String> env, String name, String expectedValue) {
|
||||
assertTrue(env.containsKey(name), format("Expected environment variable '%s' not found", name));
|
||||
|
||||
assertFalse(env.isPresent(), format("Environment variable '%s' found", name));
|
||||
}
|
||||
|
||||
private void verifyContainsEnv(List<EnvVar> envs, String name, String expectedValue) {
|
||||
Optional<EnvVar> env = envs.stream().filter(e -> e.getName().equals(name)).findAny();
|
||||
|
||||
assertTrue(env.isPresent(), format("Expected environment variable '%s' not found", name));
|
||||
|
||||
String actualValue = env.get().getValue();
|
||||
String actualValue = env.get(name);
|
||||
assertEquals(
|
||||
actualValue,
|
||||
expectedValue,
|
||||
|
|
@ -175,66 +117,4 @@ public class InstallerConfigProvisionerTest {
|
|||
"Environment variable '%s' expected with " + "value '%s' but found with '%s'",
|
||||
name, expectedValue, actualValue));
|
||||
}
|
||||
|
||||
private static class MachineConfigBuilder {
|
||||
|
||||
private List<InstallerImpl> installers = new ArrayList<>();
|
||||
private Map<String, ServerConfig> servers = new HashMap<>();
|
||||
|
||||
MachineConfigBuilder setInstallers(InstallerImpl... installers) {
|
||||
this.installers = Arrays.asList(installers);
|
||||
return this;
|
||||
}
|
||||
|
||||
MachineConfigBuilder setServer(String name, ServerConfig server) {
|
||||
this.servers.put(name, server);
|
||||
return this;
|
||||
}
|
||||
|
||||
InternalMachineConfig build() {
|
||||
final InternalMachineConfig machineConfig = mock(InternalMachineConfig.class);
|
||||
when(machineConfig.getInstallers()).thenReturn(installers);
|
||||
when(machineConfig.getServers()).thenReturn(servers);
|
||||
return machineConfig;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PodBuilder {
|
||||
|
||||
private String name;
|
||||
private List<String> containersNames;
|
||||
|
||||
PodBuilder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
PodBuilder setContainers(String... names) {
|
||||
this.containersNames = Arrays.asList(names);
|
||||
return this;
|
||||
}
|
||||
|
||||
Pod build() {
|
||||
final Pod pod = mock(Pod.class);
|
||||
final ObjectMeta podMeta = mock(ObjectMeta.class);
|
||||
when(pod.getMetadata()).thenReturn(podMeta);
|
||||
when(podMeta.getName()).thenReturn(name);
|
||||
|
||||
final PodSpec podSpec = mock(PodSpec.class);
|
||||
when(pod.getSpec()).thenReturn(podSpec);
|
||||
|
||||
final List<Container> containers = new ArrayList<>();
|
||||
for (String containerName : containersNames) {
|
||||
final Container container = mock(Container.class);
|
||||
when(container.getName()).thenReturn(containerName);
|
||||
when(container.getEnv()).thenReturn(new ArrayList<>());
|
||||
|
||||
containers.add(container);
|
||||
}
|
||||
|
||||
when(podSpec.getContainers()).thenReturn(containers);
|
||||
|
||||
return pod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.provision.restartpolicy;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.workspace.infrastructure.openshift.provision.restartpolicy.RestartPolicyRewriter.DEFAULT_RESTART_POLICY;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodSpecBuilder;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.eclipse.che.api.core.model.workspace.Warning;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/** @author Alexander Garagatyi */
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class RestartPolicyRewriterTest {
|
||||
private static final String TEST_POD_NAME = "app";
|
||||
private static final String ALWAYS_RESTART_POLICY = "Always";
|
||||
|
||||
@Mock private InternalEnvironment environment;
|
||||
@Mock private OpenShiftEnvironment osEnv;
|
||||
@Mock private RuntimeIdentity runtimeIdentity;
|
||||
@InjectMocks private RestartPolicyRewriter restartPolicyRewriter;
|
||||
|
||||
@Captor private ArgumentCaptor<Warning> warningCaptor;
|
||||
|
||||
@Test
|
||||
public void rewritesRestartPolicyWhenItsDifferentWithDefaultOne() throws Exception {
|
||||
when(osEnv.getPods())
|
||||
.thenReturn(singletonMap(TEST_POD_NAME, newPod(TEST_POD_NAME, ALWAYS_RESTART_POLICY)));
|
||||
|
||||
restartPolicyRewriter.provision(environment, osEnv, runtimeIdentity);
|
||||
|
||||
assertEquals(
|
||||
osEnv.getPods().get(TEST_POD_NAME).getSpec().getRestartPolicy(), DEFAULT_RESTART_POLICY);
|
||||
verifyWarnings(
|
||||
new WarningImpl(
|
||||
101,
|
||||
format(
|
||||
"Restart policy '%s' for pod '%s' is rewritten with %s",
|
||||
ALWAYS_RESTART_POLICY, TEST_POD_NAME, DEFAULT_RESTART_POLICY)));
|
||||
}
|
||||
|
||||
private static Pod newPod(String podName, String restartPolicy, Container... containers) {
|
||||
final ObjectMeta podMetadata = new ObjectMetaBuilder().withName(podName).build();
|
||||
final PodSpec podSpec =
|
||||
new PodSpecBuilder().withRestartPolicy(restartPolicy).withContainers(containers).build();
|
||||
return new PodBuilder().withMetadata(podMetadata).withSpec(podSpec).build();
|
||||
}
|
||||
|
||||
private void verifyWarnings(Warning... expectedWarnings) {
|
||||
final Iterator<Warning> actualWarnings = captureWarnings().iterator();
|
||||
for (Warning expected : expectedWarnings) {
|
||||
if (!actualWarnings.hasNext()) {
|
||||
fail("It is expected to receive environment warning");
|
||||
}
|
||||
final Warning actual = actualWarnings.next();
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
if (actualWarnings.hasNext()) {
|
||||
fail("No more warnings expected");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Warning> captureWarnings() {
|
||||
verify(environment, atLeastOnce()).addWarning(warningCaptor.capture());
|
||||
return warningCaptor.getAllValues();
|
||||
}
|
||||
}
|
||||
|
|
@ -70,6 +70,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-factory-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace-shared</artifactId>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ package org.eclipse.che.plugin.urlfactory;
|
|||
import static java.lang.Boolean.FALSE;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.eclipse.che.plugin.urlfactory.URLFactoryBuilder.DEFAULT_DOCKER_IMAGE;
|
||||
import static org.eclipse.che.plugin.urlfactory.URLFactoryBuilder.MACHINE_NAME;
|
||||
|
|
@ -64,7 +65,7 @@ public class URLFactoryBuilderTest {
|
|||
MachineConfigDto machine =
|
||||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", MEMORY_LIMIT_BYTES));
|
||||
.withAttributes(singletonMap(MEMORY_LIMIT_ATTRIBUTE, MEMORY_LIMIT_BYTES));
|
||||
|
||||
// setup environment
|
||||
EnvironmentDto environmentDto =
|
||||
|
|
@ -101,7 +102,7 @@ public class URLFactoryBuilderTest {
|
|||
MachineConfigDto machine =
|
||||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", MEMORY_LIMIT_BYTES));
|
||||
.withAttributes(singletonMap(MEMORY_LIMIT_ATTRIBUTE, MEMORY_LIMIT_BYTES));
|
||||
|
||||
// setup environment
|
||||
EnvironmentDto environmentDto =
|
||||
|
|
@ -137,7 +138,7 @@ public class URLFactoryBuilderTest {
|
|||
MachineConfigDto machine =
|
||||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", MEMORY_LIMIT_BYTES));
|
||||
.withAttributes(singletonMap(MEMORY_LIMIT_ATTRIBUTE, MEMORY_LIMIT_BYTES));
|
||||
|
||||
// setup environment
|
||||
EnvironmentDto environmentDto =
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import static java.lang.String.format;
|
|||
import static java.lang.String.valueOf;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.workspace.server.WsAgentMachineFinderUtil.containsWsAgentServer;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
|
@ -188,7 +189,7 @@ public class TestWorkspaceServiceClient {
|
|||
.forEach(
|
||||
m ->
|
||||
m.getAttributes()
|
||||
.put("memoryLimitBytes", Long.toString(convertToByte(memory, memoryUnit))));
|
||||
.put(MEMORY_LIMIT_ATTRIBUTE, Long.toString(convertToByte(memory, memoryUnit))));
|
||||
workspace.getEnvironments().remove("replaced_name");
|
||||
workspace.getEnvironments().put(workspaceName, environment);
|
||||
workspace.setName(workspaceName);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import static java.util.Arrays.asList;
|
|||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
|
@ -191,7 +192,7 @@ public class FactoryBuilderTest {
|
|||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(
|
||||
singletonMap("memoryLimitBytes", "" + 512L * 1024L * 1024L))));
|
||||
singletonMap(MEMORY_LIMIT_ATTRIBUTE, "" + 512L * 1024L * 1024L))));
|
||||
|
||||
WorkspaceConfigDto workspaceConfig =
|
||||
dto.createDto(WorkspaceConfigDto.class)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,18 @@ import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
|||
* An entity that might additionally injected into machine and brings functionality.
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public interface Installer {
|
||||
|
||||
/**
|
||||
* Name of a property from {@link #getProperties()} that can contain environment variables that
|
||||
* should be injected into machine.
|
||||
*
|
||||
* <p>Example: { "environment" : "envVar1=value1,envVar2=value2" }
|
||||
*/
|
||||
String ENVIRONMENT_PROPERTY = "environment";
|
||||
|
||||
/** Returns the id of the installer. */
|
||||
String getId();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ package org.eclipse.che.api.workspace.server;
|
|||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
|
@ -24,6 +26,7 @@ import org.eclipse.che.api.core.model.workspace.Workspace;
|
|||
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Command;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Environment;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.config.Recipe;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
|
||||
|
|
@ -83,7 +86,11 @@ public class WorkspaceValidator {
|
|||
checkNotNull(recipe, "Environment recipe must not be null");
|
||||
checkNotNull(recipe.getType(), "Environment recipe type must not be null");
|
||||
|
||||
// TODO: spi: deal with exceptions
|
||||
for (Entry<String, ? extends MachineConfig> machineEntry :
|
||||
environment.getMachines().entrySet()) {
|
||||
validateMachine(machineEntry.getKey(), machineEntry.getValue());
|
||||
}
|
||||
|
||||
try {
|
||||
runtimes.validate(environment);
|
||||
} catch (InfrastructureException e) {
|
||||
|
|
@ -127,6 +134,20 @@ public class WorkspaceValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private void validateMachine(String name, MachineConfig machine) throws ValidationException {
|
||||
String memoryAttribute = machine.getAttributes().get(MEMORY_LIMIT_ATTRIBUTE);
|
||||
if (memoryAttribute != null) {
|
||||
try {
|
||||
Long.parseLong(memoryAttribute);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ValidationException(
|
||||
format(
|
||||
"Value '%s' of attribute '%s' in machine '%s' is illegal",
|
||||
memoryAttribute, MEMORY_LIMIT_ATTRIBUTE, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that object reference is not null, throws {@link ValidationException} in the case of
|
||||
* null {@code object} with given {@code message}.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ package org.eclipse.che.api.workspace.server.adapter;
|
|||
|
||||
import static com.google.common.primitives.Ints.tryParse;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
|
|
@ -174,7 +175,7 @@ public class WorkspaceConfigJsonAdapter {
|
|||
envName));
|
||||
}
|
||||
final JsonObject attributes = new JsonObject();
|
||||
attributes.addProperty("memoryLimitBytes", Long.toString(1024L * 1024L * ram));
|
||||
attributes.addProperty(MEMORY_LIMIT_ATTRIBUTE, Long.toString(1024L * 1024L * ram));
|
||||
newMachine.add("attributes", attributes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
package org.eclipse.che.api.workspace.server.spi;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -88,21 +89,43 @@ public class InternalMachineConfig {
|
|||
try {
|
||||
List<Installer> sortedInstallers = installerRegistry.getOrderedInstallers(installersKeys);
|
||||
for (Installer installer : sortedInstallers) {
|
||||
this.installers.add(new InstallerImpl(installer));
|
||||
for (Map.Entry<String, ? extends ServerConfig> serverEntry :
|
||||
installer.getServers().entrySet()) {
|
||||
if (servers.putIfAbsent(serverEntry.getKey(), serverEntry.getValue()) != null
|
||||
&& servers.get(serverEntry.getKey()).equals(serverEntry.getValue())) {
|
||||
throw new InfrastructureException(
|
||||
format(
|
||||
"Installer '%s' contains server '%s' conflicting with machine configuration",
|
||||
installer.getId(), serverEntry.getKey()));
|
||||
}
|
||||
}
|
||||
applyInstaller(installer);
|
||||
}
|
||||
} catch (InstallerException e) {
|
||||
// TODO installers has circular dependency or missing, what should we throw in that case?
|
||||
throw new InfrastructureException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyInstaller(Installer installer) throws InfrastructureException {
|
||||
this.installers.add(new InstallerImpl(installer));
|
||||
for (Map.Entry<String, ? extends ServerConfig> serverEntry :
|
||||
installer.getServers().entrySet()) {
|
||||
if (servers.putIfAbsent(serverEntry.getKey(), serverEntry.getValue()) != null
|
||||
&& !servers.get(serverEntry.getKey()).equals(serverEntry.getValue())) {
|
||||
throw new InfrastructureException(
|
||||
format(
|
||||
"Installer '%s' contains server '%s' conflicting with machine configuration",
|
||||
installer.getId(), serverEntry.getKey()));
|
||||
}
|
||||
}
|
||||
addEnvVars(installer);
|
||||
}
|
||||
|
||||
private void addEnvVars(Installer installer) {
|
||||
String environment = installer.getProperties().get(Installer.ENVIRONMENT_PROPERTY);
|
||||
if (isNullOrEmpty(environment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String env : environment.split(",")) {
|
||||
String[] items = env.split("=");
|
||||
if (items.length != 2) {
|
||||
// TODO add warning
|
||||
// LOG.warn(format("Illegal environment variable '%s' format", env));
|
||||
continue;
|
||||
}
|
||||
|
||||
this.env.put(items[0], items[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
package org.eclipse.che.api.workspace.server;
|
||||
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
|
@ -85,8 +86,8 @@ public class WorkspaceConfigJsonAdapterTest {
|
|||
assertTrue(
|
||||
devMachineObj.get("attributes").isJsonObject(), "dev machine attributes is json object");
|
||||
final JsonObject attributes = devMachineObj.getAsJsonObject("attributes");
|
||||
assertTrue(attributes.has("memoryLimitBytes"), "has memory limit");
|
||||
assertEquals(attributes.get("memoryLimitBytes").getAsString(), "2147483648");
|
||||
assertTrue(attributes.has(MEMORY_LIMIT_ATTRIBUTE), "has memory limit");
|
||||
assertEquals(attributes.get(MEMORY_LIMIT_ATTRIBUTE).getAsString(), "2147483648");
|
||||
|
||||
// check environment recipe
|
||||
assertTrue(environmentObj.has("recipe"), "environment contains recipe");
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import static java.util.Collections.singletonMap;
|
|||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STARTING;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.workspace.server.WorkspaceManager.UPDATED_ATTRIBUTE_NAME;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
|
|
@ -557,7 +558,7 @@ public class WorkspaceManagerTest {
|
|||
singletonList("org.eclipse.che.ws-agent"),
|
||||
null,
|
||||
singletonMap("CHE_ENV", "value"),
|
||||
singletonMap("memoryLimitBytes", "10000"));
|
||||
singletonMap(MEMORY_LIMIT_ATTRIBUTE, "10000"));
|
||||
EnvironmentImpl environment =
|
||||
new EnvironmentImpl(
|
||||
new RecipeImpl("type", "contentType", "content", null),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import static java.util.Collections.singletonList;
|
|||
import static java.util.Collections.singletonMap;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STARTING;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
|
||||
import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
|
||||
|
|
@ -917,7 +918,7 @@ public class WorkspaceServiceTest {
|
|||
singletonList("org.eclipse.che.ws-agent"),
|
||||
null,
|
||||
singletonMap("CHE_ENV", "value"),
|
||||
singletonMap("memoryLimitBytes", "10000"));
|
||||
singletonMap(MEMORY_LIMIT_ATTRIBUTE, "10000"));
|
||||
|
||||
return DtoConverter.asDto(
|
||||
new EnvironmentImpl(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ package org.eclipse.che.api.workspace.server;
|
|||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
@ -20,6 +21,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.ValidationException;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
|
||||
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
|
||||
import org.eclipse.che.api.workspace.shared.dto.MachineConfigDto;
|
||||
|
|
@ -184,6 +186,27 @@ public class WorkspaceValidatorTest {
|
|||
wsValidator.validateConfig(config);
|
||||
}
|
||||
|
||||
@Test(
|
||||
expectedExceptions = ValidationException.class,
|
||||
expectedExceptionsMessageRegExp =
|
||||
"Value '.*' of attribute '" + MEMORY_LIMIT_ATTRIBUTE + "' in machine '.*' is illegal",
|
||||
dataProvider = "illegalMemoryAttributeValueProvider"
|
||||
)
|
||||
public void shouldFailValidationIfMemoryMachineAttributeHasIllegalValue(String attributeValue)
|
||||
throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
EnvironmentDto env = config.getEnvironments().values().iterator().next();
|
||||
MachineConfigDto machine = env.getMachines().values().iterator().next();
|
||||
machine.getAttributes().put(MachineConfig.MEMORY_LIMIT_ATTRIBUTE, attributeValue);
|
||||
|
||||
wsValidator.validateConfig(config);
|
||||
}
|
||||
|
||||
@DataProvider(name = "illegalMemoryAttributeValueProvider")
|
||||
public static Object[][] illegalMemoryAttributeValueProvider() {
|
||||
return new Object[][] {{"text"}, {""}, {"123MB"}, {"123GB"}, {"123KB"}};
|
||||
}
|
||||
|
||||
@Test(
|
||||
expectedExceptions = ValidationException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace ws-name contains command with null or empty name"
|
||||
|
|
@ -221,17 +244,17 @@ public class WorkspaceValidatorTest {
|
|||
final WorkspaceConfigDto workspaceConfigDto =
|
||||
newDto(WorkspaceConfigDto.class).withName("ws-name").withDefaultEnv("dev-env");
|
||||
|
||||
MachineConfigDto extendedMachine =
|
||||
MachineConfigDto machineConfig =
|
||||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withServers(
|
||||
singletonMap(
|
||||
"ref1",
|
||||
newDto(ServerConfigDto.class).withPort("8080/tcp").withProtocol("https")))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", "1000000"));
|
||||
.withAttributes(new HashMap<>(singletonMap(MEMORY_LIMIT_ATTRIBUTE, "1000000")));
|
||||
EnvironmentDto env =
|
||||
newDto(EnvironmentDto.class)
|
||||
.withMachines(singletonMap("devmachine1", extendedMachine))
|
||||
.withMachines(singletonMap("devmachine1", machineConfig))
|
||||
.withRecipe(
|
||||
newDto(RecipeDto.class)
|
||||
.withType("type")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.che.api.workspace.server.stack;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
|
|
@ -194,7 +195,7 @@ public class StackLoaderTest {
|
|||
newDto(MachineConfigDto.class)
|
||||
.withInstallers(Arrays.asList("agent1", "agent2"))
|
||||
.withServers(servers)
|
||||
.withAttributes(singletonMap("memoryLimitBytes", "" + 512L * 1024L * 1024L)));
|
||||
.withAttributes(singletonMap(MEMORY_LIMIT_ATTRIBUTE, "" + 512L * 1024L * 1024L)));
|
||||
|
||||
EnvironmentDto environmentDto =
|
||||
newDto(EnvironmentDto.class).withRecipe(environmentRecipe).withMachines(machines);
|
||||
|
|
|
|||
Loading…
Reference in New Issue