Skip to content

Commit

Permalink
Add devfile property to allow enabling/disabling plugin merging
Browse files Browse the repository at this point in the history
Add attribute 'mergePlugins' to devfile to manually enable/disable plugin
merging in the plugin broker. Default value when no property is present
is controlled by property che.workspace.plugin_broker.default_merge_plugins

Signed-off-by: Angel Misevski <amisevsk@redhat.com>
  • Loading branch information
amisevsk committed Sep 11, 2020
1 parent edfa7ec commit 9bf5f6f
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,12 @@ che.singleport.wildcard_domain.ipless=false
che.workspace.plugin_broker.metadata.image=quay.io/eclipse/che-plugin-metadata-broker:v3.4.0
che.workspace.plugin_broker.artifacts.image=quay.io/eclipse/che-plugin-artifacts-broker:v3.4.0

# Configures the default behavior of the plugin brokers when provisioning plugins into a workspace.
# If set to true, the plugin brokers will attempt to merge plugins when possible (i.e. they run in
# the same sidecar image and do not have conflicting settings). This value is the default setting
# used when the devfile does not specify otherwise, via the "mergePlugins" attribute.
che.workspace.plugin_broker.default_merge_plugins=false

# Docker image of Che plugin broker app that resolves workspace tooling configuration and copies
# plugins dependencies to a workspace
che.workspace.plugin_broker.pull_policy=Always
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ public KubernetesArtifactsBrokerApplier(BrokerEnvironmentFactory<E> brokerEnviro
* broker's configmap, machines, and volumes added in addition to the init container
*/
public void apply(
E workspaceEnvironment, RuntimeIdentity runtimeID, Collection<PluginFQN> pluginFQNs)
E workspaceEnvironment,
RuntimeIdentity runtimeID,
Collection<PluginFQN> pluginFQNs,
boolean mergePlugins)
throws InfrastructureException {

E brokerEnvironment = brokerEnvironmentFactory.createForArtifactsBroker(pluginFQNs, runtimeID);
E brokerEnvironment =
brokerEnvironmentFactory.createForArtifactsBroker(pluginFQNs, runtimeID, mergePlugins);

Map<String, PodData> workspacePods = workspaceEnvironment.getPodsData();
if (workspacePods.size() != 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,16 @@ public List<ChePlugin> getTooling(
StartSynchronizer startSynchronizer,
Collection<PluginFQN> pluginFQNs,
boolean isEphemeral,
boolean mergePlugins,
Map<String, String> startOptions)
throws InfrastructureException {

String workspaceId = identity.getWorkspaceId();
KubernetesNamespace kubernetesNamespace = factory.getOrCreate(identity);
BrokersResult brokersResult = new BrokersResult();

E brokerEnvironment = brokerEnvironmentFactory.createForMetadataBroker(pluginFQNs, identity);
E brokerEnvironment =
brokerEnvironmentFactory.createForMetadataBroker(pluginFQNs, identity, mergePlugins);
if (isEphemeral) {
EphemeralWorkspaceUtility.makeEphemeral(brokerEnvironment.getAttributes());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins;

import static org.eclipse.che.api.workspace.shared.Constants.MERGE_PLUGINS_ATTRIBUTE;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
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.wsplugins.ChePluginsApplier;
Expand Down Expand Up @@ -44,17 +47,20 @@ public class SidecarToolingProvisioner<E extends KubernetesEnvironment> {
private final KubernetesArtifactsBrokerApplier<E> artifactsBrokerApplier;
private final PluginFQNParser pluginFQNParser;
private final PluginBrokerManager<E> pluginBrokerManager;
private final String defaultMergePlugins;

@Inject
public SidecarToolingProvisioner(
Map<String, ChePluginsApplier> workspaceNextAppliers,
KubernetesArtifactsBrokerApplier<E> artifactsBrokerApplier,
PluginFQNParser pluginFQNParser,
PluginBrokerManager<E> pluginBrokerManager) {
PluginBrokerManager<E> pluginBrokerManager,
@Named("che.workspace.plugin_broker.default_merge_plugins") String defaultMergePlugins) {
this.workspaceNextAppliers = ImmutableMap.copyOf(workspaceNextAppliers);
this.artifactsBrokerApplier = artifactsBrokerApplier;
this.pluginFQNParser = pluginFQNParser;
this.pluginBrokerManager = pluginBrokerManager;
this.defaultMergePlugins = defaultMergePlugins;
}

@Traced
Expand All @@ -79,12 +85,20 @@ public void provision(
}

boolean isEphemeral = EphemeralWorkspaceUtility.isEphemeral(environment.getAttributes());
boolean mergePlugins = shouldMergePlugins(environment.getAttributes());
List<ChePlugin> chePlugins =
pluginBrokerManager.getTooling(
identity, startSynchronizer, pluginFQNs, isEphemeral, startOptions);
identity, startSynchronizer, pluginFQNs, isEphemeral, mergePlugins, startOptions);

pluginsApplier.apply(identity, environment, chePlugins);
artifactsBrokerApplier.apply(environment, identity, pluginFQNs);
artifactsBrokerApplier.apply(environment, identity, pluginFQNs, mergePlugins);
LOG.debug("Finished sidecar tooling provisioning workspace '{}'", identity.getWorkspaceId());
}

private boolean shouldMergePlugins(Map<String, String> attributes) {
if (attributes.containsKey(MERGE_PLUGINS_ATTRIBUTE)) {
return "true".equals(attributes.get(MERGE_PLUGINS_ATTRIBUTE));
}
return "true".equals(defaultMergePlugins);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ public BrokerEnvironmentFactory(
* @param runtimeID ID of the runtime the broker would be started
* @return kubernetes environment (or its extension) with the Plugin broker objects
*/
public E createForMetadataBroker(Collection<PluginFQN> pluginFQNs, RuntimeIdentity runtimeID)
public E createForMetadataBroker(
Collection<PluginFQN> pluginFQNs, RuntimeIdentity runtimeID, boolean mergePlugins)
throws InfrastructureException {
BrokersConfigs brokersConfigs = getBrokersConfigs(pluginFQNs, runtimeID, metadataBrokerImage);
BrokersConfigs brokersConfigs =
getBrokersConfigs(pluginFQNs, runtimeID, metadataBrokerImage, mergePlugins);
return doCreate(brokersConfigs);
}

Expand All @@ -116,11 +118,14 @@ public E createForMetadataBroker(Collection<PluginFQN> pluginFQNs, RuntimeIdenti
*
* @param pluginFQNs fully qualified names of plugins that needs to be resolved by the broker
* @param runtimeID ID of the runtime the broker would be started
* @param mergePlugins whether the broker should be configured to merge plugins where possible
* @return kubernetes environment (or its extension) with the Plugin broker objects
*/
public E createForArtifactsBroker(Collection<PluginFQN> pluginFQNs, RuntimeIdentity runtimeID)
public E createForArtifactsBroker(
Collection<PluginFQN> pluginFQNs, RuntimeIdentity runtimeID, boolean mergePlugins)
throws InfrastructureException {
BrokersConfigs brokersConfigs = getBrokersConfigs(pluginFQNs, runtimeID, artifactsBrokerImage);
BrokersConfigs brokersConfigs =
getBrokersConfigs(pluginFQNs, runtimeID, artifactsBrokerImage, mergePlugins);
brokersConfigs
.machines
.values()
Expand All @@ -130,7 +135,10 @@ public E createForArtifactsBroker(Collection<PluginFQN> pluginFQNs, RuntimeIdent
}

protected BrokersConfigs getBrokersConfigs(
Collection<PluginFQN> pluginFQNs, RuntimeIdentity runtimeID, String brokerImage)
Collection<PluginFQN> pluginFQNs,
RuntimeIdentity runtimeID,
String brokerImage,
boolean mergePlugins)
throws InfrastructureException {

String configMapName = generateUniqueName(CONFIG_MAP_NAME_SUFFIX);
Expand All @@ -143,7 +151,8 @@ protected BrokersConfigs getBrokersConfigs(
authEnableEnvVarProvider.get(runtimeID), machineTokenEnvVarProvider.get(runtimeID))
.map(this::asEnvVar)
.collect(Collectors.toList());
Container container = newContainer(runtimeID, envVars, brokerImage, configMapVolume);
Container container =
newContainer(runtimeID, envVars, brokerImage, configMapVolume, mergePlugins);
pod.getSpec().getContainers().add(container);
pod.getSpec().getVolumes().add(newConfigMapVolume(configMapName, configMapVolume));

Expand All @@ -165,9 +174,10 @@ private Container newContainer(
RuntimeIdentity runtimeId,
List<EnvVar> envVars,
String image,
@Nullable String brokerVolumeName) {
@Nullable String brokerVolumeName,
boolean mergePlugins) {
String containerName = generateContainerNameFromImageRef(image);
String[] cmdArgs = getCommandLineArgs(runtimeId).toArray(new String[0]);
String[] cmdArgs = getCommandLineArgs(runtimeId, mergePlugins).toArray(new String[0]);
final ContainerBuilder cb =
new ContainerBuilder()
.withName(containerName)
Expand All @@ -186,22 +196,26 @@ private Container newContainer(
return container;
}

protected List<String> getCommandLineArgs(RuntimeIdentity runtimeId) {
return new ArrayList<String>(
Arrays.asList(
"--push-endpoint",
cheWebsocketEndpoint,
"--runtime-id",
String.format(
"%s:%s:%s",
runtimeId.getWorkspaceId(),
MoreObjects.firstNonNull(runtimeId.getEnvName(), ""),
runtimeId.getOwnerId()),
"--cacert",
certProvisioner.isConfigured() ? certProvisioner.getCertPath() : "",
"--registry-address",
Strings.nullToEmpty(pluginRegistryUrl),
"--merge-plugins"));
protected List<String> getCommandLineArgs(RuntimeIdentity runtimeId, boolean mergePlugins) {
ArrayList<String> args =
new ArrayList<>(
Arrays.asList(
"--push-endpoint",
cheWebsocketEndpoint,
"--runtime-id",
String.format(
"%s:%s:%s",
runtimeId.getWorkspaceId(),
MoreObjects.firstNonNull(runtimeId.getEnvName(), ""),
runtimeId.getOwnerId()),
"--cacert",
certProvisioner.isConfigured() ? certProvisioner.getCertPath() : "",
"--registry-address",
Strings.nullToEmpty(pluginRegistryUrl)));
if (mergePlugins) {
args.add("--merge-plugins");
}
return args;
}

private Pod newPod() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import static org.eclipse.che.workspace.infrastructure.kubernetes.Names.createMachineNameAnnotations;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
Expand Down Expand Up @@ -123,22 +124,22 @@ public void setUp() throws Exception {
.build();
doReturn(brokerEnvironment)
.when(brokerEnvironmentFactory)
.createForArtifactsBroker(any(), any());
.createForArtifactsBroker(any(), any(), anyBoolean());

applier = new KubernetesArtifactsBrokerApplier<>(brokerEnvironmentFactory);
}

@Test
public void shouldAddBrokerMachineToWorkspaceEnvironment() throws Exception {
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs);
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs, false);

assertNotNull(workspaceEnvironment.getMachines());
assertTrue(workspaceEnvironment.getMachines().values().contains(brokerMachine));
}

@Test
public void shouldAddBrokerConfigMapsToWorkspaceEnvironment() throws Exception {
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs);
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs, false);

ConfigMap workspaceConfigMap = workspaceEnvironment.getConfigMaps().get(BROKER_CONFIGMAP_NAME);
assertNotNull(workspaceConfigMap);
Expand All @@ -153,7 +154,7 @@ public void shouldAddBrokerConfigMapsToWorkspaceEnvironment() throws Exception {

@Test
public void shouldAddBrokerAsInitContainerOnWorkspacePod() throws Exception {
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs);
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs, false);

List<Container> initContainers = workspacePod.getSpec().getInitContainers();
assertEquals(initContainers.size(), 1);
Expand All @@ -162,7 +163,7 @@ public void shouldAddBrokerAsInitContainerOnWorkspacePod() throws Exception {

@Test
public void shouldAddBrokerVolumesToWorkspacePod() throws Exception {
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs);
applier.apply(workspaceEnvironment, runtimeID, pluginFQNs, false);

List<Volume> workspaceVolumes = workspacePod.getSpec().getVolumes();
assertEquals(workspaceVolumes.size(), 1);
Expand Down
Loading

0 comments on commit 9bf5f6f

Please sign in to comment.