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

Also copy the content of the truststore config map to the workspace namespace (port from 7.20.x) #18280

Merged
merged 1 commit into from
Nov 5, 2020
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 @@ -14,18 +14,22 @@
import static com.google.common.base.Strings.isNullOrEmpty;

import com.google.common.base.Splitter;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.VolumeBuilder;
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.CheInstallationLocation;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodRole;
Expand All @@ -43,19 +47,28 @@ public class Openshift4TrustedCAProvisioner {

private final String certificateMountPath;
private final boolean trustedStoreInitialized;
private final String caBundleConfigMap;
private final String configMapName;
private final Map<String, String> configMapLabelKeyValue;
private final CheServerKubernetesClientFactory cheServerClientFactory;
private final String installationLocationNamespace;

@Inject
public Openshift4TrustedCAProvisioner(
@Nullable @Named("che.trusted_ca_bundles_configmap") String caBundleConfigMap,
@Named("che.infra.openshift.trusted_ca_bundles_config_map") String configMapName,
@Named("che.infra.openshift.trusted_ca_bundles_config_map_labels") String configMapLabel,
@Named("che.infra.openshift.trusted_ca_bundles_mount_path") String certificateMountPath) {
@Named("che.infra.openshift.trusted_ca_bundles_mount_path") String certificateMountPath,
CheInstallationLocation cheInstallationLocation,
CheServerKubernetesClientFactory cheServerClientFactory)
throws InfrastructureException {
this.cheServerClientFactory = cheServerClientFactory;
this.trustedStoreInitialized = !isNullOrEmpty(caBundleConfigMap);
this.configMapName = configMapName;
this.caBundleConfigMap = caBundleConfigMap;
this.certificateMountPath = certificateMountPath;
this.configMapLabelKeyValue = Splitter.on(",").withKeyValueSeparator("=").split(configMapLabel);
this.installationLocationNamespace = cheInstallationLocation.getInstallationLocationNamespace();
}

public boolean isTrustedStoreInitialized() {
Expand All @@ -67,9 +80,22 @@ public void provision(KubernetesEnvironment k8sEnv, OpenShiftProject project)
if (!trustedStoreInitialized) {
return;
}
ConfigMap configMap =
cheServerClientFactory
.create()
.configMaps()
.inNamespace(installationLocationNamespace)
.withName(caBundleConfigMap)
.get();

if (configMap == null) {
return;
}

Optional<ConfigMap> existing = project.configMaps().get(configMapName);

if (!project.configMaps().get(configMapName).isPresent()) {
// create new map
if (!existing.isPresent() || !existing.get().getData().equals(configMap.getData())) {
// create or renew map
k8sEnv
.getConfigMaps()
.put(
Expand All @@ -78,10 +104,14 @@ public void provision(KubernetesEnvironment k8sEnv, OpenShiftProject project)
.withMetadata(
new ObjectMetaBuilder()
.withName(configMapName)
.withAnnotations(configMap.getMetadata().getAnnotations())
.withLabels(configMapLabelKeyValue)
.build())
.withApiVersion(configMap.getApiVersion())
.withData(configMap.getData())
.build());
}

for (PodData pod : k8sEnv.getPodsData().values()) {
if (pod.getRole() == PodRole.DEPLOYMENT) {
if (pod.getSpec()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,34 @@
package org.eclipse.che.workspace.infrastructure.openshift.provision;

import static com.google.common.collect.ImmutableMap.of;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import com.google.common.collect.ImmutableMap;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ConfigMapList;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
import io.fabric8.kubernetes.api.model.DoneableConfigMap;
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.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.openshift.client.OpenShiftClient;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.CheInstallationLocation;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientFactory;
import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProject;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
Expand All @@ -48,12 +56,41 @@ public class Openshift4TrustedCAProvisionerTest {
private static final String CERTIFICATE_MOUNT_PATH = "/certs";
private static final String CONFIGMAP_KEY = "testConfigMapKey";
private static final String CONFIGMAP_VALUE = "testConfigMapValue";
private static final String CHE_SERVER_NAMESPACE = "testCheServerNamespace";
private static final String INJECTED_CA_BUNDLE_KEY = "ca-bundle.crt";
private static final String INJECTED_CA_BUNDLE_VALUE = "ca-bundle.crt.content";
private static final String MANUAL_CA_BUNDLE_KEY = "manual-ca.crt";
private static final String MANUAL_CA_BUNDLE_VALUE = "maunal-ca.crt.content";

@Mock OpenShiftClientFactory clientFactory;
@Mock CheServerKubernetesClientFactory clientFactory;

@Mock private KubernetesEnvironment k8sEnv;
@Mock private OpenShiftProject openShiftProject;
@Mock private KubernetesConfigsMaps kubernetesConfigsMaps;
@Mock private CheInstallationLocation cheInstallationLocation;

@Mock
private MixedOperation<
ConfigMap, ConfigMapList, DoneableConfigMap, Resource<ConfigMap, DoneableConfigMap>>
cheServerConfigMapGetter1;

@Mock
private NonNamespaceOperation<
ConfigMap, ConfigMapList, DoneableConfigMap, Resource<ConfigMap, DoneableConfigMap>>
cheServerConfigMapGetter2;

@Mock private Resource<ConfigMap, DoneableConfigMap> cheServerConfigMapResource;
@Mock private ConfigMap cheServerConfigMap;
@Mock private ObjectMeta cheServerConfigMapMetadata;

private Map<String, String> cheServerConfigMapData =
ImmutableMap.of(
INJECTED_CA_BUNDLE_KEY, INJECTED_CA_BUNDLE_VALUE,
MANUAL_CA_BUNDLE_KEY, MANUAL_CA_BUNDLE_VALUE);

private Map<String, String> cheServerConfigMapAnnotations =
ImmutableMap.of(
"testCheServerConfigMapAnnotationsKey", "testCheServerConfigMapAnnotationsValue");

@Mock private OpenShiftClient k8sClient;

Expand All @@ -63,35 +100,68 @@ public class Openshift4TrustedCAProvisionerTest {

@BeforeMethod
public void setup() throws Exception {
lenient().when(clientFactory.createOC()).thenReturn(k8sClient);
lenient().when(clientFactory.create()).thenReturn(k8sClient);
lenient().when(openShiftProject.configMaps()).thenReturn(kubernetesConfigsMaps);
lenient()
.when(cheInstallationLocation.getInstallationLocationNamespace())
.thenReturn(CHE_SERVER_NAMESPACE);
lenient().when(k8sEnv.getConfigMaps()).thenReturn(envConfigMaps);
lenient().when(k8sClient.configMaps()).thenReturn(cheServerConfigMapGetter1);
lenient()
.when(cheServerConfigMapGetter1.inNamespace(CHE_SERVER_NAMESPACE))
.thenReturn(cheServerConfigMapGetter2);
lenient()
.when(cheServerConfigMapGetter2.withName(anyString()))
.thenReturn(cheServerConfigMapResource);
lenient().when(cheServerConfigMap.getData()).thenReturn(cheServerConfigMapData);
lenient().when(cheServerConfigMap.getMetadata()).thenReturn(cheServerConfigMapMetadata);
lenient()
.when(cheServerConfigMapMetadata.getAnnotations())
.thenReturn(cheServerConfigMapAnnotations);

this.trustedCAProvisioner =
new Openshift4TrustedCAProvisioner(
CONFIGMAP_NAME, CONFIGMAP_NAME, CONFIGMAP_LABELS, CERTIFICATE_MOUNT_PATH);
CONFIGMAP_NAME,
CONFIGMAP_NAME,
CONFIGMAP_LABELS,
CERTIFICATE_MOUNT_PATH,
cheInstallationLocation,
clientFactory);
}

@Test
public void shouldDoNothingIfCAStoreIsNotInitialized() throws Exception {
Openshift4TrustedCAProvisioner localProvisioner =
new Openshift4TrustedCAProvisioner(
null, CONFIGMAP_NAME, CONFIGMAP_LABELS, CERTIFICATE_MOUNT_PATH);
null,
CONFIGMAP_NAME,
CONFIGMAP_LABELS,
CERTIFICATE_MOUNT_PATH,
cheInstallationLocation,
clientFactory);

localProvisioner.provision(k8sEnv, openShiftProject);
verifyZeroInteractions(k8sEnv, openShiftProject, clientFactory, openShiftProject);
verifyZeroInteractions(
k8sEnv, openShiftProject, clientFactory, openShiftProject, clientFactory);
}

@Test
public void shouldProvisionTrustStoreMapAndMountIt() throws Exception {
Pod pod = newPod();
PodData podData = new PodData(pod.getSpec(), pod.getMetadata());
doReturn(of(POD_NAME, podData)).when(k8sEnv).getPodsData();
lenient().when(cheServerConfigMapResource.get()).thenReturn(cheServerConfigMap);

trustedCAProvisioner.provision(k8sEnv, openShiftProject);

assertEquals(envConfigMaps.size(), 1);
assertTrue(envConfigMaps.get(CONFIGMAP_NAME).getMetadata().getLabels().containsKey("foo"));
assertEquals(envConfigMaps.get(CONFIGMAP_NAME).getMetadata().getLabels().get("foo"), "bar");
assertEquals(
envConfigMaps.get(CONFIGMAP_NAME).getMetadata().getAnnotations(),
cheServerConfigMapAnnotations);
assertEquals(envConfigMaps.get(CONFIGMAP_NAME).getData(), cheServerConfigMapData);

PodSpec podSpec = pod.getSpec();
assertEquals(podSpec.getVolumes().size(), 1);
assertEquals(podSpec.getVolumes().get(0).getConfigMap().getName(), CONFIGMAP_NAME);
Expand All @@ -111,14 +181,4 @@ private static Pod newPod() {
.endSpec()
.build();
}

private static ConfigMap newConfigMap() {
return new ConfigMapBuilder()
.withNewMetadata()
.withName(CONFIGMAP_NAME)
.withLabels(of("foo", "bar"))
.endMetadata()
.withData(of(CONFIGMAP_KEY, CONFIGMAP_VALUE))
.build();
}
}