Skip to content

Commit

Permalink
Propage env variables and memory limit on plugin brokering phase
Browse files Browse the repository at this point in the history
Signed-off-by: Sergii Leshchenko <sleshche@redhat.com>
  • Loading branch information
sleshchenko committed Dec 10, 2019
1 parent 936f4e9 commit 42a04ee
Show file tree
Hide file tree
Showing 22 changed files with 188 additions and 333 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ che.workspace.wsagent_java_options=-XX:MaxRAM=600m -XX:MaxRAMFraction=1 -XX:+Use
che.workspace.maven_server_java_options=-XX:MaxRAM=128m -XX:MaxRAMFraction=1 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xms20m -Djava.security.egd=file:/dev/./urandom



# Folder that will be a volume mount from your host into your workspace.
che.workspace.volume=

# The location of the Web terminal used within the browser.
# This is copied into the workspace and runs within the workspace.
# Suffix helps differentiate archive for different architectures/OSes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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.ProjectConfig;
import org.eclipse.che.api.core.model.workspace.devfile.Devfile;
import org.eclipse.che.commons.annotation.Nullable;

/**
Expand Down Expand Up @@ -64,4 +65,7 @@ public interface WorkspaceConfig {
* values.
*/
Map<String, String> getAttributes();

/** Returns devfile that was to generating workspace config, null otherwise. */
Devfile getDevfile();
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.core.model.workspace.devfile.Component;
import org.eclipse.che.api.core.model.workspace.devfile.Endpoint;
import org.eclipse.che.api.workspace.server.devfile.Constants;
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider;
Expand All @@ -51,6 +50,7 @@
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.VolumeImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.Containers;
Expand Down Expand Up @@ -103,7 +103,7 @@ public DockerimageComponentToWorkspaceApplier(
@Override
public void apply(
WorkspaceConfigImpl workspaceConfig,
Component dockerimageComponent,
ComponentImpl dockerimageComponent,
FileContentProvider contentProvider)
throws DevfileException {
checkArgument(workspaceConfig != null, "Workspace config must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException;
import org.eclipse.che.api.workspace.server.model.impl.MachineConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
Expand Down Expand Up @@ -134,7 +135,7 @@ protected KubernetesComponentToWorkspaceApplier(
@Override
public void apply(
WorkspaceConfigImpl workspaceConfig,
Component k8sComponent,
ComponentImpl k8sComponent,
FileContentProvider contentProvider)
throws DevfileException {
checkArgument(workspaceConfig != null, "Workspace config must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.api.core.model.workspace.devfile.Component;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ComponentImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
Expand Down Expand Up @@ -124,8 +127,30 @@ public void apply(

Collection<CommandImpl> pluginRelatedCommands = commandsResolver.resolve(chePlugin);

Optional<ComponentImpl> pluginRelatedComponentOpt =
k8sEnv
.getDevfile()
.getComponents()
.stream()
.filter(c -> chePlugin.getId().equals(c.getId()))
.findAny();
if (!pluginRelatedComponentOpt.isPresent()) {
throw new InfrastructureException(
"The downloaded plugin configuration does not have the "
+ "corresponding component in devfile");
}

ComponentImpl pluginRelatedComponent = pluginRelatedComponentOpt.get();

for (CheContainer container : chePlugin.getContainers()) {
addSidecar(pod, container, chePlugin, k8sEnv, pluginRelatedCommands, runtimeIdentity);
addSidecar(
pod,
container,
chePlugin,
k8sEnv,
pluginRelatedCommands,
pluginRelatedComponent,
runtimeIdentity);
}
}

Expand Down Expand Up @@ -202,6 +227,7 @@ private void addSidecar(
ChePlugin chePlugin,
KubernetesEnvironment k8sEnv,
Collection<CommandImpl> sidecarRelatedCommands,
Component pluginRelatedComponent,
RuntimeIdentity runtimeIdentity)
throws InfrastructureException {

Expand All @@ -222,11 +248,8 @@ private void addSidecar(
.setContainer(k8sContainer)
.setContainerEndpoints(containerEndpoints)
.setDefaultSidecarMemorySizeAttribute(defaultSidecarMemoryLimitBytes)
.setAttributes(k8sEnv.getAttributes())
.setProjectsRootPathEnvVar(projectsRootEnvVariableProvider.get(runtimeIdentity))
.setPluginPublisher(chePlugin.getPublisher())
.setPluginName(chePlugin.getName())
.setPluginId(chePlugin.getId())
.setComponent(pluginRelatedComponent)
.build();

InternalMachineConfig machineConfig = machineResolver.resolve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,20 @@

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toMap;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.DEVFILE_COMPONENT_ALIAS_ATTRIBUTE;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import static org.eclipse.che.api.workspace.server.devfile.Constants.EDITOR_COMPONENT_ALIAS_WORKSPACE_ATTRIBUTE;
import static org.eclipse.che.api.workspace.server.devfile.Constants.PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE;
import static org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME;
import static org.eclipse.che.api.workspace.shared.Constants.SIDECAR_ENV_VARIABLES_ATTR_TEMPLATE;
import static org.eclipse.che.api.workspace.shared.Constants.SIDECAR_MEMORY_LIMIT_ATTR_TEMPLATE;

import io.fabric8.kubernetes.api.model.Container;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.core.model.workspace.devfile.Component;
import org.eclipse.che.api.core.model.workspace.devfile.Env;
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.VolumeImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
Expand All @@ -47,105 +41,58 @@
/** @author Oleksandr Garagatyi */
public class MachineResolver {

private final String pluginPublisherAndName;
private final String pluginId;
private final Container container;
private final CheContainer cheContainer;
private final String defaultSidecarMemoryLimitBytes;
private final List<ChePluginEndpoint> containerEndpoints;
private Map<String, String> wsAttributes;
private final Pair<String, String> projectsRootPathEnvVar;
private final Component component;

public MachineResolver(
String pluginPublisher,
String pluginName,
String pluginId,
Pair<String, String> projectsRootPathEnvVar,
Container container,
CheContainer cheContainer,
String defaultSidecarMemoryLimitBytes,
List<ChePluginEndpoint> containerEndpoints,
Map<String, String> wsAttributes) {
this.pluginPublisherAndName = pluginPublisher + "/" + pluginName;
this.pluginId = pluginId;
Component component) {
this.container = container;
this.cheContainer = cheContainer;
this.defaultSidecarMemoryLimitBytes = defaultSidecarMemoryLimitBytes;
this.containerEndpoints = containerEndpoints;
this.wsAttributes = wsAttributes != null ? wsAttributes : Collections.emptyMap();
this.projectsRootPathEnvVar = projectsRootPathEnvVar;
this.component = component;
}

public InternalMachineConfig resolve() throws InfrastructureException {
InternalMachineConfig machineConfig =
new InternalMachineConfig(
null,
toServers(containerEndpoints),
toEnvVariables(wsAttributes),
toMachineAttributes(pluginId, wsAttributes),
component.getEnv().stream().collect(Collectors.toMap(Env::getName, Env::getValue)),
resolveMachineAttributes(),
toWorkspaceVolumes(cheContainer));

normalizeMemory(container, machineConfig);
return machineConfig;
}

private Map<String,String> toEnvVariables(Map<String,String> wsAttributes) {
String envVars = wsAttributes
.get(format(SIDECAR_ENV_VARIABLES_ATTR_TEMPLATE, pluginPublisherAndName));
if (isNullOrEmpty(envVars)) {
return null;
}
return Stream.of(envVars.split(","))
// only splitting by 1'st '=' since env value may also contain it
.map(value -> value.split("=", 2))
.collect(toMap(arr -> arr[0], arr -> arr[1]));
}

private Map<String, String> toMachineAttributes(
String pluginId, Map<String, String> wsAttributes) {
private Map<String, String> resolveMachineAttributes() {
Map<String, String> attributes = new HashMap<>();

Optional<String> pluginAlias = findPluginAlias(pluginId, wsAttributes);
pluginAlias.ifPresent(s -> attributes.put(DEVFILE_COMPONENT_ALIAS_ATTRIBUTE, s));

return attributes;
}

private Optional<String> findPluginAlias(String pluginId, Map<String, String> wsAttributes) {

List<String> aliases = new ArrayList<>();

String pluginComponentAliases =
wsAttributes.get(PLUGINS_COMPONENTS_ALIASES_WORKSPACE_ATTRIBUTE);
if (!isNullOrEmpty(pluginComponentAliases)) {
aliases.addAll(asList(pluginComponentAliases.split(",")));
}

String editorComponentAlias = wsAttributes.get(EDITOR_COMPONENT_ALIAS_WORKSPACE_ATTRIBUTE);
if (!isNullOrEmpty(editorComponentAlias)) {
aliases.add(editorComponentAlias);
String alias = component.getAlias();
if (alias != null) {
attributes.put(DEVFILE_COMPONENT_ALIAS_ATTRIBUTE, alias);
}

if (aliases.isEmpty()) {
return Optional.empty();
}

return aliases
.stream()
.map(value -> value.split("="))
.filter(arr -> arr[0].equals(pluginId))
.map(arr -> arr[1])
.findAny();
return attributes;
}

private void normalizeMemory(Container container, InternalMachineConfig machineConfig) {
long ramLimit = Containers.getRamLimit(container);
if (ramLimit == 0) {
machineConfig.getAttributes().put(MEMORY_LIMIT_ATTRIBUTE, defaultSidecarMemoryLimitBytes);
}
// Use plugin_publisher/plugin_name to find overriding of memory limit.
String overriddenSidecarMemLimit =
wsAttributes.get(format(SIDECAR_MEMORY_LIMIT_ATTR_TEMPLATE, pluginPublisherAndName));
String overriddenSidecarMemLimit = component.getMemoryLimit();
if (!isNullOrEmpty(overriddenSidecarMemLimit)) {
machineConfig
.getAttributes()
Expand Down Expand Up @@ -174,7 +121,7 @@ private void normalizeMemory(Container container, InternalMachineConfig machineC
+ " the mountSources attribute to true instead and remove the manual volume"
+ " mount in the plugin. After that the mount path of the sources will be"
+ " available automatically in the '%s' environment variable.",
pluginPublisherAndName,
component.getId(),
PROJECTS_VOLUME_NAME,
container.getName(),
volume.getMountPath(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import io.fabric8.kubernetes.api.model.Container;
import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.model.workspace.devfile.Component;
import org.eclipse.che.api.workspace.server.wsplugins.model.CheContainer;
import org.eclipse.che.api.workspace.server.wsplugins.model.ChePluginEndpoint;
import org.eclipse.che.commons.lang.Pair;
Expand All @@ -25,35 +25,25 @@ public class MachineResolverBuilder {
private CheContainer cheContainer;
private String defaultSidecarMemorySizeAttribute;
private List<ChePluginEndpoint> containerEndpoints;
private Map<String, String> wsAttributes;
private Pair<String, String> projectsRootPathEnvVar;
private String pluginPublisher;
private String pluginName;
private String pluginId;
private Component component;

public MachineResolver build() {
if (container == null
|| cheContainer == null
|| defaultSidecarMemorySizeAttribute == null
|| wsAttributes == null
|| containerEndpoints == null
|| projectsRootPathEnvVar == null
|| pluginPublisher == null
|| pluginName == null
|| pluginId == null) {
|| projectsRootPathEnvVar == null) {
throw new IllegalStateException();
}

return new MachineResolver(
pluginPublisher,
pluginName,
pluginId,
projectsRootPathEnvVar,
container,
cheContainer,
defaultSidecarMemorySizeAttribute,
containerEndpoints,
wsAttributes);
component);
}

public MachineResolverBuilder setContainer(Container container) {
Expand All @@ -77,29 +67,14 @@ public MachineResolverBuilder setContainerEndpoints(List<ChePluginEndpoint> cont
return this;
}

public MachineResolverBuilder setAttributes(Map<String, String> wsConfigAttributes) {
this.wsAttributes = wsConfigAttributes;
return this;
}

public MachineResolverBuilder setProjectsRootPathEnvVar(
Pair<String, String> projectsRootPathEnvVar) {
this.projectsRootPathEnvVar = projectsRootPathEnvVar;
return this;
}

public MachineResolverBuilder setPluginPublisher(String pluginPublisher) {
this.pluginPublisher = pluginPublisher;
return this;
}

public MachineResolverBuilder setPluginName(String pluginName) {
this.pluginName = pluginName;
return this;
}

public MachineResolverBuilder setPluginId(String pluginId) {
this.pluginId = pluginId;
public MachineResolverBuilder setComponent(Component component) {
this.component = component;
return this;
}
}
Loading

0 comments on commit 42a04ee

Please sign in to comment.