Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate plugin/editor component environment variables #15435

Merged
merged 3 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@ -272,7 +272,7 @@ private void ensureJwtProxyInjected(KubernetesEnvironment k8sEnv) throws Infrast
}

private InternalMachineConfig createJwtProxyMachine() {
return new InternalMachineConfig(null, emptyMap(), emptyMap(), attributes, null);
return new InternalMachineConfig(emptyMap(), emptyMap(), attributes, null);
}

private Pod createJwtProxyPod() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
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 @@ -122,10 +125,33 @@ public void apply(
chePluginsVolumeApplier.applyVolumes(pod, k8sInitContainer, container.getVolumes(), k8sEnv);
}

Map<String, ComponentImpl> devfilePlugins =
k8sEnv
.getDevfile()
.getComponents()
.stream()
.filter(c -> c.getType().equals("cheEditor") || c.getType().equals("chePlugin"))
.collect(Collectors.toMap(ComponentImpl::getId, Function.identity()));
if (!devfilePlugins.containsKey(chePlugin.getId())) {
throw new InfrastructureException(
String.format(
"The downloaded plugin '%s' configuration does not have the "
+ "corresponding component in devfile. Devfile contains the following cheEditor/chePlugins: %s",
chePlugin.getId(), devfilePlugins.keySet()));
}
ComponentImpl pluginRelatedComponent = devfilePlugins.get(chePlugin.getId());

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

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 +228,7 @@ private void addSidecar(
ChePlugin chePlugin,
KubernetesEnvironment k8sEnv,
Collection<CommandImpl> sidecarRelatedCommands,
Component pluginRelatedComponent,
RuntimeIdentity runtimeIdentity)
throws InfrastructureException {

Expand All @@ -222,11 +249,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,24 +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_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.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 @@ -45,93 +41,57 @@
/** @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),
null,
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> 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 alias = component.getAlias();
if (alias != null) {
attributes.put(DEVFILE_COMPONENT_ALIAS_ATTRIBUTE, alias);
}

String editorComponentAlias = wsAttributes.get(EDITOR_COMPONENT_ALIAS_WORKSPACE_ATTRIBUTE);
if (!isNullOrEmpty(editorComponentAlias)) {
aliases.add(editorComponentAlias);
}

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 @@ -160,7 +120,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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ public InternalMachineConfigBuilder withVolume(String volumeName, String path) {
}

public InternalMachineConfig build() {
return new InternalMachineConfig(
new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), volumes);
return new InternalMachineConfig(new HashMap<>(), new HashMap<>(), new HashMap<>(), volumes);
}
}
}
Loading