You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by of...@apache.org on 2020/01/08 09:42:12 UTC

[incubator-dlab] branch feature-integration-tests updated: [DLAB-1424] Added notebook feature part 1

This is an automated email from the ASF dual-hosted git repository.

ofuks pushed a commit to branch feature-integration-tests
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git


The following commit(s) were added to refs/heads/feature-integration-tests by this push:
     new e0f5fd4  [DLAB-1424] Added notebook feature part 1
e0f5fd4 is described below

commit e0f5fd4b272f5680221661fcff0e35a024039994
Author: Oleh Fuks <ol...@gmail.com>
AuthorDate: Wed Jan 8 11:41:51 2020 +0200

    [DLAB-1424] Added notebook feature part 1
---
 doc/.DS_Store                                      | Bin 12292 -> 0 bytes
 .../org/apache/dlab/dto/NotebookCreateDTO.java     |  61 ++++++++
 .../main/java/org/apache/dlab/dto/NotebookDTO.java |  70 +++++++++
 .../org/apache/dlab/dto/ProjectNotebookDTO.java    |  34 +++++
 .../src/test/java/dlab/Constants.java              |   6 +-
 .../src/test/java/dlab/notebook/NotebookSteps.java | 167 +++++++++++++++++++++
 .../src/test/java/dlab/project/ProjectSteps.java   |   8 +-
 .../src/test/resources/dlab/notebook.feature       |  16 ++
 .../src/test/resources/dlab/project.feature        |   8 +-
 9 files changed, 360 insertions(+), 10 deletions(-)

diff --git a/doc/.DS_Store b/doc/.DS_Store
deleted file mode 100644
index 3a993d5..0000000
Binary files a/doc/.DS_Store and /dev/null differ
diff --git a/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookCreateDTO.java b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookCreateDTO.java
new file mode 100644
index 0000000..0752285
--- /dev/null
+++ b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookCreateDTO.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dlab.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+public class NotebookCreateDTO {
+
+    @JsonProperty
+    private String image;
+
+    @JsonProperty("template_name")
+    private String templateName;
+
+    @JsonProperty
+    private String name;
+
+    @JsonProperty
+    private String project;
+
+    @JsonProperty("custom_tag")
+    private String exploratoryTag;
+
+    @JsonProperty
+    private String endpoint;
+
+    @JsonProperty
+    private String shape;
+
+    @JsonProperty
+    private String version;
+
+    @JsonProperty("notebook_image_name")
+    private String imageName;
+
+    @JsonProperty("cluster_config")
+    private List<String> clusterConfig;
+}
diff --git a/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookDTO.java b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookDTO.java
new file mode 100644
index 0000000..d91d9cd
--- /dev/null
+++ b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/NotebookDTO.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dlab.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.Data;
+
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class NotebookDTO {
+    @JsonProperty("exploratory_name")
+    private String name;
+    private String endpoint;
+    private String project;
+    private String user;
+    private Status status;
+
+
+    public enum Status {
+        CREATING("creating"),
+        CREATED("created"),
+        STARTING("starting"),
+        CONFIGURING("configuring"),
+        RUNNING("running"),
+        STOPPING("stopping"),
+        STOPPED("stopped"),
+        TERMINATING("terminating"),
+        TERMINATED("terminated"),
+        FAILED("failed"),
+        CREATING_IMAGE("creating image"),
+        RECONFIGURING("reconfiguring");
+
+        private String name;
+
+        Status(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        @JsonValue
+        public String getName() {
+            return name;
+        }
+    }
+}
+
diff --git a/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/ProjectNotebookDTO.java b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/ProjectNotebookDTO.java
new file mode 100644
index 0000000..639ce5f
--- /dev/null
+++ b/integration-tests-cucumber/src/main/java/org/apache/dlab/dto/ProjectNotebookDTO.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dlab.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ProjectNotebookDTO {
+    private String project;
+    @JsonProperty("exploratory")
+    private List<NotebookDTO> notebooks;
+}
diff --git a/integration-tests-cucumber/src/test/java/dlab/Constants.java b/integration-tests-cucumber/src/test/java/dlab/Constants.java
index 5641cd0..92cdbf6 100644
--- a/integration-tests-cucumber/src/test/java/dlab/Constants.java
+++ b/integration-tests-cucumber/src/test/java/dlab/Constants.java
@@ -3,10 +3,12 @@ package dlab;
 import org.apache.dlab.util.PropertyHelper;
 
 public interface Constants {
-	String API_URI = PropertyHelper.read("dlab.api.base.uri");
-	String LOCAL_ENDPOINT = "local";
 	String CONNECTION_TIMEOUT_LABEL = "http.connection.timeout";
 	int CONNECTION_TIMEOUT = Integer.parseInt(PropertyHelper.read(CONNECTION_TIMEOUT_LABEL));
 	String SOCKET_TIMEOUT_LABEL = "http.socket.timeout";
 	int SOCKET_TIMEOUT = Integer.parseInt(PropertyHelper.read(SOCKET_TIMEOUT_LABEL));
+
+	String API_URI = PropertyHelper.read("dlab.api.base.uri");
+	String LOCAL_ENDPOINT = "local";
+	String CLIENT_ID = PropertyHelper.read("keycloak.clientId");
 }
diff --git a/integration-tests-cucumber/src/test/java/dlab/notebook/NotebookSteps.java b/integration-tests-cucumber/src/test/java/dlab/notebook/NotebookSteps.java
new file mode 100644
index 0000000..1f4d026
--- /dev/null
+++ b/integration-tests-cucumber/src/test/java/dlab/notebook/NotebookSteps.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package dlab.notebook;
+
+import com.jayway.restassured.config.HttpClientConfig;
+import com.jayway.restassured.config.RestAssuredConfig;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.response.Response;
+import com.jayway.restassured.specification.RequestSpecification;
+import cucumber.api.java.en.And;
+import cucumber.api.java.en.Given;
+import cucumber.api.java.en.Then;
+import cucumber.api.java.en.When;
+import dlab.util.KeycloakUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dlab.dto.EndpointStatusDTO;
+import org.apache.dlab.dto.NotebookCreateDTO;
+import org.apache.dlab.dto.NotebookDTO;
+import org.apache.dlab.dto.ProjectDTO;
+import org.apache.dlab.dto.ProjectNotebookDTO;
+import org.apache.dlab.util.JacksonMapper;
+
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import static com.jayway.restassured.RestAssured.given;
+import static dlab.Constants.API_URI;
+import static dlab.Constants.CLIENT_ID;
+import static dlab.Constants.CONNECTION_TIMEOUT;
+import static dlab.Constants.CONNECTION_TIMEOUT_LABEL;
+import static dlab.Constants.LOCAL_ENDPOINT;
+import static dlab.Constants.SOCKET_TIMEOUT;
+import static dlab.Constants.SOCKET_TIMEOUT_LABEL;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+
+
+@Slf4j
+public class NotebookSteps {
+    private static final String SERVICE_ACCOUNT_FORMAT = "service-account-%s";
+
+    private RequestSpecification request;
+    private Response response;
+    private String name;
+    private String projectName;
+
+
+    @Given("There is active project {string} in DLab")
+    public void thereIsActiveProjectInDLab(String project) {
+        this.projectName = project;
+        Response response = authenticatedRequest().get(API_URI + "project/{project}", project);
+
+        assertThat("Status code doesn't match!", response.getStatusCode(), equalTo(200));
+
+        boolean runningProjectExists = response.as(ProjectDTO.class).getEndpoints().stream()
+                .anyMatch(e -> LOCAL_ENDPOINT.equals(e.getName()) && e.getStatus() == EndpointStatusDTO.Status.RUNNING);
+
+        assertTrue(String.format("There is no active project %s.", project), runningProjectExists);
+        log.info("There is an active project {}", project);
+    }
+
+    @And("There is no notebook with name {string}")
+    public void thereIsNoNotebookWithName(String name) throws URISyntaxException {
+        this.name = name;
+        Optional<NotebookDTO> notebook = getNotebookDTO();
+
+        assertFalse("Notebook exists!", notebook.isPresent());
+    }
+
+    @And("User tries to create new notebook with name {string}, endpoint {string}, image {string}, template {string}, project {string}, exploratory tag {string}, shape {string}, version {string}, image name {string}")
+    public void userTriesToCreateNewNotebookWithNameEndpointImageTemplateProjectExploratoryTagShapeVersionImageName(String name, String endpoint, String image, String template, String project, String exploratoryTag, String shape, String version, String imageName) {
+        this.name = name;
+        NotebookCreateDTO notebookCreateDTO = new NotebookCreateDTO(image, template, name, project, exploratoryTag, endpoint, shape, version, imageName, null);
+        request = authenticatedRequest()
+                .body(JacksonMapper.marshall(notebookCreateDTO))
+                .contentType(ContentType.JSON);
+    }
+
+    @When("User sends create new notebook request")
+    public void userSendsCreateNewNotebookRequest() {
+        response = request.put(API_URI + "infrastructure_provision/exploratory_environment");
+        log.info("Sending request to create notebook {} in project {}", name, projectName);
+    }
+
+    @Then("Status code is {int} for notebook")
+    public void statusCodeIs(int code) {
+        assertThat("Status codes don't match!", response.getStatusCode(), equalTo(code));
+    }
+
+    @And("User waits maximum {int} minutes while notebook is creating")
+    public void userWaitsMaximumTimeoutMinutesWhileNotebookIsCreating(int timeout) throws URISyntaxException, InterruptedException {
+        boolean isRunning = waitForStatus(timeout, NotebookDTO.Status.RUNNING);
+
+        assertTrue("Timeout for notebook status check reached!", isRunning);
+        log.info("Notebook {} successfully started", projectName);
+    }
+
+    private boolean waitForStatus(int timeout, NotebookDTO.Status status) throws URISyntaxException, InterruptedException {
+        boolean correctStatus = false;
+        LocalDateTime withTimeout = LocalDateTime.now().plusMinutes(timeout);
+        log.info("User wait till {} for notebook {} to be {}", withTimeout, projectName, status);
+
+        while (!correctStatus && LocalDateTime.now().isBefore(withTimeout)) {
+            Optional<NotebookDTO> notebook = getNotebookDTO();
+
+            assertTrue("Notebook does not exist!", notebook.isPresent());
+            assertNotSame("Notebook with status FAILED", NotebookDTO.Status.FAILED.toString(), notebook.get().getStatus().toString());
+
+            correctStatus = status == notebook.get().getStatus();
+            TimeUnit.MINUTES.sleep(1);
+        }
+
+        return correctStatus;
+    }
+
+    private Optional<NotebookDTO> getNotebookDTO() throws URISyntaxException {
+        Response response = authenticatedRequest().get(new URI(API_URI + "infrastructure/info"));
+
+        assertThat("Status code doesn't match!", response.getStatusCode(), equalTo(200));
+
+        List<NotebookDTO> notebooks = Arrays.stream(response.getBody().as(ProjectNotebookDTO[].class))
+                .filter(projectNotebook -> projectName.equals(projectNotebook.getProject()))
+                .map(ProjectNotebookDTO::getNotebooks)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+
+        return notebooks.stream()
+                .filter(n -> name.equals(n.getName()) && String.format(SERVICE_ACCOUNT_FORMAT, CLIENT_ID).equals(n.getUser()) &&
+                        projectName.equals(n.getProject()))
+                .findAny();
+    }
+
+    private RequestSpecification authenticatedRequest() {
+        return given()
+                .auth()
+                .oauth2(KeycloakUtil.getToken())
+                .config(RestAssuredConfig.config().httpClient(HttpClientConfig.httpClientConfig()
+                        .setParam(CONNECTION_TIMEOUT_LABEL, CONNECTION_TIMEOUT)
+                        .setParam(SOCKET_TIMEOUT_LABEL, SOCKET_TIMEOUT)));
+    }
+}
diff --git a/integration-tests-cucumber/src/test/java/dlab/project/ProjectSteps.java b/integration-tests-cucumber/src/test/java/dlab/project/ProjectSteps.java
index d8250ea..e1f6ced 100644
--- a/integration-tests-cucumber/src/test/java/dlab/project/ProjectSteps.java
+++ b/integration-tests-cucumber/src/test/java/dlab/project/ProjectSteps.java
@@ -193,7 +193,7 @@ public class ProjectSteps {
 		assertThat(response.getStatusCode(), equalTo(code));
 	}
 
-	@Then("User waits maximum {int} minutes while project is creating")
+	@And("User waits maximum {int} minutes while project is creating")
 	public void userWaitMaximumMinutesWhileProjectIsCreating(int timeout) throws URISyntaxException, InterruptedException {
 		boolean isRunning = waitForStatus(timeout, EndpointStatusDTO.Status.RUNNING);
 
@@ -201,7 +201,7 @@ public class ProjectSteps {
 		log.info("Project {} successfully created", projectName);
 	}
 
-	@Then("User waits maximum {int} minutes while project is terminating")
+	@And("User waits maximum {int} minutes while project is terminating")
 	public void userWaitsMaximumTimeoutMinutesWhileProjectIsTerminated(int timeout) throws URISyntaxException, InterruptedException {
 		boolean isTerminated = waitForStatus(timeout, EndpointStatusDTO.Status.TERMINATED);
 
@@ -209,7 +209,7 @@ public class ProjectSteps {
 		log.info("Project {} successfully terminated", projectName);
 	}
 
-	@Then("User waits maximum {int} minutes while project is stopping")
+	@And("User waits maximum {int} minutes while project is stopping")
 	public void userWaitsMaximumTimeoutMinutesWhileProjectIsStopping(int timeout) throws URISyntaxException, InterruptedException {
 		boolean isStopped = waitForStatus(timeout, EndpointStatusDTO.Status.STOPPED);
 
@@ -217,7 +217,7 @@ public class ProjectSteps {
 		log.info("Project {} successfully stopped", projectName);
 	}
 
-	@Then("User waits maximum {int} minutes while project is starting")
+	@And("User waits maximum {int} minutes while project is starting")
 	public void userWaitsMaximumTimeoutMinutesWhileProjectIsStarting(int timeout) throws URISyntaxException, InterruptedException {
 		boolean isRunning = waitForStatus(timeout, EndpointStatusDTO.Status.RUNNING);
 
diff --git a/integration-tests-cucumber/src/test/resources/dlab/notebook.feature b/integration-tests-cucumber/src/test/resources/dlab/notebook.feature
new file mode 100644
index 0000000..02bdffb
--- /dev/null
+++ b/integration-tests-cucumber/src/test/resources/dlab/notebook.feature
@@ -0,0 +1,16 @@
+@notebook
+Feature: Notebook management in DLab
+  Such feature allowed to manage notebook inside DLab
+
+  Scenario Outline: Create new notebook when it does not exist
+
+    Given There is active project "<project>" in DLab
+    And There is no notebook with name "<name>"
+    And User tries to create new notebook with name "<name>", endpoint "<endpoint>", image "<image>", template "<template>", project "<project>", exploratory tag "<exploratoryTag>", shape "<shape>", version "<version>", image name "<imageName>"
+    When User sends create new notebook request
+    Then Status code is 200 for notebook
+    And User waits maximum <timeout> minutes while notebook is creating
+    @aws @v1 @jupyter
+    Examples:
+      | name | endpoint | image               | template               | project | exploratoryTag       | shape     | version                | imageName | timeout |
+      | jup1 | local    | docker.dlab-jupyter | Jupyter notebook 6.0.2 | prj1    | integration test tag | t2.medium | jupyter_notebook-6.0.2 |           | 20      |
\ No newline at end of file
diff --git a/integration-tests-cucumber/src/test/resources/dlab/project.feature b/integration-tests-cucumber/src/test/resources/dlab/project.feature
index c478c7f..b8c5fbc 100644
--- a/integration-tests-cucumber/src/test/resources/dlab/project.feature
+++ b/integration-tests-cucumber/src/test/resources/dlab/project.feature
@@ -12,8 +12,8 @@ Feature: Project management in DLab
     And User generates new publicKey
     And User tries to create new project with name "<name>", endpoints, groups, publicKey and use shared image enable "true"
     When User sends create new project request
-    Then User waits maximum <timeout> minutes while project is creating
     Then Status code is 200
+    And User waits maximum <timeout> minutes while project is creating
     @v1
     Examples:
       | name | timeout |
@@ -124,7 +124,7 @@ Feature: Project management in DLab
     And User tries to stop the project
     When User sends request to stop the project
     Then Status code is 202
-    Then User waits maximum <timeout> minutes while project is stopping
+    And User waits maximum <timeout> minutes while project is stopping
     @v1
     Examples:
       | name | timeout |
@@ -141,7 +141,7 @@ Feature: Project management in DLab
     And User tries to start the project
     When User sends request to start the project
     Then Status code is 202
-    Then User waits maximum <timeout> minutes while project is starting
+    And User waits maximum <timeout> minutes while project is starting
     @v1
     Examples:
       | name | timeout |
@@ -158,8 +158,8 @@ Feature: Project management in DLab
     Given There is a project with name "<name>" in DLab
     And User tries to terminate the project with name "<name>"
     When User sends termination request
-    Then User waits maximum <timeout> minutes while project is terminating
     Then Status code is 200
+    And User waits maximum <timeout> minutes while project is terminating
     @v1
     Examples:
       | name | timeout |


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org