AsyncStorageProvisioner { public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) throws InfrastructureException { if (!parseBoolean(k8sEnv.getAttributes().get(ASYNC_PERSIST_ATTRIBUTE))) { return; } if (!COMMON_STRATEGY.equals(pvcStrategy)) { String message = format( "Workspace configuration not valid: Asynchronous storage available only for 'common' PVC strategy, but got %s", pvcStrategy); LOG.warn(message); k8sEnv.addWarning(new WarningImpl(4200, message)); throw new InfrastructureException(message); } if (!isEphemeral(k8sEnv.getAttributes())) { String message = format( "Workspace configuration not valid: Asynchronous storage available only if '%s' attribute set to false", ASYNC_PERSIST_ATTRIBUTE); LOG.warn(message); k8sEnv.addWarning(new WarningImpl(4200, message)); throw new InfrastructureException(message); } String namespace = identity.getInfrastructureNamespace(); String userId = identity.getOwnerId(); KubernetesClient k8sClient = kubernetesClientFactory.create(identity.getWorkspaceId()); String configMapName = namespace + ASYNC_STORAGE_CONFIG; createPvcIfNotExist(k8sClient, namespace, userId); createConfigMapIfNotExist(k8sClient, namespace, configMapName, userId, k8sEnv); createAsyncStoragePodIfNotExist(k8sClient, namespace, configMapName, userId); createStorageServiceIfNotExist(k8sClient, namespace, userId); } @Inject  AsyncStorageProvisioner(
      @Named("che.workspace.sidecar.image_pull_policy") String sidecarImagePullPolicy,
      @Named("che.infra.kubernetes.pvc.quantity") String pvcQuantity,
      @Named("che.infra.kubernetes.async.storage.image") String asyncStorageImage,
      @Named("che.infra.kubernetes.pvc.access_mode") String pvcAccessMode,
      @Named("che.infra.kubernetes.pvc.strategy") String pvcStrategy,
      @Named("che.infra.kubernetes.pvc.name") String pvcName,
      @Named("che.infra.kubernetes.pvc.storage_class_name") String pvcStorageClassName,
      SshManager sshManager,
      KubernetesClientFactory kubernetesClientFactory); void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity);  }
@Test(expectedExceptions = InfrastructureException.class) public void shouldThrowExceptionIfNotCommonStrategy() throws Exception { AsyncStorageProvisioner asyncStorageProvisioner = new AsyncStorageProvisioner( "Always", "10Gi", "org/image:tag", "ReadWriteOnce", randomUUID().toString(), VPC_NAME, "storageClass", sshManager, clientFactory); when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verifyNoMoreInteractions(sshManager); verifyNoMoreInteractions(clientFactory); verifyNoMoreInteractions(identity); }
@Test(expectedExceptions = InfrastructureException.class) public void shouldThrowExceptionIfAsyncStorageForNotEphemeralWorkspace() throws Exception { Map attributes = new HashMap<>(2); attributes.put(ASYNC_PERSIST_ATTRIBUTE, "true"); attributes.put(PERSIST_VOLUMES_ATTRIBUTE, "true"); when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verifyNoMoreInteractions(sshManager); verifyNoMoreInteractions(clientFactory); verifyNoMoreInteractions(identity); }
@Test public void shouldDoNothingIfNotSetAttribute() throws InfrastructureException { when(kubernetesEnvironment.getAttributes()).thenReturn(emptyMap()); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verifyNoMoreInteractions(sshManager); verifyNoMoreInteractions(clientFactory); verifyNoMoreInteractions(identity); }
@Test public void shouldDoNothingIfAttributesAsyncPersistOnly() throws InfrastructureException { when(kubernetesEnvironment.getAttributes()) .thenReturn(singletonMap(PERSIST_VOLUMES_ATTRIBUTE, "false")); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verifyNoMoreInteractions(sshManager); verifyNoMoreInteractions(clientFactory); verifyNoMoreInteractions(identity); }
@Test public void shouldCreateAll() throws InfrastructureException, ServerException, ConflictException { when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); when(clientFactory.create(anyString())).thenReturn(kubernetesClient); when(identity.getWorkspaceId()).thenReturn(WORKSPACE_ID); when(identity.getInfrastructureNamespace()).thenReturn(NAMESPACE); when(identity.getOwnerId()).thenReturn(USER); when(sshManager.getPairs(USER, "internal")).thenReturn(singletonList(sshPair)); when(kubernetesClient.persistentVolumeClaims()).thenReturn(mixedOperationPvc); when(mixedOperationPvc.inNamespace(NAMESPACE)).thenReturn(namespacePvcOperation); when(namespacePvcOperation.withName(VPC_NAME)).thenReturn(pvcResource); when(pvcResource.get()).thenReturn(null); when(kubernetesClient.configMaps()).thenReturn(mixedOperationConfigMap); when(mixedOperationConfigMap.inNamespace(NAMESPACE)).thenReturn(namespaceConfigMapOperation); when(namespaceConfigMapOperation.withName(anyString())).thenReturn(mapResource); when(mapResource.get()).thenReturn(null); when(kubernetesClient.apps()).thenReturn(apps); when(apps.deployments()).thenReturn(mixedOperationDeployment); when(mixedOperationDeployment.inNamespace(NAMESPACE)).thenReturn(namespaceDeploymentOperation); when(namespaceDeploymentOperation.withName(ASYNC_STORAGE)).thenReturn(deploymentResource); when(deploymentResource.get()).thenReturn(null); when(kubernetesClient.services()).thenReturn(mixedOperationService); when(mixedOperationService.inNamespace(NAMESPACE)).thenReturn(namespaceServiceOperation); when(namespaceServiceOperation.withName(ASYNC_STORAGE)).thenReturn(serviceResource); when(serviceResource.get()).thenReturn(null); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verify(identity, times(1)).getInfrastructureNamespace(); verify(identity, times(1)).getOwnerId(); verify(sshManager, times(1)).getPairs(USER, "internal"); verify(sshManager, never()).generatePair(USER, "internal", SSH_KEY_NAME); verify(kubernetesClient.services().inNamespace(NAMESPACE), times(1)).create(any(Service.class)); verify(kubernetesClient.configMaps().inNamespace(NAMESPACE), times(1)) .create(any(ConfigMap.class)); verify(kubernetesClient.apps().deployments().inNamespace(NAMESPACE), times(1)) .create(any(Deployment.class)); verify(kubernetesClient.persistentVolumeClaims().inNamespace(NAMESPACE), times(1)) .create(any(PersistentVolumeClaim.class)); }
@Test public void shouldNotCreateConfigMap() throws InfrastructureException, ServerException, ConflictException { when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); when(clientFactory.create(anyString())).thenReturn(kubernetesClient); when(identity.getWorkspaceId()).thenReturn(WORKSPACE_ID); when(identity.getInfrastructureNamespace()).thenReturn(NAMESPACE); when(identity.getOwnerId()).thenReturn(USER); when(kubernetesClient.persistentVolumeClaims()).thenReturn(mixedOperationPvc); when(mixedOperationPvc.inNamespace(NAMESPACE)).thenReturn(namespacePvcOperation); when(namespacePvcOperation.withName(VPC_NAME)).thenReturn(pvcResource); when(pvcResource.get()).thenReturn(null); when(kubernetesClient.configMaps()).thenReturn(mixedOperationConfigMap); when(mixedOperationConfigMap.inNamespace(NAMESPACE)).thenReturn(namespaceConfigMapOperation); when(namespaceConfigMapOperation.withName(CONFIGMAP_NAME)).thenReturn(mapResource); ObjectMeta meta = new ObjectMeta(); meta.setName(CONFIGMAP_NAME); ConfigMap configMap = new ConfigMap(); configMap.setMetadata(meta); when(mapResource.get()).thenReturn(configMap); when(kubernetesClient.pods()).thenReturn(mixedOperationPod); when(mixedOperationPod.inNamespace(NAMESPACE)).thenReturn(namespacePodOperation); when(namespacePodOperation.withName(ASYNC_STORAGE)).thenReturn(podResource); when(podResource.get()).thenReturn(null); when(kubernetesClient.apps()).thenReturn(apps); when(apps.deployments()).thenReturn(mixedOperationDeployment); when(mixedOperationDeployment.inNamespace(NAMESPACE)).thenReturn(namespaceDeploymentOperation); when(namespaceDeploymentOperation.withName(ASYNC_STORAGE)).thenReturn(deploymentResource); when(deploymentResource.get()).thenReturn(null); when(kubernetesClient.services()).thenReturn(mixedOperationService); when(mixedOperationService.inNamespace(NAMESPACE)).thenReturn(namespaceServiceOperation); when(namespaceServiceOperation.withName(ASYNC_STORAGE)).thenReturn(serviceResource); when(serviceResource.get()).thenReturn(null); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verify(identity, times(1)).getInfrastructureNamespace(); verify(identity, times(1)).getOwnerId(); verify(identity, times(1)).getWorkspaceId(); verify(sshManager, never()).getPairs(USER, "internal"); verify(sshManager, never()).generatePair(USER, "internal", SSH_KEY_NAME); verify(kubernetesClient.services().inNamespace(NAMESPACE), times(1)).create(any(Service.class)); verify(kubernetesClient.configMaps().inNamespace(NAMESPACE), never()) .create(any(ConfigMap.class)); verify(kubernetesClient.apps().deployments().inNamespace(NAMESPACE), times(1)) .create(any(Deployment.class)); verify(kubernetesClient.persistentVolumeClaims().inNamespace(NAMESPACE), times(1)) .create(any(PersistentVolumeClaim.class)); }
@Test public void shouldNotCreatePod() throws InfrastructureException, ServerException, ConflictException { when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); when(clientFactory.create(anyString())).thenReturn(kubernetesClient); when(identity.getWorkspaceId()).thenReturn(WORKSPACE_ID); when(identity.getInfrastructureNamespace()).thenReturn(NAMESPACE); when(identity.getOwnerId()).thenReturn(USER); when(sshManager.getPairs(USER, "internal")).thenReturn(singletonList(sshPair)); when(kubernetesClient.persistentVolumeClaims()).thenReturn(mixedOperationPvc); when(mixedOperationPvc.inNamespace(NAMESPACE)).thenReturn(namespacePvcOperation); when(namespacePvcOperation.withName(VPC_NAME)).thenReturn(pvcResource); when(pvcResource.get()).thenReturn(null); when(kubernetesClient.configMaps()).thenReturn(mixedOperationConfigMap); when(mixedOperationConfigMap.inNamespace(NAMESPACE)).thenReturn(namespaceConfigMapOperation); when(namespaceConfigMapOperation.withName(CONFIGMAP_NAME)).thenReturn(mapResource); when(mapResource.get()).thenReturn(null); when(kubernetesClient.pods()).thenReturn(mixedOperationPod); when(mixedOperationPod.inNamespace(NAMESPACE)).thenReturn(namespacePodOperation); when(namespacePodOperation.withName(ASYNC_STORAGE)).thenReturn(podResource); when(kubernetesClient.apps()).thenReturn(apps); when(apps.deployments()).thenReturn(mixedOperationDeployment); when(mixedOperationDeployment.inNamespace(NAMESPACE)).thenReturn(namespaceDeploymentOperation); when(namespaceDeploymentOperation.withName(ASYNC_STORAGE)).thenReturn(deploymentResource); ObjectMeta meta = new ObjectMeta(); meta.setName(ASYNC_STORAGE); Deployment deployment = new Deployment(); deployment.setMetadata(meta); when(deploymentResource.get()).thenReturn(deployment); when(kubernetesClient.services()).thenReturn(mixedOperationService); when(mixedOperationService.inNamespace(NAMESPACE)).thenReturn(namespaceServiceOperation); when(namespaceServiceOperation.withName(ASYNC_STORAGE)).thenReturn(serviceResource); when(serviceResource.get()).thenReturn(null); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verify(identity, times(1)).getInfrastructureNamespace(); verify(identity, times(1)).getOwnerId(); verify(sshManager, times(1)).getPairs(USER, "internal"); verify(sshManager, never()).generatePair(USER, "internal", SSH_KEY_NAME); verify(kubernetesClient.services().inNamespace(NAMESPACE), times(1)).create(any(Service.class)); verify(kubernetesClient.configMaps().inNamespace(NAMESPACE), times(1)) .create(any(ConfigMap.class)); verify(kubernetesClient.pods().inNamespace(NAMESPACE), never()).create(any(Pod.class)); verify(kubernetesClient.persistentVolumeClaims().inNamespace(NAMESPACE), times(1)) .create(any(PersistentVolumeClaim.class)); }
@Test public void shouldNotCreateService() throws InfrastructureException, ServerException, ConflictException { when(kubernetesEnvironment.getAttributes()).thenReturn(attributes); when(clientFactory.create(anyString())).thenReturn(kubernetesClient); when(identity.getWorkspaceId()).thenReturn(WORKSPACE_ID); when(identity.getInfrastructureNamespace()).thenReturn(NAMESPACE); when(identity.getOwnerId()).thenReturn(USER); when(sshManager.getPairs(USER, "internal")).thenReturn(singletonList(sshPair)); when(kubernetesClient.persistentVolumeClaims()).thenReturn(mixedOperationPvc); when(mixedOperationPvc.inNamespace(NAMESPACE)).thenReturn(namespacePvcOperation); when(namespacePvcOperation.withName(VPC_NAME)).thenReturn(pvcResource); when(pvcResource.get()).thenReturn(null); when(kubernetesClient.configMaps()).thenReturn(mixedOperationConfigMap); when(mixedOperationConfigMap.inNamespace(NAMESPACE)).thenReturn(namespaceConfigMapOperation); when(namespaceConfigMapOperation.withName(CONFIGMAP_NAME)).thenReturn(mapResource); when(mapResource.get()).thenReturn(null); when(kubernetesClient.pods()).thenReturn(mixedOperationPod); when(mixedOperationPod.inNamespace(NAMESPACE)).thenReturn(namespacePodOperation); when(namespacePodOperation.withName(ASYNC_STORAGE)).thenReturn(podResource); when(podResource.get()).thenReturn(null); when(kubernetesClient.apps()).thenReturn(apps); when(apps.deployments()).thenReturn(mixedOperationDeployment); when(mixedOperationDeployment.inNamespace(NAMESPACE)).thenReturn(namespaceDeploymentOperation); when(namespaceDeploymentOperation.withName(ASYNC_STORAGE)).thenReturn(deploymentResource); when(deploymentResource.get()).thenReturn(null); when(kubernetesClient.services()).thenReturn(mixedOperationService); when(mixedOperationService.inNamespace(NAMESPACE)).thenReturn(namespaceServiceOperation); when(namespaceServiceOperation.withName(ASYNC_STORAGE)).thenReturn(serviceResource); ObjectMeta meta = new ObjectMeta(); meta.setName(ASYNC_STORAGE); Service service = new Service(); service.setMetadata(meta); when(serviceResource.get()).thenReturn(service); asyncStorageProvisioner.provision(kubernetesEnvironment, identity); verify(identity, times(1)).getInfrastructureNamespace(); verify(identity, times(1)).getOwnerId(); verify(sshManager, times(1)).getPairs(USER, "internal"); verify(sshManager, never()).generatePair(USER, "internal", SSH_KEY_NAME); verify(kubernetesClient.services().inNamespace(NAMESPACE), never()).create(any(Service.class)); verify(kubernetesClient.configMaps().inNamespace(NAMESPACE), times(1)) .create(any(ConfigMap.class)); verify(kubernetesClient.apps().deployments().inNamespace(NAMESPACE), times(1)) .create(any(Deployment.class)); verify(kubernetesClient.persistentVolumeClaims().inNamespace(NAMESPACE), times(1)) .create(any(PersistentVolumeClaim.class)); }