Skip to content
This repository has been archived by the owner on Mar 17, 2021. It is now read-only.

Commit

Permalink
fixup! fixup! fixup! fixup! fixup! fixup! fixup! rh-che #541: Login t…
Browse files Browse the repository at this point in the history
…o user project using oc CLI in workspace containers
  • Loading branch information
Oleksandr Garagatyi committed Mar 2, 2018
1 parent 8179510 commit b7912c5
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

import static java.lang.String.format;
import static org.slf4j.LoggerFactory.getLogger;
Expand All @@ -53,10 +51,11 @@
*/
@Singleton
public class RhCheInfraEnvironmentProvisioner extends OpenShiftEnvironmentProvisioner {
public static final String TOKEN_VAR = "CHE_OSO_USER_TOKEN";
public static final String CLUSTER_VAR = "CHE_OSO_CLUSTER";
public static final String PROJECT_VAR = "CHE_OSO_PROJECT";

private static final Logger LOG = getLogger(RhCheInfraEnvironmentProvisioner.class);
private static final String TOKEN_VAR = "CHE_OSO_USER_TOKEN";
private static final String CLUSTER_VAR = "CHE_OSO_CLUSTER";
private static final String PROJECT_VAR = "CHE_OSO_PROJECT";

private final OpenshiftUserTokenProvider openshiftUserTokenProvider;
private final TenantDataProvider tenantDataProvider;
Expand Down Expand Up @@ -104,61 +103,50 @@ public void provision(OpenShiftEnvironment osEnv, RuntimeIdentity identity)
Map<String, String> envVars = new HashMap<>();

try {
getSubjectFuture(identity)
.thenApply(subject -> addTokenEnvVar(envVars, subject))
.thenApply(subject -> addTenantEnvVars(envVars, subject))
.thenAccept(aVoid -> injectEnvVars(osEnv, envVars))
.join();
} catch (CompletionException e) {
Subject subject = getSubject(identity);
addTokenEnvVar(envVars, subject);
addTenantEnvVars(envVars, subject);
injectEnvVars(osEnv, envVars);
} catch (InfrastructureException e) {
// oc login injection is not critical - lets continue start of the workspace if failed
LOG.error(e.getLocalizedMessage());
}
}

private CompletableFuture<Subject> getSubjectFuture(RuntimeIdentity identity) {
return new CompletableFuture<>()
.thenApply(
o -> {
try {
return subjectsRegistry.getSubject(identity.getOwnerId());
} catch (NotFoundException e) {
// we can't perform operations without subject
throw new RuntimeException(
"Subject for user ID '"
+ identity.getOwnerId()
+ "' not found in subjects registry");
}
});
private Subject getSubject(RuntimeIdentity identity) throws InfrastructureException {
try {
return subjectsRegistry.getSubject(identity.getOwnerId());
} catch (NotFoundException e) {
// we can't perform operations without subject
throw new InfrastructureException(
"Subject for user ID '" + identity.getOwnerId() + "' not found in subjects registry");
}
}

private Subject addTokenEnvVar(Map<String, String> envVars, Subject subject) {
private void addTokenEnvVar(Map<String, String> envVars, Subject subject) throws InfrastructureException {
try {
String osoToken = openshiftUserTokenProvider.getToken(subject);
if (osoToken == null) {
throw new RuntimeException("OSO token not found for user " + getUserDescription(subject));
throw new InfrastructureException("OSO token not found for user " + getUserDescription(subject));
} else {
envVars.put(TOKEN_VAR, osoToken);
return subject;
}
} catch (InfrastructureException e) {
throw new RuntimeException(
format(
"OSO token retrieval for user '%s' failed with error: %s",
getUserDescription(subject), e.getMessage()));
throw new InfrastructureException(
format("OSO token retrieval for user '%s' failed with error: %s", getUserDescription(subject),
e.getMessage()));
}
}

private Void addTenantEnvVars(Map<String, String> envVars, Subject subject) {
private void addTenantEnvVars(Map<String, String> envVars, Subject subject) throws InfrastructureException {
try {
UserCheTenantData tenantData = tenantDataProvider.getUserCheTenantData(subject, "user");
envVars.put(CLUSTER_VAR, tenantData.getClusterUrl());
envVars.put(PROJECT_VAR, tenantData.getNamespace());
return null;
} catch (InfrastructureException e) {
throw new RuntimeException(
format(
"OSO tenant data retrieval for user '%s' failed with error: %s",
getUserDescription(subject), e.getMessage()));
throw new InfrastructureException(
format("OSO tenant data retrieval for user '%s' failed with error: %s", getUserDescription(subject),
e.getMessage()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,15 @@
*/
package com.redhat.che.multitenant;

import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodSpec;

import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.rest.DefaultHttpJsonRequestFactory;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy;
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.InstallerServersPortProvisioner;
Expand All @@ -29,61 +36,208 @@
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.List;

import static com.google.common.collect.ImmutableMap.of;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

@Listeners(MockitoTestNGListener.class)
public class RhCheInfraEnvironmentProvisionerTest {
private static final String USER_ID = "userId";

private static final String USER_ID = "userId";
private static final String NAMESPACE = "project1";
private static final String CLUSTER_URL = "https://api.starter-us-east-2.openshift.com/";
private static final Subject SUBJECT = new SubjectImpl("name", USER_ID, "keycloakToken", false);
private static final String OSO_TOKEN = "osoToken";

@Mock
OpenShiftUniqueNamesProvisioner uniqueNamesProvisioner;
private OpenShiftUniqueNamesProvisioner uniqueNamesProvisioner;
@Mock
RouteTlsProvisioner routeTlsProvisioner;
private RouteTlsProvisioner routeTlsProvisioner;
@Mock
OpenShiftServersConverter openShiftServersConverter;
private OpenShiftServersConverter openShiftServersConverter;
@Mock
EnvVarsConverter envVarsConverter;
private EnvVarsConverter envVarsConverter;
@Mock
RestartPolicyRewriter restartPolicyRewriter;
private RestartPolicyRewriter restartPolicyRewriter;
@Mock
WorkspaceVolumesStrategy volumesStrategy;
private WorkspaceVolumesStrategy volumesStrategy;
@Mock
RamLimitProvisioner ramLimitProvisioner;
private RamLimitProvisioner ramLimitProvisioner;
@Mock
InstallerServersPortProvisioner installerServersPortProvisioner;
private InstallerServersPortProvisioner installerServersPortProvisioner;
@Mock
LogsVolumeMachineProvisioner logsVolumeMachineProvisioner;
private LogsVolumeMachineProvisioner logsVolumeMachineProvisioner;





@Mock
OpenshiftUserTokenProvider openshiftUserTokenProvider;
private OpenshiftUserTokenProvider openshiftUserTokenProvider;
@Mock
TenantDataProvider tenantDataProvider;
private TenantDataProvider tenantDataProvider;
@Mock
WorkspaceSubjectsRegistry subjectsRegistry;
private WorkspaceSubjectsRegistry subjectsRegistry;
@Mock
RuntimeIdentity runtimeIdentity;
private RuntimeIdentity runtimeIdentity;
@Mock
OpenShiftEnvironment openShiftEnvironment;
private OpenShiftEnvironment openShiftEnvironment;

RhCheInfraEnvironmentProvisioner provisioner;
private List<EnvVar> con1EnvVars;
private List<EnvVar> con2EnvVars;
private List<EnvVar> con3EnvVars;
private RhCheInfraEnvironmentProvisioner provisioner;

@BeforeMethod
public void setUp() throws Exception {
con1EnvVars = new ArrayList<>();
con2EnvVars = new ArrayList<>();
con3EnvVars = new ArrayList<>();

provisioner = new RhCheInfraEnvironmentProvisioner(true, uniqueNamesProvisioner, routeTlsProvisioner,
openShiftServersConverter, envVarsConverter,
restartPolicyRewriter,
volumesStrategy, ramLimitProvisioner,
installerServersPortProvisioner,
logsVolumeMachineProvisioner, openshiftUserTokenProvider,
tenantDataProvider, subjectsRegistry);

Pod pod1 = mock(Pod.class);
Pod pod2 = mock(Pod.class);
PodSpec podSpec1 = mock(PodSpec.class);
PodSpec podSpec2 = mock(PodSpec.class);
Container container1 = mock(Container.class);
Container container2 = mock(Container.class);
Container container3 = mock(Container.class);

when(runtimeIdentity.getOwnerId()).thenReturn(USER_ID);
when(subjectsRegistry.getSubject(USER_ID)).thenReturn(SUBJECT);
when(openshiftUserTokenProvider.getToken(eq(SUBJECT))).thenReturn(OSO_TOKEN);
when(tenantDataProvider.getUserCheTenantData(eq(SUBJECT), eq("user")))
.thenReturn(new UserCheTenantData(NAMESPACE, CLUSTER_URL, null));
when(openShiftEnvironment.getPods()).thenReturn(of("pod1", pod1, "pod2", pod2));
when(pod1.getSpec()).thenReturn(podSpec1);
when(pod2.getSpec()).thenReturn(podSpec2);
when(podSpec1.getContainers()).thenReturn(singletonList(container1));
when(podSpec2.getContainers()).thenReturn(asList(container2, container3));
when(container1.getEnv()).thenReturn(con1EnvVars);
when(container2.getEnv()).thenReturn(con2EnvVars);
when(container3.getEnv()).thenReturn(con3EnvVars);
}

@Test
public void shouldSetEnvVars() throws Exception {
provisioner.provision(openShiftEnvironment, runtimeIdentity);

verifyOcLoginEnvVarsPresence(con1EnvVars);
verifyOcLoginEnvVarsPresence(con2EnvVars);
verifyOcLoginEnvVarsPresence(con3EnvVars);
verify(subjectsRegistry).getSubject(eq(USER_ID));
verify(tenantDataProvider).getUserCheTenantData(eq(SUBJECT), eq("user"));
}

@Test
public void shouldReplaceEnvVarIfItIsPresent() throws Exception {
con2EnvVars.add(new EnvVar(RhCheInfraEnvironmentProvisioner.TOKEN_VAR, "anotherValue", null));

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertEquals(con2EnvVars.size(), 3);
verifyOcLoginEnvVarsPresence(con2EnvVars);
}

@Test
public void shouldPreserveExistingEnvVars() throws Exception {
con3EnvVars.add(new EnvVar("OTHER_VAR", "otherValue", null));

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertEquals(con3EnvVars.size(), 4);
verifyOcLoginEnvVarsPresence(con3EnvVars);
verifyEnvVarPresence("OTHER_VAR", "otherValue", con3EnvVars);
}

@Test
public void shouldNotThrowExceptionIfSubjectFetchingFails() throws Exception {
when(subjectsRegistry.getSubject(anyString())).thenThrow(new NotFoundException("error"));

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertTrue(con1EnvVars.isEmpty());
assertTrue(con2EnvVars.isEmpty());
assertTrue(con3EnvVars.isEmpty());
}

@Test
public void shouldNotThrowExceptionIfTokenFetchingFails() throws Exception {
when(openshiftUserTokenProvider.getToken(eq(SUBJECT))).thenThrow(new InfrastructureException("error"));

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertTrue(con1EnvVars.isEmpty());
assertTrue(con2EnvVars.isEmpty());
assertTrue(con3EnvVars.isEmpty());
}

@Test
public void shouldNotThrowExceptionIfTokenIsNull() throws Exception {
when(openshiftUserTokenProvider.getToken(eq(SUBJECT))).thenReturn(null);

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertTrue(con1EnvVars.isEmpty());
assertTrue(con2EnvVars.isEmpty());
assertTrue(con3EnvVars.isEmpty());
}

@Test
public void shouldNotThrowExceptionIfTenantDataFetchingFails() throws Exception {
when(tenantDataProvider.getUserCheTenantData(eq(SUBJECT), eq("user")))
.thenThrow(new InfrastructureException("error"));

provisioner.provision(openShiftEnvironment, runtimeIdentity);

assertTrue(con1EnvVars.isEmpty());
assertTrue(con2EnvVars.isEmpty());
assertTrue(con3EnvVars.isEmpty());
verify(tenantDataProvider).getUserCheTenantData(eq(SUBJECT), eq("user"));
}

private void verifyOcLoginEnvVarsPresence(List<EnvVar> envVars) {
verifyEnvVarPresence(RhCheInfraEnvironmentProvisioner.CLUSTER_VAR, CLUSTER_URL, envVars);
verifyEnvVarPresence(RhCheInfraEnvironmentProvisioner.PROJECT_VAR, NAMESPACE, envVars);
verifyEnvVarPresence(RhCheInfraEnvironmentProvisioner.TOKEN_VAR, OSO_TOKEN, envVars);
}

private void verifyEnvVarPresence(String name, String value, List<EnvVar> envVars) {
boolean match = false;
for (EnvVar envVar : envVars) {
if (envVar.getName().equals(name) && envVar.getValue().equals(value)) {
match = true;
}
}
assertTrue(match, "No env var with name '%s' and value '%s' found in env vars list");
}

/*@Test
public void integration() throws Exception {
String keycloakToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwbEwwdlhzOVlSVnFaTW93eXc4dU5MUl95cjBpRmFvemRRazlyenEyT1ZVIn0.eyJqdGkiOiI1OGE2MDcwNS05MDg1LTRhYjAtYjFmMC1iNjc2YTA3Y2ZjYmQiLCJleHAiOjE1MjI1NjkyNTAsIm5iZiI6MCwiaWF0IjoxNTE5OTc3MjUwLCJpc3MiOiJodHRwczovL3Nzby5vcGVuc2hpZnQuaW8vYXV0aC9yZWFsbXMvZmFicmljOCIsImF1ZCI6Im9wZW5zaGlmdGlvLXB1YmxpYyIsInN1YiI6IjY0Y2M0ZjdmLTM2YjAtNDdhNS05ZGMxLTMyYzczYmJiODg0ZCIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9wZW5zaGlmdGlvLXB1YmxpYyIsIm5vbmNlIjoiYzgxYzAwYmMtNzdlMC00YWZmLWI5N2YtMDYyYmRkODIyYzEyIiwiYXV0aF90aW1lIjoxNTE4NzIwMjc5LCJzZXNzaW9uX3N0YXRlIjoiYTk2YmFlYzQtMWVlOC00ZDIzLWIzYzYtMDU4OWY4OWNkZDIxIiwiYWNyIjoiMCIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL2xhdW5jaC1zdGFnZS5vcGVuc2hpZnQuaW8iLCJodHRwczovL2NoZS5vcGVuc2hpZnQuaW8iLCJodHRwczovL29wZW5zaGlmdC5pbyIsImh0dHBzOi8vYXV0aC5vcGVuc2hpZnQuaW8iLCJodHRwczovL2xhdW5jaC5vcGVuc2hpZnQuaW8iXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYnJva2VyIjp7InJvbGVzIjpbInJlYWQtdG9rZW4iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sImFwcHJvdmVkIjp0cnVlLCJuYW1lIjoiQWxleGFuZGVyIEdhcmFnYXR5aSIsImNvbXBhbnkiOiJSZWRIYXQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJvZ2FyYWdhdCIsImdpdmVuX25hbWUiOiJBbGV4YW5kZXIiLCJmYW1pbHlfbmFtZSI6IkdhcmFnYXR5aSIsImVtYWlsIjoib2dhcmFnYXRAcmVkaGF0LmNvbSJ9.Zq_btLz43f3XkZ9_U2L6_JR0oQ2MC6JnyZWfhdL8V110RUocWogF9-pJ0FuRaQ5kVbydZfO1GHSv5XFYhBi8uA6Vbqq20NUjB7h-di2mcp6xZNV1850ujCEJJZ7clqH5SOJ6ig5MbGfMHtp9EgmR-q-eYBLCMUYgq-Z3mzSA2xGtDgOp_8nmLDfZlQ6cOJIHktRqlqOCqcq0JcAwOnAO-Wd7qSWGKFeRvppWBQ2G8zmyuo_6iL9oOFcPVlhjHUcQmA-lQyhOjNpTddarm2w-pDJVZZndCel78N27bYCaQS_ct3DGw3dmZxlblxbFQg72BXbmdkTltUI_rxFxQqxXGA";
String userServiceEndpoint = "https://api.openshift.io/api/user/services";
String openshiftKeycloakEndpoint = "https://sso.openshift.io/auth/realms/fabric8/broker/openshift-v3/token";
tenantDataProvider = new TenantDataProvider(new DefaultHttpJsonRequestFactory(), userServiceEndpoint);
KeycloakTokenProvider keycloakTokenProvider =
new KeycloakTokenProvider(null, openshiftKeycloakEndpoint, new DefaultHttpJsonRequestFactory());
openshiftUserTokenProvider = new OpenshiftUserTokenProvider(keycloakTokenProvider);
provisioner = new RhCheInfraEnvironmentProvisioner(true, uniqueNamesProvisioner, routeTlsProvisioner,
Expand All @@ -95,7 +249,8 @@ public void integration() throws Exception {
tenantDataProvider, subjectsRegistry);
when(subjectsRegistry.getSubject(USER_ID)).thenReturn(new SubjectImpl("name", USER_ID, keycloakToken, false));
when(runtimeIdentity.getOwnerId()).thenReturn(USER_ID);
provisioner.provision(openShiftEnvironment, runtimeIdentity);
}
}*/
}

0 comments on commit b7912c5

Please sign in to comment.