OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<OpenShiftEnvironment> { @Override protected OpenShiftEnvironment doCreate( @Nullable InternalRecipe recipe, Map<String, InternalMachineConfig> machines, List<Warning> sourceWarnings) throws InfrastructureException, ValidationException { checkNotNull(recipe, "Null recipe is not supported by openshift environment factory"); List<Warning> warnings = new ArrayList<>(); if (sourceWarnings != null) { warnings.addAll(sourceWarnings); } final List<HasMetadata> list = k8sObjectsParser.parse(recipe); Map<String, Pod> pods = new HashMap<>(); Map<String, Deployment> deployments = new HashMap<>(); Map<String, Service> services = new HashMap<>(); Map<String, ConfigMap> configMaps = new HashMap<>(); Map<String, PersistentVolumeClaim> pvcs = new HashMap<>(); Map<String, Route> routes = new HashMap<>(); Map<String, Secret> secrets = new HashMap<>(); for (HasMetadata object : list) { checkNotNull(object.getKind(), "Environment contains object without specified kind field"); checkNotNull(object.getMetadata(), "%s metadata must not be null", object.getKind()); checkNotNull(object.getMetadata().getName(), "%s name must not be null", object.getKind()); if (object instanceof DeploymentConfig) { throw new ValidationException("Supporting of deployment configs is not implemented yet."); } else if (object instanceof Pod) { putInto(pods, object.getMetadata().getName(), (Pod) object); } else if (object instanceof Deployment) { putInto(deployments, object.getMetadata().getName(), (Deployment) object); } else if (object instanceof Service) { putInto(services, object.getMetadata().getName(), (Service) object); } else if (object instanceof Route) { putInto(routes, object.getMetadata().getName(), (Route) object); } else if (object instanceof PersistentVolumeClaim) { putInto(pvcs, object.getMetadata().getName(), (PersistentVolumeClaim) object); } else if (object instanceof Secret) { putInto(secrets, object.getMetadata().getName(), (Secret) object); } else if (object instanceof ConfigMap) { putInto(configMaps, object.getMetadata().getName(), (ConfigMap) object); } else { throw new ValidationException( format( "Found unknown object type in recipe -- name: '%s', kind: '%s'", object.getMetadata().getName(), object.getKind())); } } if (deployments.size() + pods.size() > 1) { mergePods(pods, deployments, services); } OpenShiftEnvironment osEnv = OpenShiftEnvironment.builder() .setInternalRecipe(recipe) .setMachines(machines) .setWarnings(warnings) .setPods(pods) .setDeployments(deployments) .setServices(services) .setPersistentVolumeClaims(pvcs) .setSecrets(secrets) .setConfigMaps(configMaps) .setRoutes(routes) .build(); envValidator.validate(osEnv); return osEnv; } @Inject  OpenShiftEnvironmentFactory(
      RecipeRetriever recipeRetriever,
      MachineConfigsValidator machinesValidator,
      OpenShiftEnvironmentValidator envValidator,
      KubernetesRecipeParser k8sObjectsParser,
      PodMerger podMerger);   }
@Test public void shouldCreateOpenShiftEnvironmentWithServicesFromRecipe() throws Exception { Service service1 = new ServiceBuilder().withNewMetadata().withName("service1").endMetadata().build(); Service service2 = new ServiceBuilder().withNewMetadata().withName("service2").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(asList(service1, service2)); KubernetesEnvironment osEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(osEnv.getServices().size(), 2); assertEquals(osEnv.getServices().get("service1"), service1); assertEquals(osEnv.getServices().get("service2"), service2); }
@Test public void shouldCreateOpenShiftEnvironmentWithPVCsFromRecipe() throws Exception { PersistentVolumeClaim pvc1 = new PersistentVolumeClaimBuilder().withNewMetadata().withName("pvc1").endMetadata().build(); PersistentVolumeClaim pvc2 = new PersistentVolumeClaimBuilder().withNewMetadata().withName("pvc2").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(asList(pvc1, pvc2)); OpenShiftEnvironment osEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(osEnv.getPersistentVolumeClaims().size(), 2); assertEquals(osEnv.getPersistentVolumeClaims().get("pvc1"), pvc1); assertEquals(osEnv.getPersistentVolumeClaims().get("pvc2"), pvc2); }
@Test public void addRoutesWhenRecipeContainsThem() throws Exception { Route route = new RouteBuilder().withNewMetadata().withName("test-route").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(route)); final OpenShiftEnvironment parsed = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(parsed.getRoutes().size(), 1); assertEquals( parsed.getRoutes().get("test-route").getMetadata().getName(), route.getMetadata().getName()); }
@Test public void addSecretsWhenRecipeContainsThem() throws Exception { Secret secret = new SecretBuilder().withNewMetadata().withName("test-secret").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(secret)); final OpenShiftEnvironment parsed = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(parsed.getSecrets().size(), 1); assertEquals( parsed.getSecrets().get("test-secret").getMetadata().getName(), secret.getMetadata().getName()); }
@Test public void addConfigMapsWhenRecipeContainsThem() throws Exception { ConfigMap configMap = new ConfigMapBuilder().withNewMetadata().withName("test-configmap").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(configMap)); final KubernetesEnvironment parsed = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(parsed.getConfigMaps().size(), 1); assertEquals( parsed.getConfigMaps().values().iterator().next().getMetadata().getName(), configMap.getMetadata().getName()); }
@Test public void addPodsWhenRecipeContainsThem() throws Exception { Pod pod = new PodBuilder() .withNewMetadata() .withName("pod") .endMetadata() .withSpec(new PodSpec()) .build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(pod)); KubernetesEnvironment osEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(osEnv.getPodsCopy().size(), 1); assertEquals(osEnv.getPodsCopy().get("pod"), pod); assertEquals(osEnv.getPodsData().size(), 1); assertEquals(osEnv.getPodsData().get("pod").getMetadata(), pod.getMetadata()); assertEquals(osEnv.getPodsData().get("pod").getSpec(), pod.getSpec()); }
@Test public void addDeploymentsWhenRecipeContainsThem() throws Exception { PodTemplateSpec podTemplate = new PodTemplateSpecBuilder() .withNewMetadata() .withName("deployment-pod") .endMetadata() .withNewSpec() .endSpec() .build(); Deployment deployment = new DeploymentBuilder() .withNewMetadata() .withName("deployment-test") .endMetadata() .withNewSpec() .withTemplate(podTemplate) .endSpec() .build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(deployment)); final KubernetesEnvironment osEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); assertEquals(osEnv.getDeploymentsCopy().size(), 1); assertEquals(osEnv.getDeploymentsCopy().get("deployment-test"), deployment); assertEquals(osEnv.getPodsData().size(), 1); assertEquals( osEnv.getPodsData().get("deployment-test").getMetadata(), podTemplate.getMetadata()); assertEquals(osEnv.getPodsData().get("deployment-test").getSpec(), podTemplate.getSpec()); }
@Test public void shouldUseDeploymentNameAsPodTemplateNameIfItIsMissing() throws Exception { PodTemplateSpec podTemplate = new PodTemplateSpecBuilder().withNewSpec().endSpec().build(); Deployment deployment = new DeploymentBuilder() .withNewMetadata() .withName("deployment-test") .endMetadata() .withNewSpec() .withTemplate(podTemplate) .endSpec() .build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(asList(deployment)); final KubernetesEnvironment k8sEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); Deployment deploymentTest = k8sEnv.getDeploymentsCopy().get("deployment-test"); assertNotNull(deploymentTest); PodTemplateSpec resultPodTemplate = deploymentTest.getSpec().getTemplate(); assertEquals(resultPodTemplate.getMetadata().getName(), "deployment-test"); }
@Test public void shouldMergeDeploymentAndPodIntoOneDeployment() throws Exception { PodTemplateSpec podTemplate = new PodTemplateSpecBuilder() .withNewMetadata() .withName("deployment-pod") .endMetadata() .withNewSpec() .endSpec() .build(); Deployment deployment = new DeploymentBuilder() .withNewMetadata() .withName("deployment-test") .endMetadata() .withNewSpec() .withTemplate(podTemplate) .endSpec() .build(); Pod pod = new PodBuilder() .withNewMetadata() .withName("bare-pod") .endMetadata() .withNewSpec() .endSpec() .build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(asList(deployment, pod)); Deployment merged = createEmptyDeployment("merged"); when(podMerger.merge(any())).thenReturn(merged); final KubernetesEnvironment k8sEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); verify(podMerger).merge(asList(new PodData(pod), new PodData(deployment))); assertEquals(k8sEnv.getPodsData().size(), 1); assertTrue(k8sEnv.getPodsCopy().isEmpty()); assertEquals(k8sEnv.getDeploymentsCopy().size(), 1); assertEquals(k8sEnv.getDeploymentsCopy().get("merged"), merged); }
@Test public void shouldReconfigureServiceToMatchMergedDeployment() throws Exception { Pod pod1 = new PodBuilder() .withNewMetadata() .withName("bare-pod1") .withLabels(ImmutableMap.of("name", "pod1")) .endMetadata() .withNewSpec() .endSpec() .build(); Pod pod2 = new PodBuilder() .withNewMetadata() .withName("bare-pod2") .withLabels(ImmutableMap.of("name", "pod2")) .endMetadata() .withNewSpec() .endSpec() .build(); Service service1 = new ServiceBuilder() .withNewMetadata() .withName("pod1-service") .endMetadata() .withNewSpec() .withSelector(ImmutableMap.of("name", "pod1")) .endSpec() .build(); Service service2 = new ServiceBuilder() .withNewMetadata() .withName("pod2-service") .endMetadata() .withNewSpec() .withSelector(ImmutableMap.of("name", "pod2")) .endSpec() .build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))) .thenReturn(asList(pod1, pod2, service1, service2)); Deployment merged = createEmptyDeployment("merged"); when(podMerger.merge(any())).thenReturn(merged); final KubernetesEnvironment k8sEnv = osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); verify(podMerger).merge(asList(new PodData(pod1), new PodData(pod2))); PodData mergedPodData = k8sEnv.getPodsData().get("merged"); assertEquals(mergedPodData.getMetadata().getLabels().get(DEPLOYMENT_NAME_LABEL), "merged"); assertTrue( k8sEnv .getServices() .values() .stream() .allMatch( s -> ImmutableMap.of(DEPLOYMENT_NAME_LABEL, "merged") .equals(s.getSpec().getSelector()))); }
@Test(expectedExceptions = ValidationException.class) public void exceptionOnRecipeLoadError() throws Exception { when(k8sRecipeParser.parse(any(InternalRecipe.class))) .thenThrow(new ValidationException("Could not parse recipe")); osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); }
@Test( expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "Environment can not contain two 'Service' objects with the same name 'db'") public void exceptionOnObjectsWithTheSameNameAndKind() throws Exception { HasMetadata object1 = new ServiceBuilder().withNewMetadata().withName("db").endMetadata().build(); HasMetadata object2 = new ServiceBuilder().withNewMetadata().withName("db").endMetadata().build(); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(asList(object1, object2)); osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); }
@Test( expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "Environment contains object without specified kind field") public void exceptionOnObjectWithNoKindSpecified() throws Exception { HasMetadata object = mock(HasMetadata.class); when(object.getKind()).thenReturn(null); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(object)); osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); }
@Test( expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "MyObject metadata must not be null") public void exceptionOnObjectWithNoMetadataSpecified() throws Exception { HasMetadata object = mock(HasMetadata.class); when(object.getKind()).thenReturn("MyObject"); when(object.getMetadata()).thenReturn(null); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(object)); osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); }
@Test( expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "MyObject name must not be null") public void exceptionOnObjectWithNoNameSpecified() throws Exception { HasMetadata object = mock(HasMetadata.class); when(object.getKind()).thenReturn("MyObject"); when(object.getMetadata()).thenReturn(new ObjectMetaBuilder().withName(null).build()); when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenReturn(singletonList(object)); osEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList()); }