feat: Added NamespaceProvisioner that creates user information secrets

Signed-off-by: xbaran4 <pbaran@redhat.com>
pull/117/head
xbaran4 2021-09-13 12:30:54 +02:00
parent 6d4ee34fe8
commit af89b16093
3 changed files with 154 additions and 6 deletions

View File

@ -46,5 +46,18 @@ public final class Constants {
public static final String POD_STATUS_PHASE_FAILED = "Failed";
public static final String POD_STATUS_PHASE_SUCCEEDED = "Succeeded";
/** Names for secrets with user information which are used with DevWorkspaces. */
public static final String USER_PROFILE_SECRET_NAME = "user-profile";
public static final String USER_PREFERENCES_SECRET_NAME = "user-preferences";
/** DevWorkspace labels and annotations for mounting secrets and configmaps. */
public static final String DEV_WORKSPACE_MOUNT_LABEL =
"controller.devfile.io/mount-to-devworkspace";
public static final String DEV_WORKSPACE_MOUNT_PATH_ANNOTATION =
"controller.devfile.io/mount-path";
public static final String DEV_WORKSPACE_MOUNT_AS_ANNOTATION = "controller.devfile.io/mount-as";
private Constants() {}
}

View File

@ -27,12 +27,11 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.eclipse.che.api.core.rest.Service;
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.dto.server.DtoFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.dto.KubernetesNamespaceMetaDto;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.NamespaceProvisioner;
/** @author Sergii Leshchenko */
@Api(
@ -43,10 +42,13 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesN
public class KubernetesNamespaceService extends Service {
private final KubernetesNamespaceFactory namespaceFactory;
private final NamespaceProvisioner namespaceProvisioner;
@Inject
public KubernetesNamespaceService(KubernetesNamespaceFactory namespaceFactory) {
public KubernetesNamespaceService(
KubernetesNamespaceFactory namespaceFactory, NamespaceProvisioner namespaceProvisioner) {
this.namespaceFactory = namespaceFactory;
this.namespaceProvisioner = namespaceProvisioner;
}
@GET
@ -82,9 +84,7 @@ public class KubernetesNamespaceService extends Service {
message = "Internal server error occurred during namespace provisioning")
})
public KubernetesNamespaceMetaDto provision() throws InfrastructureException {
return asDto(
namespaceFactory.provision(
new NamespaceResolutionContext(EnvironmentContext.getCurrent().getSubject())));
return asDto(namespaceProvisioner.provision());
}
private KubernetesNamespaceMetaDto asDto(KubernetesNamespaceMeta kubernetesNamespaceMeta) {

View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2012-2021 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/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace;
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 static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.USER_PREFERENCES_SECRET_NAME;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.USER_PROFILE_SECRET_NAME;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import java.util.HashMap;
import java.util.Map;
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.core.notification.EventSubscriber;
import org.eclipse.che.api.user.server.PreferenceManager;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.user.server.event.PostUserPersistedEvent;
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.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NamespaceProvisioner implements EventSubscriber<PostUserPersistedEvent> {
private static final Logger LOG = LoggerFactory.getLogger(NamespaceProvisioner.class);
private final KubernetesNamespaceFactory namespaceFactory;
private final PreferenceManager preferenceManager;
private final KubernetesClientFactory clientFactory;
private final UserManager userManager;
@Inject
public NamespaceProvisioner(
KubernetesNamespaceFactory namespaceFactory,
KubernetesClientFactory clientFactory,
UserManager userManager,
PreferenceManager preferenceManager) {
this.namespaceFactory = namespaceFactory;
this.clientFactory = clientFactory;
this.userManager = userManager;
this.preferenceManager = preferenceManager;
}
public KubernetesNamespaceMeta provision() throws InfrastructureException {
Subject subject = EnvironmentContext.getCurrent().getSubject();
KubernetesNamespaceMeta kubernetesNamespaceMeta =
namespaceFactory.provision(new NamespaceResolutionContext(subject));
try {
createOrUpdateSecrets(userManager.getById(subject.getUserId()));
} catch (NotFoundException | ServerException e) {
LOG.error("Could not find current user. Skipping creation of user information secrets.", e);
} catch (InfrastructureException e) {
LOG.error("There was a failure while creating user information secrets.", e);
}
return kubernetesNamespaceMeta;
};
@Override
public void onEvent(PostUserPersistedEvent event) {
try {
createOrUpdateSecrets(event.getUser());
} catch (InfrastructureException e) {
LOG.error("There was a failure while creating user information secrets.", e);
}
}
private void createOrUpdateSecrets(User user) throws InfrastructureException {
final Map<String, String> userProfileData = new HashMap<>();
userProfileData.put("id", user.getId());
userProfileData.put("name", user.getName());
userProfileData.put("email", user.getEmail());
String namespace =
namespaceFactory.evaluateNamespaceName(
new NamespaceResolutionContext(null, user.getId(), user.getName()));
clientFactory
.create()
.secrets()
.inNamespace(namespace)
.withName(USER_PROFILE_SECRET_NAME)
.createOrReplace(
new SecretBuilder()
.addToData(userProfileData)
.withNewMetadata()
.addToLabels(DEV_WORKSPACE_MOUNT_LABEL, "true")
.addToAnnotations(DEV_WORKSPACE_MOUNT_AS_ANNOTATION, "file")
.addToAnnotations(DEV_WORKSPACE_MOUNT_PATH_ANNOTATION, "/config/user/profile")
.endMetadata()
.build());
Map<String, String> preferences;
try {
preferences = preferenceManager.find(user.getId());
} catch (ServerException e) {
LOG.error(
"Could not find user preferences. Skipping creation of user preferences secrets.", e);
return;
}
clientFactory
.create()
.secrets()
.inNamespace(namespace)
.withName(USER_PREFERENCES_SECRET_NAME)
.createOrReplace(
new SecretBuilder()
.addToData(preferences)
.withNewMetadata()
.addToLabels(DEV_WORKSPACE_MOUNT_LABEL, "true")
.addToAnnotations(DEV_WORKSPACE_MOUNT_AS_ANNOTATION, "file")
.addToAnnotations(DEV_WORKSPACE_MOUNT_PATH_ANNOTATION, "/config/user/preferences")
.endMetadata()
.build());
}
}