Skip to content

Commit

Permalink
feat: Removing dependency on the usr, account, profile db tables
Browse files Browse the repository at this point in the history
Signed-off-by: Ilya Buziuk <ibuziuk@redhat.com>
  • Loading branch information
ibuziuk committed Jan 12, 2023
1 parent 0337316 commit a59cc49
Show file tree
Hide file tree
Showing 13 changed files with 35 additions and 514 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down Expand Up @@ -41,10 +41,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.inject.Named;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.user.server.PreferenceManager;
Expand Down Expand Up @@ -275,30 +273,21 @@ private KubernetesNamespaceMeta asNamespaceMeta(Namespace namespace) {
* the context.
*
* @param identity the identity of the workspace runtime
* @param userName the user name
* @return true if the namespace can be created, false if the namespace is expected to already
* exist
* @throws InfrastructureException on failure
*/
protected boolean canCreateNamespace(RuntimeIdentity identity) throws InfrastructureException {
protected boolean canCreateNamespace(RuntimeIdentity identity, String userName)
throws InfrastructureException {
if (!namespaceCreationAllowed) {
return false;
}

// we need to make sure that the provided namespace is indeed the one provided by our
// configuration
User owner;
try {
owner = userManager.getById(identity.getOwnerId());
} catch (NotFoundException | ServerException e) {
throw new InfrastructureException(
"Failed to resolve workspace owner. Cause: " + e.getMessage(), e);
}

String requiredNamespace = identity.getInfrastructureNamespace();

NamespaceResolutionContext resolutionContext =
new NamespaceResolutionContext(
identity.getWorkspaceId(), identity.getOwnerId(), owner.getName());
new NamespaceResolutionContext(identity.getWorkspaceId(), identity.getOwnerId(), userName);

String resolvedDefaultNamespace = evaluateNamespaceName(resolutionContext);

Expand All @@ -320,14 +309,14 @@ public KubernetesNamespace getOrCreate(RuntimeIdentity identity) throws Infrastr
KubernetesNamespace namespace = get(identity);

var subject = EnvironmentContext.getCurrent().getSubject();
var userName = subject.getUserName();
NamespaceResolutionContext resolutionCtx =
new NamespaceResolutionContext(
identity.getWorkspaceId(), subject.getUserId(), subject.getUserName());
new NamespaceResolutionContext(identity.getWorkspaceId(), subject.getUserId(), userName);
Map<String, String> namespaceAnnotationsEvaluated =
evaluateAnnotationPlaceholders(resolutionCtx);

namespace.prepare(
canCreateNamespace(identity),
canCreateNamespace(identity, userName),
labelNamespaces ? namespaceLabels : emptyMap(),
annotateNamespaces ? namespaceAnnotationsEvaluated : emptyMap());

Expand Down Expand Up @@ -515,9 +504,6 @@ private String evalDefaultNamespace(NamespaceResolutionContext resolutionCtx)
"Evaluated the namespace for workspace {} using the namespace default to {}",
resolutionCtx.getWorkspaceId(),
namespace);

recordEvaluatedNamespaceName(namespace, resolutionCtx);

return namespace;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator;

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.singletonMap;
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.GIT_USERDATA_CONFIGMAP_NAME;

Expand All @@ -21,18 +20,13 @@
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.factory.server.scm.GitUserData;
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -80,17 +74,6 @@ public void configure(NamespaceResolutionContext namespaceResolutionContext, Str
"true",
"controller.devfile.io/watch-configmap",
"true");
if (gitUserData == null) {
Subject cheSubject = EnvironmentContext.getCurrent().getSubject();
try {
User user = userManager.getById(cheSubject.getUserId());
if (!isNullOrEmpty(user.getName()) && !isNullOrEmpty(user.getEmail())) {
gitUserData = new GitUserData(user.getName(), user.getEmail());
}
} catch (NotFoundException | ServerException e) {
LOG.error(e.getMessage());
}
}
if (gitUserData != null
&& client
.configMaps()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand All @@ -11,22 +11,10 @@
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator;

import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.DEV_WORKSPACE_MOUNT_AS_ANNOTATION;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.DEV_WORKSPACE_MOUNT_LABEL;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.DEV_WORKSPACE_MOUNT_PATH_ANNOTATION;

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.KubernetesClientException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.PreferenceManager;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
Expand All @@ -39,6 +27,7 @@
*
* @author Pavol Baran
*/
@Deprecated
@Singleton
public class UserPreferencesConfigurator implements NamespaceConfigurator {
private static final String USER_PREFERENCES_SECRET_NAME = "user-preferences";
Expand All @@ -59,62 +48,10 @@ public UserPreferencesConfigurator(
this.preferenceManager = preferenceManager;
}

/** 'user-preferences' secret is obsolete and not used anymore by DevWorkspaces */
@Override
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
throws InfrastructureException {
Secret userPreferencesSecret = preparePreferencesSecret(namespaceResolutionContext);

try {
clientFactory
.create()
.secrets()
.inNamespace(namespaceName)
.createOrReplace(userPreferencesSecret);
} catch (KubernetesClientException e) {
throw new InfrastructureException(
"Error occurred while trying to create user preferences secret.", e);
}
}

private Secret preparePreferencesSecret(NamespaceResolutionContext namespaceResolutionContext)
throws InfrastructureException {
Base64.Encoder enc = Base64.getEncoder();
User user;
Map<String, String> preferences;

try {
user = userManager.getById(namespaceResolutionContext.getUserId());
preferences = preferenceManager.find(user.getId());
} catch (NotFoundException | ServerException e) {
throw new InfrastructureException(
String.format(
"Preferences of user with id:%s cannot be retrieved.",
namespaceResolutionContext.getUserId()),
e);
}

if (preferences == null || preferences.isEmpty()) {
throw new InfrastructureException(
String.format(
"Preferences of user with id:%s are empty. Cannot create user preferences secrets.",
namespaceResolutionContext.getUserId()));
}

Map<String, String> preferencesEncoded = new HashMap<>();
preferences.forEach(
(key, value) ->
preferencesEncoded.put(
normalizePreferenceName(key), enc.encodeToString(value.getBytes())));
return new SecretBuilder()
.addToData(preferencesEncoded)
.withNewMetadata()
.withName(USER_PREFERENCES_SECRET_NAME)
.addToLabels(DEV_WORKSPACE_MOUNT_LABEL, "true")
.addToAnnotations(DEV_WORKSPACE_MOUNT_AS_ANNOTATION, "file")
.addToAnnotations(DEV_WORKSPACE_MOUNT_PATH_ANNOTATION, USER_PREFERENCES_SECRET_MOUNT_PATH)
.endMetadata()
.build();
}
throws InfrastructureException {}

/**
* Some preferences names are not compatible with k8s restrictions on key field in secret. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
Expand Down Expand Up @@ -70,21 +67,15 @@ public void configure(NamespaceResolutionContext namespaceResolutionContext, Str

private Secret prepareProfileSecret(NamespaceResolutionContext namespaceResolutionContext)
throws InfrastructureException {
User user;
try {
user = userManager.getById(namespaceResolutionContext.getUserId());
} catch (NotFoundException | ServerException e) {
throw new InfrastructureException(
String.format(
"Could not find current user with id:%s.", namespaceResolutionContext.getUserId()),
e);
}
var userId = namespaceResolutionContext.getUserId();
var userName = namespaceResolutionContext.getUserName();
var userEmail = userName + "@che";

Base64.Encoder enc = Base64.getEncoder();
final Map<String, String> userProfileData = new HashMap<>();
userProfileData.put("id", enc.encodeToString(user.getId().getBytes()));
userProfileData.put("name", enc.encodeToString(user.getName().getBytes()));
userProfileData.put("email", enc.encodeToString(user.getEmail().getBytes()));
userProfileData.put("id", enc.encodeToString(userId.getBytes()));
userProfileData.put("name", enc.encodeToString(userName.getBytes()));
userProfileData.put("email", enc.encodeToString(userEmail.getBytes()));

return new SecretBuilder()
.addToData(userProfileData)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator;

import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.GIT_USERDATA_CONFIGMAP_NAME;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

Expand All @@ -25,9 +23,6 @@
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.factory.server.scm.GitUserData;
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
Expand Down Expand Up @@ -95,19 +90,6 @@ public void createUserdataConfigmapWhenDoesNotExist()
.get());
}

@Test
public void doNothingWhenGitUserDataAndCheUserAreNull()
throws InfrastructureException, ServerException, NotFoundException {
// when
when(userManager.getById(anyString())).thenThrow(new NotFoundException("not found"));
configurator.configure(namespaceResolutionContext, TEST_NAMESPACE_NAME);

// then - don't create the configmap
var configMaps =
serverMock.getClient().configMaps().inNamespace(TEST_NAMESPACE_NAME).list().getItems();
Assert.assertEquals(configMaps.size(), 0);
}

@Test
public void doNothingWhenSecretAlreadyExists()
throws InfrastructureException, InterruptedException, ScmCommunicationException,
Expand Down Expand Up @@ -151,30 +133,4 @@ public void doNothingWhenSecretAlreadyExists()
Assert.assertEquals(configMaps.size(), 1);
Assert.assertEquals(configMaps.get(0).getMetadata().getAnnotations().get("already"), "created");
}

@Test
public void createUserdataConfigmapFromCheUserData()
throws InfrastructureException, ServerException, NotFoundException, InterruptedException {
// given
User user = mock(User.class);
when(user.getName()).thenReturn("test name");
when(user.getEmail()).thenReturn("test@email.com");
when(userManager.getById(anyString())).thenReturn(user);

// when
configurator.configure(namespaceResolutionContext, TEST_NAMESPACE_NAME);

// then create a secret
Assert.assertEquals(serverMock.getLastRequest().getMethod(), "POST");
ConfigMap configMap =
serverMock
.getClient()
.configMaps()
.inNamespace(TEST_NAMESPACE_NAME)
.withName(GIT_USERDATA_CONFIGMAP_NAME)
.get();
Assert.assertNotNull(configMap);
Assert.assertTrue(configMap.getData().get("gitconfig").contains("test name"));
Assert.assertTrue(configMap.getData().get("gitconfig").contains("test@email.com"));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand All @@ -13,14 +13,10 @@

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;

import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
Expand Down Expand Up @@ -84,25 +80,6 @@ public void cleanUp() {
kubernetesServer.after();
}

@Test
public void shouldCreatePreferencesSecret() throws InfrastructureException {
userPreferencesConfigurator.configure(context, USER_NAMESPACE);
List<Secret> secrets =
kubernetesServer.getClient().secrets().inNamespace(USER_NAMESPACE).list().getItems();
assertEquals(secrets.size(), 1);
assertEquals(secrets.get(0).getMetadata().getName(), "user-preferences");
}

@Test(
expectedExceptions = InfrastructureException.class,
expectedExceptionsMessageRegExp =
"Preferences of user with id:" + USER_ID + " cannot be retrieved.")
public void shouldNotCreateSecretOnException() throws ServerException, InfrastructureException {
when(preferenceManager.find(USER_ID)).thenThrow(new ServerException("test exception"));
userPreferencesConfigurator.configure(context, USER_NAMESPACE);
fail("InfrastructureException should have been thrown.");
}

@Test
public void shouldNormalizePreferenceName() {
assertEquals(
Expand Down
Loading

0 comments on commit a59cc49

Please sign in to comment.