Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
Signed-off-by: Sergii Kabashniuk <[email protected]>
  • Loading branch information
skabashnyuk committed Jul 8, 2020
2 parents 07de922 + 7c93f56 commit 49150a5
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@

import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME;
import static org.eclipse.che.workspace.infrastructure.kubernetes.devfile.KubernetesDevfileBindings.ALLOWED_ENVIRONMENT_TYPE_UPGRADES_KEY_NAME;
import static org.eclipse.che.workspace.infrastructure.kubernetes.devfile.KubernetesDevfileBindings.KUBERNETES_BASED_ENVIRONMENTS_KEY_NAME;

import com.google.common.annotations.VisibleForTesting;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.utils.Serialization;
import java.util.HashSet;
Expand Down Expand Up @@ -119,12 +121,25 @@ public void provision(
// workspace already has k8s/OS recipe
// it is needed to merge existing recipe objects with component's ones
List<HasMetadata> envObjects = unmarshalObjects(envRecipe);
mergeProjectsPVC(envObjects, componentObjects);
envObjects.addAll(componentObjects);
checkItemsHasUniqueKindToName(envObjects);

envRecipe.setContent(asYaml(envObjects));
}
}

private void mergeProjectsPVC(List<HasMetadata> envObjects, List<HasMetadata> componentObjects) {
componentObjects.removeIf(
co ->
co instanceof PersistentVolumeClaim
&& co.getMetadata().getName().equals(PROJECTS_VOLUME_NAME)
&& envObjects
.stream()
.filter(envObject -> envObject instanceof PersistentVolumeClaim)
.anyMatch(pvc -> pvc.equals(co)));
}

private List<HasMetadata> unmarshalObjects(RecipeImpl k8sRecipe) throws DevfileException {
if (!k8sBasedEnvTypes.contains(k8sRecipe.getType())) {
String allowedEnvTypes = String.join(" or ", k8sBasedEnvTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
package org.eclipse.che.workspace.infrastructure.kubernetes.environment;

import static java.lang.String.format;
import static org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME;
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesObjectUtil.putAnnotations;
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesObjectUtil.putLabels;

Expand Down Expand Up @@ -104,6 +105,10 @@ public Deployment merge(List<PodData> podsData) throws ValidationException {

for (Volume volume : podData.getSpec().getVolumes()) {
if (!volumes.add(volume.getName())) {
if (volume.getName().equals(PROJECTS_VOLUME_NAME)) {
// project volume already added, can be skipped
continue;
}
throw new ValidationException(
format(
"Pods have to have volumes with unique names but there are multiple `%s` volumes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
import static io.fabric8.kubernetes.client.utils.Serialization.unmarshal;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE;
import static org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME;
import static org.eclipse.che.workspace.infrastructure.kubernetes.devfile.KubernetesEnvironmentProvisioner.YAML_CONTENT_TYPE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesObjectUtil.newPVC;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.testng.Assert.assertEquals;
Expand All @@ -25,10 +28,12 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.KubernetesList;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.utils.Serialization;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -274,6 +279,33 @@ public void shouldThrowExceptionIfDifferentComponentsHaveObjectsWithTheSameKindA
workspaceConfig, KubernetesEnvironment.TYPE, componentsObject, emptyMap());
}

@Test
public void shouldMergeProjectPVCIntoOne() throws Exception {
// given
PersistentVolumeClaim volumeClaim = newPVC(PROJECTS_VOLUME_NAME, "ReadWriteMany", "1Gb");
workspaceConfig.setDefaultEnv("default");
RecipeImpl existingRecipe =
new RecipeImpl("kubernetes", YAML_CONTENT_TYPE, Serialization.asYaml(volumeClaim), null);
doReturn(singletonList(volumeClaim)).when(k8sRecipeParser).parse(anyString());

workspaceConfig
.getEnvironments()
.put("default", new EnvironmentImpl(existingRecipe, emptyMap()));

// try add same claim one more time (like another component adds it)
List<HasMetadata> componentsObject = new ArrayList<>();
componentsObject.add(volumeClaim);

// when
k8sEnvProvisioner.provision(
workspaceConfig, KubernetesEnvironment.TYPE, componentsObject, emptyMap());

// we still have only one PVC
EnvironmentImpl resultEnv =
workspaceConfig.getEnvironments().get(workspaceConfig.getDefaultEnv());
assertEquals(toK8SList(resultEnv.getRecipe().getContent()).getItems().size(), 1);
}

@Test(
expectedExceptions = DevfileFormatException.class,
expectedExceptionsMessageRegExp =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.environment;

import static org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
Expand Down Expand Up @@ -212,6 +213,31 @@ public void shouldThrownAnExceptionIfVolumeNameCollisionHappened() throws Except
podMerger.merge(Arrays.asList(podData1, podData2));
}

@Test
public void shouldMergeProjectVolumesWithoutException() throws Exception {
// given
PodSpec podSpec1 =
new PodSpecBuilder()
.withVolumes(new VolumeBuilder().withName(PROJECTS_VOLUME_NAME).build())
.build();
podSpec1.setAdditionalProperty("add1", 1L);
PodData podData1 = new PodData(podSpec1, new ObjectMetaBuilder().build());

PodSpec podSpec2 =
new PodSpecBuilder()
.withVolumes(new VolumeBuilder().withName(PROJECTS_VOLUME_NAME).build())
.build();
podSpec2.setAdditionalProperty("add2", 2L);
PodData podData2 = new PodData(podSpec2, new ObjectMetaBuilder().build());

// when
Deployment merged = podMerger.merge(Arrays.asList(podData1, podData2));

// then
PodTemplateSpec podTemplate = merged.getSpec().getTemplate();
assertEquals(podTemplate.getSpec().getVolumes().size(), 1);
}

@Test
public void shouldNotAddImagePullPolicyTwice() throws Exception {
// given
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<javax.ws.rs.version>2.0</javax.ws.rs.version>
<junit.version>4.11</junit.version>
<logstash.logback.encoder.version>4.11</logstash.logback.encoder.version>
<mysql.connector.version>8.0.12</mysql.connector.version>
<mysql.connector.version>8.0.16</mysql.connector.version>
<net.java.dev.jna.version>4.1.0</net.java.dev.jna.version>
<org.antlr.st4.version>4.0.7</org.antlr.st4.version>
<org.apache.commons.lang3.version>3.8.1</org.apache.commons.lang3.version>
Expand Down
49 changes: 28 additions & 21 deletions tests/e2e/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion tests/e2e/pageobjects/ide/Ide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ export class Ide {
const mainIdeParts: Array<By> = [By.css(Ide.TOP_MENU_PANEL_CSS), By.css(Ide.LEFT_CONTENT_PANEL_CSS), By.id(Ide.EXPLORER_BUTTON_ID)];

for (const idePartLocator of mainIdeParts) {
await this.driverHelper.waitVisibility(idePartLocator, timeout);
try {
await this.driverHelper.waitVisibility(idePartLocator, timeout);
} catch (err) {
if (err instanceof error.NoSuchWindowError) {
await this.driverHelper.waitVisibility(idePartLocator, timeout);
}
}
}
}

Expand Down
18 changes: 17 additions & 1 deletion tests/e2e/pageobjects/ide/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ export class Terminal {
}

private async getTerminalIndex(terminalTitle: string): Promise<number> {
for (let i: number = 0; i < 10; i++) {
try {
return await this.searchTerminalIndex(terminalTitle);
} catch (err) {
if (!(err instanceof error.NoSuchElementError)) {
throw err;
}

}
}

throw new error.NoSuchElementError(`The terminal with title '${terminalTitle}' has not been found.`);
}

private async searchTerminalIndex(terminalTitle: string): Promise<number> {
const terminalTabTitleXpathLocator: string = `//div[@id='theia-bottom-content-panel']` +
`//li[contains(@id, 'shell-tab-terminal') or contains(@id, 'shell-tab-plugin')]` +
`//div[@class='p-TabBar-tabLabel']`;
Expand All @@ -152,8 +167,9 @@ export class Terminal {
terminalTitles.push(currentTerminalTitle);
}

throw new error.WebDriverError(`The terminal with title '${terminalTitle}' has not been found.\n` +
throw new error.NoSuchElementError(`The terminal with title '${terminalTitle}' has not been found.\n` +
`List of the tabs:\n${terminalTitles}`);

}

private getTerminalEditorInteractionEditorLocator(terminalIndex: number): By {
Expand Down
3 changes: 0 additions & 3 deletions tests/e2e/utils/workspace/TestWorkspaceUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ export class TestWorkspaceUtil implements ITestWorkspaceUtil {
}
await this.driverHelper.wait(TestConstants.TS_SELENIUM_DEFAULT_POLLING);
}
const wsStatus = await this.processRequestHandler.get(stopWorkspaceApiUrl);
let waitTime = TestConstants.TS_SELENIUM_PLUGIN_PRECENCE_ATTEMPTS * TestConstants.TS_SELENIUM_DEFAULT_POLLING;
throw new error.TimeoutError(`The workspace was not stopped in ${waitTime} ms. Currnet status is: ${wsStatus.data.status}`);
} catch (err) {
console.log(`Stopping workspace failed. URL used: ${stopWorkspaceApiUrl}`);
throw err;
Expand Down

0 comments on commit 49150a5

Please sign in to comment.