make it possible to disable labeling the namespaces (#18340)

7.22.x
Michal Vala 2020-11-13 13:06:09 +01:00 committed by GitHub
parent 6a572f1659
commit 220a7e54b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 3 deletions

View File

@ -260,6 +260,9 @@ che.infra.kubernetes.namespace.creation_allowed=true
# Is used by OpenShift infra as well to specify Project
che.infra.kubernetes.namespace.default=<username>-che
# Defines whether che-server should try to label the workspace namespaces.
che.infra.kubernetes.namespace.label=true
# List of labels to find Namespaces/Projects that are used for Che Workspaces.
# They are used to:
# - find prepared Namespaces/Projects for users in combination with `che.infra.kubernetes.namespace.annotations`.

View File

@ -163,6 +163,9 @@ public class KubernetesNamespace {
*/
protected void label(Namespace namespace, Map<String, String> ensureLabels)
throws InfrastructureException {
if (ensureLabels.isEmpty()) {
return;
}
Map<String, String> currentLabels = namespace.getMetadata().getLabels();
Map<String, String> newLabels =
currentLabels != null ? new HashMap<>(currentLabels) : new HashMap<>();
@ -187,7 +190,13 @@ public class KubernetesNamespace {
.build());
} catch (KubernetesClientException kce) {
if (kce.getCode() == 403) {
LOG.debug("Can't label the namespace due to lack of permissions ¯\\_(ツ)_/¯");
LOG.warn(
"Can't label the namespace due to lack of permissions. Grant cluster-wide permissions "
+ "to `get` and `update` the `namespaces` to the `che` service account "
+ "(Che operator might have already prepared a cluster role called "
+ "`che-namespace-editor` for this, depending on its configuration). "
+ "Alternatively, consider disabling the feature by setting "
+ "`che.infra.kubernetes.namepsace.label` to `false`.");
return;
}
throw new InfrastructureException(kce);

View File

@ -93,6 +93,7 @@ public class KubernetesNamespaceFactory {
private final String defaultNamespaceName;
private final boolean allowUserDefinedNamespaces;
protected final boolean labelNamespaces;
protected final Map<String, String> namespaceLabels;
protected final Map<String, String> namespaceAnnotations;
@ -115,6 +116,7 @@ public class KubernetesNamespaceFactory {
@Named("che.infra.kubernetes.namespace.allow_user_defined")
boolean allowUserDefinedNamespaces,
@Named("che.infra.kubernetes.namespace.creation_allowed") boolean namespaceCreationAllowed,
@Named("che.infra.kubernetes.namespace.label") boolean labelNamespaces,
@Named("che.infra.kubernetes.namespace.labels") String namespaceLabels,
@Named("che.infra.kubernetes.namespace.annotations") String namespaceAnnotations,
KubernetesClientFactory clientFactory,
@ -133,6 +135,7 @@ public class KubernetesNamespaceFactory {
this.allowUserDefinedNamespaces = allowUserDefinedNamespaces;
this.preferenceManager = preferenceManager;
this.sharedPool = sharedPool;
this.labelNamespaces = labelNamespaces;
//noinspection UnstableApiUsage
Splitter.MapSplitter csvMapSplitter = Splitter.on(",").withKeyValueSeparator("=");
@ -391,7 +394,7 @@ public class KubernetesNamespaceFactory {
public KubernetesNamespace getOrCreate(RuntimeIdentity identity) throws InfrastructureException {
KubernetesNamespace namespace = get(identity);
namespace.prepare(canCreateNamespace(identity), namespaceLabels);
namespace.prepare(canCreateNamespace(identity), labelNamespaces ? namespaceLabels : emptyMap());
if (!isNullOrEmpty(serviceAccountName)) {
KubernetesWorkspaceServiceAccount workspaceServiceAccount =

View File

@ -163,6 +163,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -186,6 +187,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -214,6 +216,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -240,6 +243,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -263,6 +267,7 @@ public class KubernetesNamespaceFactoryTest {
null,
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -314,6 +319,7 @@ public class KubernetesNamespaceFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -358,6 +364,7 @@ public class KubernetesNamespaceFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -389,6 +396,7 @@ public class KubernetesNamespaceFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -424,6 +432,7 @@ public class KubernetesNamespaceFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -453,6 +462,7 @@ public class KubernetesNamespaceFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -485,6 +495,7 @@ public class KubernetesNamespaceFactoryTest {
"che",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -512,6 +523,7 @@ public class KubernetesNamespaceFactoryTest {
"default",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -548,6 +560,7 @@ public class KubernetesNamespaceFactoryTest {
"default",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -585,6 +598,7 @@ public class KubernetesNamespaceFactoryTest {
"default_ns",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -616,6 +630,7 @@ public class KubernetesNamespaceFactoryTest {
"new-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -649,6 +664,7 @@ public class KubernetesNamespaceFactoryTest {
"new-default",
true,
false,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -683,6 +699,7 @@ public class KubernetesNamespaceFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -721,6 +738,7 @@ public class KubernetesNamespaceFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -790,6 +808,7 @@ public class KubernetesNamespaceFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -847,6 +866,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -867,6 +887,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -891,6 +912,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -919,6 +941,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -950,6 +973,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>-<username>",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -982,6 +1006,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>-<username>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1014,6 +1039,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<workspaceid>-<username>",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1046,6 +1072,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1074,6 +1101,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1104,6 +1132,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1156,6 +1185,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1194,6 +1224,7 @@ public class KubernetesNamespaceFactoryTest {
"defaultNs",
false,
true,
true,
"try_placeholder_here=<username>",
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1217,6 +1248,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -1237,6 +1269,7 @@ public class KubernetesNamespaceFactoryTest {
"che-<userid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,

View File

@ -41,6 +41,7 @@ import io.fabric8.kubernetes.client.Watcher.Action;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Executor;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
@ -367,6 +368,35 @@ public class KubernetesNamespaceTest {
verify(nonNamespaceOperation, never()).createOrReplace(any());
}
@Test
public void testDontTryToLabelNamespaceIfNoNamespacesProvided() throws InfrastructureException {
// given
Map<String, String> existingLabels = Map.of("some", "labels");
Namespace namespace = prepareNamespace(NAMESPACE);
namespace.getMetadata().setLabels(existingLabels);
KubernetesNamespace kubernetesNamespace =
new KubernetesNamespace(clientFactory, cheClientFactory, executor, NAMESPACE, WORKSPACE_ID);
KubernetesClient cheKubeClient = mock(KubernetesClient.class);
lenient().doReturn(cheKubeClient).when(cheClientFactory).create();
NonNamespaceOperation nonNamespaceOperation = mock(NonNamespaceOperation.class);
lenient().doReturn(nonNamespaceOperation).when(cheKubeClient).namespaces();
lenient()
.doAnswer(a -> a.getArgument(0))
.when(nonNamespaceOperation)
.createOrReplace(any(Namespace.class));
// when
kubernetesNamespace.prepare(true, Collections.emptyMap());
// then
assertTrue(
namespace.getMetadata().getLabels().entrySet().containsAll(existingLabels.entrySet()));
verify(nonNamespaceOperation, never()).createOrReplace(any());
}
@Test
public void testDoNotFailWhenNoPermissionsToUpdateNamespace() throws InfrastructureException {
// given

View File

@ -14,6 +14,7 @@ package org.eclipse.che.workspace.infrastructure.openshift.project;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
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 com.google.common.annotations.VisibleForTesting;
@ -71,6 +72,7 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
@Named("che.infra.kubernetes.namespace.allow_user_defined")
boolean allowUserDefinedNamespaces,
@Named("che.infra.kubernetes.namespace.creation_allowed") boolean namespaceCreationAllowed,
@Named("che.infra.kubernetes.namespace.label") boolean labelProjects,
@Named("che.infra.kubernetes.namespace.labels") String projectLabels,
@Named("che.infra.kubernetes.namespace.annotations") String projectAnnotations,
OpenShiftClientFactory clientFactory,
@ -89,6 +91,7 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
defaultNamespaceName,
allowUserDefinedNamespaces,
namespaceCreationAllowed,
labelProjects,
projectLabels,
projectAnnotations,
clientFactory,
@ -111,7 +114,7 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
public OpenShiftProject getOrCreate(RuntimeIdentity identity) throws InfrastructureException {
OpenShiftProject osProject = get(identity);
osProject.prepare(canCreateNamespace(identity), namespaceLabels);
osProject.prepare(canCreateNamespace(identity), labelNamespaces ? namespaceLabels : emptyMap());
if (!isNullOrEmpty(getServiceAccountName())) {
OpenShiftWorkspaceServiceAccount osWorkspaceServiceAccount =

View File

@ -153,6 +153,7 @@ public class OpenShiftProjectFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -179,6 +180,7 @@ public class OpenShiftProjectFactoryTest {
"defaultNs",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -208,6 +210,7 @@ public class OpenShiftProjectFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -236,6 +239,7 @@ public class OpenShiftProjectFactoryTest {
null,
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -273,6 +277,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -311,6 +316,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -345,6 +351,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -389,6 +396,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -427,6 +435,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -465,6 +474,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -495,6 +505,7 @@ public class OpenShiftProjectFactoryTest {
"default",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -541,6 +552,7 @@ public class OpenShiftProjectFactoryTest {
"default",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -582,6 +594,7 @@ public class OpenShiftProjectFactoryTest {
"default-ns",
true,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -615,6 +628,7 @@ public class OpenShiftProjectFactoryTest {
"new-default",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -652,6 +666,7 @@ public class OpenShiftProjectFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -691,6 +706,7 @@ public class OpenShiftProjectFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -732,6 +748,7 @@ public class OpenShiftProjectFactoryTest {
"<workspaceid>",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -785,6 +802,7 @@ public class OpenShiftProjectFactoryTest {
"defaultNs",
false,
true,
true,
NAMESPACE_LABELS,
NAMESPACE_ANNOTATIONS,
clientFactory,
@ -819,6 +837,7 @@ public class OpenShiftProjectFactoryTest {
"che-default",
false,
true,
true,
"try_placeholder_here=<username>",
NAMESPACE_ANNOTATIONS,
clientFactory,