diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespace.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespace.java index ee6d74a9255..295ca576739 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespace.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespace.java @@ -142,17 +142,13 @@ public KubernetesNamespace( * @param annotations annotations that should be set to the namespace * @throws InfrastructureException if any exception occurs during namespace preparation or if the * namespace doesn't exist and {@code canCreate} is {@code false}. - * @return {@code true} if the namespace didn't exist and namespace creation was invoked, {@code - * false} if the namespace was already created in the previous calls. */ - boolean prepare(boolean canCreate, Map labels, Map annotations) + void prepare(boolean canCreate, Map labels, Map annotations) throws InfrastructureException { KubernetesClient client = clientFactory.create(workspaceId); Namespace namespace = get(name, client); - boolean needToCreateNewNamespace = false; if (namespace == null) { - needToCreateNewNamespace = true; if (!canCreate) { throw new InfrastructureException( format("Creating the namespace '%s' is not allowed, yet it was not found.", name)); @@ -161,7 +157,6 @@ boolean prepare(boolean canCreate, Map labels, Map namespaceAnnotationsEvaluated = evaluateAnnotationPlaceholders(resolutionCtx); - boolean newNamespace = - namespace.prepare( - canCreateNamespace(identity), - labelNamespaces ? namespaceLabels : emptyMap(), - annotateNamespaces ? namespaceAnnotationsEvaluated : emptyMap()); - if (newNamespace) { + namespace.prepare( + canCreateNamespace(identity), + labelNamespaces ? namespaceLabels : emptyMap(), + annotateNamespaces ? namespaceAnnotationsEvaluated : emptyMap()); + + if (namespace + .secrets() + .get() + .stream() + .noneMatch(s -> s.getMetadata().getName().equals(CREDENTIALS_SECRET_NAME))) { Secret secret = new SecretBuilder() .withType("opaque") diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesSecrets.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesSecrets.java index 64cc09cb120..301c7dad9b6 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesSecrets.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesSecrets.java @@ -76,6 +76,20 @@ public List get(LabelSelector labelSelector) throws InfrastructureExcept } } + /** + * Get all secrets. + * + * @return namespace secrets list + * @throws InfrastructureException when any exception occurs + */ + public List get() throws InfrastructureException { + try { + return clientFactory.create(workspaceId).secrets().inNamespace(namespace).list().getItems(); + } catch (KubernetesClientException e) { + throw new KubernetesInfrastructureException(e); + } + } + /** * Deletes all existing secrets. * diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceFactoryTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceFactoryTest.java index 202cb1e1316..c40cd838bf0 100644 --- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceFactoryTest.java +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceFactoryTest.java @@ -20,7 +20,6 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.SECRETS_ROLE_NAME; import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory.NAMESPACE_TEMPLATE_ATTRIBUTE; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -44,6 +43,7 @@ import io.fabric8.kubernetes.api.model.Namespace; import io.fabric8.kubernetes.api.model.NamespaceBuilder; import io.fabric8.kubernetes.api.model.NamespaceList; +import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.ServiceAccountList; import io.fabric8.kubernetes.api.model.Status; @@ -460,7 +460,7 @@ public void shouldReturnDefaultNamespaceWhenItDoesNotExistAndUserDefinedIsNotAll } @Test - public void shouldCreateCredentialsSecretWhenNamespaceDoesNotExist() throws Exception { + public void shouldCreateCredentialsSecretIfExists() throws Exception { // given namespaceFactory = spy( @@ -479,7 +479,9 @@ public void shouldCreateCredentialsSecretWhenNamespaceDoesNotExist() throws Exce preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); - when(toReturnNamespace.prepare(anyBoolean(), anyMap(), anyMap())).thenReturn(true); + KubernetesSecrets secrets = mock(KubernetesSecrets.class); + when(toReturnNamespace.secrets()).thenReturn(secrets); + when(secrets.get()).thenReturn(Collections.emptyList()); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); MixedOperation mixedOperation = mock(MixedOperation.class); lenient().when(k8sClient.secrets()).thenReturn(mixedOperation); @@ -498,6 +500,41 @@ public void shouldCreateCredentialsSecretWhenNamespaceDoesNotExist() throws Exce Assert.assertEquals(secret.getType(), "opaque"); } + @Test + public void shouldNotCreateCredentialsSecretIfNotExists() throws Exception { + // given + namespaceFactory = + spy( + new KubernetesNamespaceFactory( + "", + "", + "-che", + true, + true, + true, + NAMESPACE_LABELS, + NAMESPACE_ANNOTATIONS, + clientFactory, + cheClientFactory, + userManager, + preferenceManager, + pool)); + KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); + doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); + MixedOperation mixedOperation = mock(MixedOperation.class); + lenient().when(k8sClient.secrets()).thenReturn(mixedOperation); + lenient().when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); + + // when + RuntimeIdentity identity = + new RuntimeIdentityImpl("workspace123", null, USER_ID, "workspace123"); + namespaceFactory.getOrCreate(identity); + + // then + verify(namespaceOperation, never()).create(any()); + } + @Test( expectedExceptions = InfrastructureException.class, expectedExceptionsMessageRegExp = @@ -576,6 +613,7 @@ public void shouldRequireNamespacePriorExistenceIfDifferentFromDefaultAndUserDef preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); // when @@ -608,6 +646,7 @@ public void shouldReturnDefaultNamespaceWhenCreatingIsNotIsNotAllowed() throws E preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); // when @@ -642,6 +681,7 @@ public void shouldPrepareWorkspaceServiceAccountIfItIsConfiguredAndNamespaceIsNo preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getWorkspaceId()).thenReturn("workspace123"); when(toReturnNamespace.getName()).thenReturn("workspace123"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); @@ -680,6 +720,7 @@ public void shouldBindToAllConfiguredClusterRoles() throws Exception { preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getWorkspaceId()).thenReturn("workspace123"); when(toReturnNamespace.getName()).thenReturn("workspace123"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); @@ -751,6 +792,7 @@ public void shouldCreateAndBindCredentialsSecretRole() throws Exception { preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getWorkspaceId()).thenReturn("workspace123"); when(toReturnNamespace.getName()).thenReturn("workspace123"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); @@ -809,6 +851,7 @@ public void shouldCreateExecAndViewRolesAndBindings() throws Exception { preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getWorkspaceId()).thenReturn("workspace123"); when(toReturnNamespace.getName()).thenReturn("workspace123"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); @@ -1143,6 +1186,7 @@ public void shouldHandleProvision() throws InfrastructureException { preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getName()).thenReturn("jondoe-che"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); KubernetesNamespaceMetaImpl namespaceMeta = @@ -1182,6 +1226,7 @@ public void shouldFailToProvisionIfNotAbleToFindNamespace() throws Infrastructur preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getName()).thenReturn("jondoe-cha-cha-cha"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); KubernetesNamespaceMetaImpl namespaceMeta = @@ -1220,6 +1265,7 @@ public void shouldFail2ProvisionIfNotAbleToFindNamespace() throws Infrastructure preferenceManager, pool)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); when(toReturnNamespace.getName()).thenReturn("jondoe-cha-cha-cha"); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); KubernetesNamespaceMetaImpl namespaceMeta = @@ -1296,6 +1342,7 @@ public void testUsernamePlaceholderInAnnotationsIsEvaluated() throws Infrastruct pool)); EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false)); KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class); + prepareNamespace(toReturnNamespace); doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any()); // when @@ -1417,6 +1464,16 @@ private void throwOnTryToGetNamespacesList(Throwable e) throws Exception { when(namespaceList.getItems()).thenThrow(e); } + private void prepareNamespace(KubernetesNamespace namespace) throws InfrastructureException { + KubernetesSecrets secrets = mock(KubernetesSecrets.class); + when(namespace.secrets()).thenReturn(secrets); + Secret secretMock = mock(Secret.class); + ObjectMeta objectMeta = mock(ObjectMeta.class); + when(objectMeta.getName()).thenReturn(CREDENTIALS_SECRET_NAME); + when(secretMock.getMetadata()).thenReturn(objectMeta); + when(secrets.get()).thenReturn(Collections.singletonList(secretMock)); + } + private Namespace createNamespace(String name, String phase) { return new NamespaceBuilder() .withNewMetadata() diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java index 92d6600218d..9d202ade4d0 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java @@ -12,11 +12,8 @@ package org.eclipse.che.workspace.infrastructure.openshift.project; import static java.lang.String.format; -import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.CREDENTIALS_SECRET_NAME; import com.google.common.annotations.VisibleForTesting; -import io.fabric8.kubernetes.api.model.Secret; -import io.fabric8.kubernetes.api.model.SecretBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.openshift.api.model.Project; @@ -104,8 +101,7 @@ public OpenShiftProject( /** * Prepare a project for using. * - *

Preparing includes creating if needed and waiting for default service account, then it - * creates a secret for storing credentials. + *

Preparing includes creating if needed and waiting for default service account. * * @param canCreate defines what to do when the project is not found. The project is created when * {@code true}, otherwise an exception is thrown. @@ -216,14 +212,6 @@ private void create(String projectName, OpenShiftClient osClient) throws Infrast .withName(projectName) .endMetadata() .build()); - Secret secret = - new SecretBuilder() - .withType("opaque") - .withNewMetadata() - .withName(CREDENTIALS_SECRET_NAME) - .endMetadata() - .build(); - osClient.secrets().inNamespace(projectName).create(secret); } catch (KubernetesClientException e) { if (e.getCode() == 403) { LOG.error( diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactory.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactory.java index b193ddec631..220f6330756 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactory.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactory.java @@ -16,11 +16,14 @@ import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta.PHASE_ATTRIBUTE; +import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.CREDENTIALS_SECRET_NAME; import com.google.common.annotations.VisibleForTesting; import com.google.inject.Inject; import com.google.inject.Singleton; import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.api.model.SecretBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.openshift.api.model.Project; import java.util.HashMap; @@ -120,6 +123,26 @@ public OpenShiftProject getOrCreate(RuntimeIdentity identity) throws Infrastruct labelNamespaces ? namespaceLabels : emptyMap(), annotateNamespaces ? namespaceAnnotationsEvaluated : emptyMap()); + // create credentials secret + if (osProject + .secrets() + .get() + .stream() + .noneMatch(s -> s.getMetadata().getName().equals(CREDENTIALS_SECRET_NAME))) { + Secret secret = + new SecretBuilder() + .withType("opaque") + .withNewMetadata() + .withName(CREDENTIALS_SECRET_NAME) + .endMetadata() + .build(); + clientFactory + .createOC() + .secrets() + .inNamespace(identity.getInfrastructureNamespace()) + .create(secret); + } + if (!isNullOrEmpty(getServiceAccountName())) { OpenShiftWorkspaceServiceAccount osWorkspaceServiceAccount = doCreateServiceAccount(osProject.getWorkspaceId(), osProject.getName()); diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactoryTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactoryTest.java index 3d5e47dc06a..910adc758c2 100644 --- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactoryTest.java +++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectFactoryTest.java @@ -16,12 +16,12 @@ import static java.util.Collections.singletonList; import static org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta.DEFAULT_ATTRIBUTE; import static org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta.PHASE_ATTRIBUTE; +import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.CREDENTIALS_SECRET_NAME; import static org.eclipse.che.workspace.infrastructure.openshift.Constants.PROJECT_DESCRIPTION_ANNOTATION; import static org.eclipse.che.workspace.infrastructure.openshift.Constants.PROJECT_DESCRIPTION_ATTRIBUTE; import static org.eclipse.che.workspace.infrastructure.openshift.Constants.PROJECT_DISPLAY_NAME_ANNOTATION; import static org.eclipse.che.workspace.infrastructure.openshift.Constants.PROJECT_DISPLAY_NAME_ATTRIBUTE; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.lenient; @@ -35,9 +35,13 @@ import static org.testng.Assert.assertNull; import com.google.common.collect.ImmutableMap; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Status; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; +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.api.model.Project; import io.fabric8.openshift.api.model.ProjectBuilder; @@ -45,6 +49,7 @@ import io.fabric8.openshift.client.OpenShiftClient; import io.fabric8.openshift.client.dsl.ProjectOperation; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -63,12 +68,15 @@ import org.eclipse.che.inject.ConfigurationException; import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory; import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta; +import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesSecrets; import org.eclipse.che.workspace.infrastructure.kubernetes.util.KubernetesSharedPool; import org.eclipse.che.workspace.infrastructure.openshift.CheServerOpenshiftClientFactory; import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientFactory; import org.eclipse.che.workspace.infrastructure.openshift.provision.OpenShiftStopWorkspaceRoleProvisioner; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; +import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; @@ -529,6 +537,7 @@ public void shouldRequireNamespacePriorExistenceIfDifferentFromDefaultAndUserDef pool, NO_OAUTH_IDENTITY_PROVIDER)); OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + prepareProject(toReturnProject); doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); // when @@ -542,6 +551,92 @@ public void shouldRequireNamespacePriorExistenceIfDifferentFromDefaultAndUserDef verify(toReturnProject).prepare(eq(false), eq(false), any(), any()); } + @Test + public void shouldCreateCredentialsSecretIfNotExists() throws Exception { + // given + projectFactory = + spy( + new OpenShiftProjectFactory( + "", + null, + "-che", + true, + true, + true, + NAMESPACE_LABELS, + NAMESPACE_ANNOTATIONS, + true, + clientFactory, + cheClientFactory, + cheServerOpenshiftClientFactory, + stopWorkspaceRoleProvisioner, + userManager, + preferenceManager, + pool, + NO_OAUTH_IDENTITY_PROVIDER)); + OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); + NonNamespaceOperation namespaceOperation = mock(NonNamespaceOperation.class); + MixedOperation mixedOperation = mock(MixedOperation.class); + KubernetesSecrets secrets = mock(KubernetesSecrets.class); + when(toReturnProject.secrets()).thenReturn(secrets); + when(secrets.get()).thenReturn(Collections.emptyList()); + lenient().when(osClient.secrets()).thenReturn(mixedOperation); + lenient().when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); + + // when + RuntimeIdentity identity = + new RuntimeIdentityImpl("workspace123", null, USER_ID, "workspace123"); + projectFactory.getOrCreate(identity); + + // then + ArgumentCaptor secretsCaptor = ArgumentCaptor.forClass(Secret.class); + verify(namespaceOperation).create(secretsCaptor.capture()); + Secret secret = secretsCaptor.getValue(); + Assert.assertEquals(secret.getMetadata().getName(), CREDENTIALS_SECRET_NAME); + Assert.assertEquals(secret.getType(), "opaque"); + } + + @Test + public void shouldNotCreateCredentialsSecretIfExist() throws Exception { + // given + projectFactory = + spy( + new OpenShiftProjectFactory( + "", + null, + "-che", + true, + true, + true, + NAMESPACE_LABELS, + NAMESPACE_ANNOTATIONS, + true, + clientFactory, + cheClientFactory, + cheServerOpenshiftClientFactory, + stopWorkspaceRoleProvisioner, + userManager, + preferenceManager, + pool, + NO_OAUTH_IDENTITY_PROVIDER)); + OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + prepareProject(toReturnProject); + doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); + NonNamespaceOperation namespaceOperation = mock(NonNamespaceOperation.class); + MixedOperation mixedOperation = mock(MixedOperation.class); + lenient().when(osClient.secrets()).thenReturn(mixedOperation); + lenient().when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); + + // when + RuntimeIdentity identity = + new RuntimeIdentityImpl("workspace123", null, USER_ID, "workspace123"); + projectFactory.getOrCreate(identity); + + // then + verify(namespaceOperation, never()).create(any()); + } + @Test public void shouldPrepareWorkspaceServiceAccountIfItIsConfiguredAndProjectIsNotPredefined() throws Exception { @@ -567,6 +662,7 @@ public void shouldPrepareWorkspaceServiceAccountIfItIsConfiguredAndProjectIsNotP pool, NO_OAUTH_IDENTITY_PROVIDER)); OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + prepareProject(toReturnProject); when(toReturnProject.getWorkspaceId()).thenReturn("workspace123"); when(toReturnProject.getName()).thenReturn("workspace123"); doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); @@ -609,6 +705,7 @@ public void shouldCallStopWorkspaceRoleProvisionWhenIdentityProviderIsDefined() OpenShiftProject toReturnProject = mock(OpenShiftProject.class); when(toReturnProject.getWorkspaceId()).thenReturn("workspace123"); when(toReturnProject.getName()).thenReturn("workspace123"); + prepareProject(toReturnProject); doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); OpenShiftWorkspaceServiceAccount serviceAccount = mock(OpenShiftWorkspaceServiceAccount.class); @@ -649,6 +746,7 @@ public void shouldNotCallStopWorkspaceRoleProvisionWhenIdentityProviderIsDefined pool, NO_OAUTH_IDENTITY_PROVIDER)); OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + prepareProject(toReturnProject); when(toReturnProject.getWorkspaceId()).thenReturn("workspace123"); when(toReturnProject.getName()).thenReturn("workspace123"); doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); @@ -769,6 +867,7 @@ public void testUsernamePlaceholderInAnnotationsIsEvaluated() throws Infrastruct NO_OAUTH_IDENTITY_PROVIDER)); EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false)); OpenShiftProject toReturnProject = mock(OpenShiftProject.class); + prepareProject(toReturnProject); doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any()); // when @@ -806,6 +905,16 @@ private void prepareListedProjects(List projects) throws Exception { when(projectList.getItems()).thenReturn(projects); } + private void prepareProject(OpenShiftProject project) throws InfrastructureException { + KubernetesSecrets secrets = mock(KubernetesSecrets.class); + when(project.secrets()).thenReturn(secrets); + Secret secretMock = mock(Secret.class); + ObjectMeta objectMeta = mock(ObjectMeta.class); + when(objectMeta.getName()).thenReturn(CREDENTIALS_SECRET_NAME); + when(secretMock.getMetadata()).thenReturn(objectMeta); + when(secrets.get()).thenReturn(Collections.singletonList(secretMock)); + } + private void throwOnTryToGetProjectsList(Throwable e) throws Exception { when(projectListResource.list()).thenThrow(e); } diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java index 053874a58a0..1e8ad7820ba 100644 --- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java +++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java @@ -11,7 +11,6 @@ */ package org.eclipse.che.workspace.infrastructure.openshift.project; -import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.CREDENTIALS_SECRET_NAME; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; @@ -30,7 +29,6 @@ import com.google.common.collect.ImmutableList; import io.fabric8.kubernetes.api.model.Namespace; import io.fabric8.kubernetes.api.model.NamespaceBuilder; -import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.ServiceAccount; import io.fabric8.kubernetes.api.model.Status; import io.fabric8.kubernetes.client.KubernetesClient; @@ -124,7 +122,6 @@ public void setUp() throws Exception { lenient().when(namespaceOperation.withName(anyString())).thenReturn(serviceAccountResource); lenient().when(serviceAccountResource.get()).thenReturn(mock(ServiceAccount.class)); lenient().doReturn(projectRequestOperation).when(openShiftClient).projectrequests(); - lenient().doReturn(mixedOperation).when(openShiftClient).secrets(); lenient().doReturn(metadataNested).when(metadataNested).withName(anyString()); openShiftProject = @@ -163,7 +160,6 @@ public void testOpenShiftProjectPreparingWhenProjectExists() throws Exception { // then verify(metadataNested, never()).withName(PROJECT_NAME); - verify(kubernetesClient, never()).secrets(); } @Test @@ -202,7 +198,6 @@ public void testOpenShiftProjectPreparingWhenProjectDoesNotExistWithCheServerSA( final MixedOperation mixedOperation = mock(MixedOperation.class); final NonNamespaceOperation namespaceOperation = mock(NonNamespaceOperation.class); doReturn(mixedOperation).when(openShiftCheServerClient).serviceAccounts(); - doReturn(mixedOperation).when(openShiftCheServerClient).secrets(); when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); when(namespaceOperation.withName(anyString())).thenReturn(serviceAccountResource); when(serviceAccountResource.get()).thenReturn(mock(ServiceAccount.class)); @@ -240,7 +235,6 @@ public void testOpenShiftProjectPreparingRoleBindingWhenProjectDoesNotExistWithC final MixedOperation mixedOperation = mock(MixedOperation.class); final NonNamespaceOperation namespaceOperation = mock(NonNamespaceOperation.class); doReturn(mixedOperation).when(openShiftCheServerClient).serviceAccounts(); - doReturn(mixedOperation).when(openShiftCheServerClient).secrets(); when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); when(namespaceOperation.withName(anyString())).thenReturn(serviceAccountResource); when(serviceAccountResource.get()).thenReturn(mock(ServiceAccount.class)); @@ -266,40 +260,6 @@ public void testOpenShiftProjectPreparingRoleBindingWhenProjectDoesNotExistWithC assertEquals(roleBinding.getUserNames(), ImmutableList.of("jdoe")); } - @Test - public void testOpenShiftProjectPreparingSecretWhenProjectDoesNotExistWithCheServerSA() - throws Exception { - // given - prepareNamespaceGet(PROJECT_NAME); - - Resource resource = prepareProjectResource(PROJECT_NAME); - doThrow(new KubernetesClientException("error", 403, null)).when(resource).get(); - final MixedOperation mixedOperation = mock(MixedOperation.class); - final NonNamespaceOperation namespaceOperation = mock(NonNamespaceOperation.class); - doReturn(mixedOperation).when(openShiftCheServerClient).serviceAccounts(); - doReturn(mixedOperation).when(openShiftCheServerClient).secrets(); - when(mixedOperation.inNamespace(anyString())).thenReturn(namespaceOperation); - when(namespaceOperation.withName(anyString())).thenReturn(serviceAccountResource); - when(serviceAccountResource.get()).thenReturn(mock(ServiceAccount.class)); - doReturn(projectRequestOperation).when(openShiftCheServerClient).projectrequests(); - when(openShiftCheServerClient.roleBindings()).thenReturn(mixedRoleBindingOperation); - lenient() - .when(mixedRoleBindingOperation.inNamespace(anyString())) - .thenReturn(nonNamespaceRoleBindingOperation); - when(openShiftClient.currentUser()) - .thenReturn(new UserBuilder().withNewMetadata().withName("jdoe").endMetadata().build()); - - // when - openShiftProject.prepare(true, true, Map.of(), Map.of()); - - // then - ArgumentCaptor secretsArgumentCaptor = ArgumentCaptor.forClass(Secret.class); - verify(namespaceOperation).create(secretsArgumentCaptor.capture()); - Secret secret = secretsArgumentCaptor.getValue(); - Assert.assertEquals(secret.getType(), "opaque"); - Assert.assertEquals(secret.getMetadata().getName(), CREDENTIALS_SECRET_NAME); - } - @Test(expectedExceptions = InfrastructureException.class) public void throwsExceptionIfNamespaceDoesntExistAndNotAllowedToCreateIt() throws Exception { // given