diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java index 31e4c0d36c..79e637d295 100644 --- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java @@ -53,12 +53,14 @@ import io.fabric8.kubernetes.api.model.IntOrString; import io.fabric8.kubernetes.api.model.IntOrStringBuilder; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.PodSpec; +import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServicePort; import io.fabric8.kubernetes.api.model.ServicePortBuilder; import io.fabric8.kubernetes.api.model.ServiceSpec; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; import io.fabric8.kubernetes.api.model.extensions.Ingress; import io.fabric8.kubernetes.api.model.extensions.IngressBackend; import io.fabric8.kubernetes.api.model.extensions.IngressRule; @@ -215,6 +217,14 @@ public class KubernetesInternalRuntimeTest { mockContainer(CONTAINER_NAME_1, EXPOSED_PORT_1), mockContainer(CONTAINER_NAME_2, EXPOSED_PORT_2, INTERNAL_PORT)))); + private final ImmutableMap deploymentsMap = + ImmutableMap.of( + WORKSPACE_POD_NAME, + mockDeployment( + ImmutableList.of( + mockContainer(CONTAINER_NAME_1, EXPOSED_PORT_1), + mockContainer(CONTAINER_NAME_2, EXPOSED_PORT_2, INTERNAL_PORT)))); + @Mock(answer = Answers.RETURNS_MOCKS) private OptionalTracer tracer; @@ -393,6 +403,86 @@ public class KubernetesInternalRuntimeTest { verify(namespace.deployments(), times(1)).stopWatch(); } + @Test + public void startKubernetesEnvironmentWithDeploymentsInsteadOfPods() throws Exception { + when(k8sEnv.getPodsCopy()).thenReturn(emptyMap()); + when(k8sEnv.getDeploymentsCopy()).thenReturn(deploymentsMap); + when(k8sEnv.getSecrets()).thenReturn(ImmutableMap.of("secret", new Secret())); + when(k8sEnv.getConfigMaps()).thenReturn(ImmutableMap.of("configMap", new ConfigMap())); + when(deployments.deploy(any(Deployment.class))) + .thenAnswer( + a -> { + Deployment deployment = (Deployment) a.getArguments()[0]; + return new PodBuilder() + .withMetadata(deployment.getSpec().getTemplate().getMetadata()) + .withSpec(deployment.getSpec().getTemplate().getSpec()) + .build(); + }); + + internalRuntime.start(emptyMap()); + + verify(toolingProvisioner).provision(IDENTITY, startSynchronizer, k8sEnv); + verify(internalEnvironmentProvisioner).provision(IDENTITY, k8sEnv); + verify(kubernetesEnvironmentProvisioner).provision(k8sEnv, IDENTITY); + verify(deployments).deploy(any(Deployment.class)); + verify(ingresses).create(any()); + verify(services).create(any()); + verify(secrets).create(any()); + verify(configMaps).create(any()); + verify(namespace.deployments(), times(1)).watchEvents(any()); + verify(bootstrapper, times(2)).bootstrapAsync(); + verify(eventService, times(4)).publish(any()); + verifyOrderedEventsChains( + new MachineStatusEvent[] {newEvent(M1_NAME, STARTING), newEvent(M1_NAME, RUNNING)}, + new MachineStatusEvent[] {newEvent(M2_NAME, STARTING), newEvent(M2_NAME, RUNNING)}); + verify(serverCheckerFactory).create(IDENTITY, M1_NAME, emptyMap()); + verify(serverCheckerFactory).create(IDENTITY, M2_NAME, emptyMap()); + verify(serversChecker, times(2)).startAsync(any()); + verify(namespace.deployments(), times(1)).stopWatch(); + } + + @Test + public void startKubernetesEnvironmentWithDeploymentsAndPods() throws Exception { + when(k8sEnv.getDeploymentsCopy()).thenReturn(deploymentsMap); + when(k8sEnv.getSecrets()).thenReturn(ImmutableMap.of("secret", new Secret())); + when(k8sEnv.getConfigMaps()).thenReturn(ImmutableMap.of("configMap", new ConfigMap())); + when(deployments.deploy(any(Deployment.class))) + .thenAnswer( + a -> { + Deployment deployment = (Deployment) a.getArguments()[0]; + return new PodBuilder() + .withMetadata(deployment.getSpec().getTemplate().getMetadata()) + .withSpec(deployment.getSpec().getTemplate().getSpec()) + .build(); + }); + + internalRuntime.start(emptyMap()); + + verify(toolingProvisioner).provision(IDENTITY, startSynchronizer, k8sEnv); + verify(internalEnvironmentProvisioner).provision(IDENTITY, k8sEnv); + verify(kubernetesEnvironmentProvisioner).provision(k8sEnv, IDENTITY); + verify(deployments).deploy(any(Deployment.class)); + verify(deployments).deploy(any(Pod.class)); + verify(ingresses).create(any()); + verify(services).create(any()); + verify(secrets).create(any()); + verify(configMaps).create(any()); + verify(namespace.deployments(), times(1)).watchEvents(any()); + verify(bootstrapper, times(2)).bootstrapAsync(); + verify(eventService, times(6)).publish(any()); + verifyOrderedEventsChains( + new MachineStatusEvent[] { + newEvent(M1_NAME, STARTING), newEvent(M1_NAME, STARTING), newEvent(M1_NAME, RUNNING) + }, + new MachineStatusEvent[] { + newEvent(M2_NAME, STARTING), newEvent(M2_NAME, STARTING), newEvent(M2_NAME, RUNNING) + }); + verify(serverCheckerFactory).create(IDENTITY, M1_NAME, emptyMap()); + verify(serverCheckerFactory).create(IDENTITY, M2_NAME, emptyMap()); + verify(serversChecker, times(2)).startAsync(any()); + verify(namespace.deployments(), times(1)).stopWatch(); + } + @Test public void shouldReturnCommandsAfterRuntimeStart() throws Exception { // given @@ -844,18 +934,47 @@ public class KubernetesInternalRuntimeTest { } private static Pod mockPod(List containers) { - final Pod pod = mock(Pod.class); - final PodSpec spec = mock(PodSpec.class); - mockName(WORKSPACE_POD_NAME, pod); - when(spec.getContainers()).thenReturn(containers); - when(pod.getSpec()).thenReturn(spec); - when(pod.getMetadata().getLabels()) - .thenReturn( - ImmutableMap.of( - POD_SELECTOR, WORKSPACE_POD_NAME, CHE_ORIGINAL_NAME_LABEL, WORKSPACE_POD_NAME)); + final Pod pod = + new PodBuilder() + .withNewMetadata() + .withName(WORKSPACE_POD_NAME) + .withLabels( + ImmutableMap.of( + POD_SELECTOR, WORKSPACE_POD_NAME, CHE_ORIGINAL_NAME_LABEL, WORKSPACE_POD_NAME)) + .endMetadata() + .withNewSpec() + .withContainers(containers) + .endSpec() + .build(); return pod; } + private static Deployment mockDeployment(List containers) { + final Deployment deployment = + new DeploymentBuilder() + .withNewMetadata() + .withName(WORKSPACE_POD_NAME) + .withLabels( + ImmutableMap.of( + POD_SELECTOR, WORKSPACE_POD_NAME, CHE_ORIGINAL_NAME_LABEL, WORKSPACE_POD_NAME)) + .endMetadata() + .withNewSpec() + .withNewTemplate() + .withNewSpec() + .withContainers(containers) + .endSpec() + .withNewMetadata() + .withName(WORKSPACE_POD_NAME) + .withLabels( + ImmutableMap.of( + POD_SELECTOR, WORKSPACE_POD_NAME, CHE_ORIGINAL_NAME_LABEL, WORKSPACE_POD_NAME)) + .endMetadata() + .endTemplate() + .endSpec() + .build(); + return deployment; + } + private static Service mockService() { final Service service = mock(Service.class); final ServiceSpec spec = mock(ServiceSpec.class); diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/UniqueNamesProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/UniqueNamesProvisionerTest.java index 805baac464..8fb7d782e3 100644 --- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/UniqueNamesProvisionerTest.java +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/UniqueNamesProvisionerTest.java @@ -17,11 +17,24 @@ import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; +import com.google.common.collect.ImmutableList; 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.Container; +import io.fabric8.kubernetes.api.model.ContainerBuilder; +import io.fabric8.kubernetes.api.model.EnvFromSource; +import io.fabric8.kubernetes.api.model.EnvFromSourceBuilder; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.EnvVarBuilder; 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.Volume; +import io.fabric8.kubernetes.api.model.VolumeBuilder; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; import io.fabric8.kubernetes.api.model.extensions.Ingress; import io.fabric8.kubernetes.api.model.extensions.IngressBuilder; import java.util.HashMap; @@ -44,6 +57,10 @@ public class UniqueNamesProvisionerTest { private static final String WORKSPACE_ID = "workspace37"; private static final String POD_NAME = "testPod"; + private static final String DEPLOYMENT_NAME = "testDeployment"; + private static final String CONFIGMAP_NAME = "testConfigMap"; + private static final String CONFIGMAP_KEY = "testConfigMapKey"; + private static final String CONFIGMAP_VALUE = "testConfigMapValue"; private static final String INGRESS_NAME = "testIngress"; @Mock private KubernetesEnvironment k8sEnv; @@ -71,6 +88,174 @@ public class UniqueNamesProvisionerTest { assertEquals(podMetadata.getLabels().get(CHE_ORIGINAL_NAME_LABEL), POD_NAME); } + @Test + public void provideUniqueDeploymentsName() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + Deployment deployment = newDeployment(); + doReturn(ImmutableMap.of(DEPLOYMENT_NAME, deployment)).when(k8sEnv).getDeploymentsCopy(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + ObjectMeta deploymentMetadata = deployment.getMetadata(); + assertNotEquals(deploymentMetadata.getName(), DEPLOYMENT_NAME); + assertEquals(deploymentMetadata.getLabels().get(CHE_ORIGINAL_NAME_LABEL), DEPLOYMENT_NAME); + } + + @Test + public void provideUniqueConfigMapName() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + ConfigMap configMap = newConfigMap(); + doReturn(ImmutableMap.of(CONFIGMAP_NAME, configMap)).when(k8sEnv).getConfigMaps(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + ObjectMeta configMapMetadata = configMap.getMetadata(); + assertNotEquals(configMapMetadata.getName(), CONFIGMAP_NAME); + assertEquals(configMapMetadata.getLabels().get(CHE_ORIGINAL_NAME_LABEL), CONFIGMAP_NAME); + } + + @Test + public void rewritePodConfigMapEnv() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + ConfigMap configMap = newConfigMap(); + doReturn(ImmutableMap.of(CONFIGMAP_NAME, configMap)).when(k8sEnv).getConfigMaps(); + + EnvVar envVar = + new EnvVarBuilder() + .withNewValueFrom() + .withNewConfigMapKeyRef() + .withName(CONFIGMAP_NAME) + .withKey(CONFIGMAP_KEY) + .endConfigMapKeyRef() + .endValueFrom() + .build(); + Container container = new ContainerBuilder().withEnv(envVar).build(); + Pod pod = newPod(); + pod.getSpec().setContainers(ImmutableList.of(container)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + String newConfigMapName = configMap.getMetadata().getName(); + EnvVar newEnvVar = container.getEnv().iterator().next(); + assertEquals(newEnvVar.getValueFrom().getConfigMapKeyRef().getName(), newConfigMapName); + } + + @Test + public void doesNotRewritePodConfigMapEnvWhenNoConfigMap() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + EnvVar envVar = + new EnvVarBuilder() + .withNewValueFrom() + .withNewConfigMapKeyRef() + .withName(CONFIGMAP_NAME) + .withKey(CONFIGMAP_KEY) + .endConfigMapKeyRef() + .endValueFrom() + .build(); + Container container = new ContainerBuilder().withEnv(envVar).build(); + Pod pod = newPod(); + pod.getSpec().setContainers(ImmutableList.of(container)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + EnvVar newEnvVar = container.getEnv().iterator().next(); + assertEquals(newEnvVar.getValueFrom().getConfigMapKeyRef().getName(), CONFIGMAP_NAME); + } + + @Test + public void rewritePodConfigMapEnvFrom() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + ConfigMap configMap = newConfigMap(); + doReturn(ImmutableMap.of(CONFIGMAP_NAME, configMap)).when(k8sEnv).getConfigMaps(); + + EnvFromSource envFrom = + new EnvFromSourceBuilder() + .withNewConfigMapRef() + .withName(CONFIGMAP_NAME) + .endConfigMapRef() + .build(); + Container container = new ContainerBuilder().withEnvFrom(envFrom).build(); + Pod pod = newPod(); + pod.getSpec().setContainers(ImmutableList.of(container)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + String newConfigMapName = configMap.getMetadata().getName(); + EnvFromSource newEnvFromSource = container.getEnvFrom().iterator().next(); + assertEquals(newEnvFromSource.getConfigMapRef().getName(), newConfigMapName); + } + + @Test + public void doesNotRewritePodConfigMapEnvFromWhenNoConfigMap() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + EnvFromSource envFrom = + new EnvFromSourceBuilder() + .withNewConfigMapRef() + .withName(CONFIGMAP_NAME) + .endConfigMapRef() + .build(); + Container container = new ContainerBuilder().withEnvFrom(envFrom).build(); + Pod pod = newPod(); + pod.getSpec().setContainers(ImmutableList.of(container)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + EnvFromSource newEnvFromSource = container.getEnvFrom().iterator().next(); + assertEquals(newEnvFromSource.getConfigMapRef().getName(), CONFIGMAP_NAME); + } + + @Test + public void rewritePodConfigMapVolumes() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + ConfigMap configMap = newConfigMap(); + doReturn(ImmutableMap.of(CONFIGMAP_NAME, configMap)).when(k8sEnv).getConfigMaps(); + + Volume volume = + new VolumeBuilder().withNewConfigMap().withName(CONFIGMAP_NAME).endConfigMap().build(); + Pod pod = newPod(); + pod.getSpec().setVolumes(ImmutableList.of(volume)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + String newConfigMapName = configMap.getMetadata().getName(); + Volume newVolume = pod.getSpec().getVolumes().iterator().next(); + assertEquals(newVolume.getConfigMap().getName(), newConfigMapName); + } + + @Test + public void doesNotRewritePodConfigMapVolumesWhenNoConfigMap() throws Exception { + when(runtimeIdentity.getWorkspaceId()).thenReturn(WORKSPACE_ID); + + Volume volume = + new VolumeBuilder().withNewConfigMap().withName(CONFIGMAP_NAME).endConfigMap().build(); + Pod pod = newPod(); + pod.getSpec().setVolumes(ImmutableList.of(volume)); + PodData podData = new PodData(pod.getSpec(), pod.getMetadata()); + doReturn(ImmutableMap.of(POD_NAME, podData)).when(k8sEnv).getPodsData(); + + uniqueNamesProvisioner.provision(k8sEnv, runtimeIdentity); + + Volume newVolume = pod.getSpec().getVolumes().iterator().next(); + assertEquals(newVolume.getConfigMap().getName(), CONFIGMAP_NAME); + } + @Test public void provideUniqueIngressesNames() throws Exception { final HashMap ingresses = new HashMap<>(); @@ -88,6 +273,32 @@ public class UniqueNamesProvisionerTest { private static Pod newPod() { return new PodBuilder() .withMetadata(new ObjectMetaBuilder().withName(POD_NAME).build()) + .withNewSpec() + .endSpec() + .build(); + } + + private static Deployment newDeployment() { + return new DeploymentBuilder() + .withNewMetadata() + .withName(DEPLOYMENT_NAME) + .endMetadata() + .withNewSpec() + .withNewTemplate() + .withNewMetadata() + .withName(POD_NAME) + .endMetadata() + .endTemplate() + .endSpec() + .build(); + } + + private static ConfigMap newConfigMap() { + return new ConfigMapBuilder() + .withNewMetadata() + .withName(CONFIGMAP_NAME) + .endMetadata() + .withData(ImmutableMap.of(CONFIGMAP_KEY, CONFIGMAP_VALUE)) .build(); }