This is an automated email from the ASF dual-hosted git repository.
ztang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new 56dd1a8 SUBMARINE-481. Use Swagger to submarine RESTful APIs
56dd1a8 is described below
commit 56dd1a8b5888aafa4d051a49c996b8c53beff79c
Author: pingsutw <[email protected]>
AuthorDate: Thu May 7 09:22:58 2020 +0800
SUBMARINE-481. Use Swagger to submarine RESTful APIs
### What is this PR for?
Use swagger annotation to generate API document
https://gist.github.com/pingsutw/4d96afb54d4c767304f74844b432585c
1. Build Submarine source code
2. start submarine server
3. open localhost:8080/v2/swagger.json
### What type of PR is it?
[Improvement]
### Todos
* [ ] - Task
### What is the Jira issue?
https://issues.apache.org/jira/browse/SUBMARINE-481
### How should this be tested?
https://travis-ci.org/github/pingsutw/hadoop-submarine/builds/680491536
### Screenshots (if appropriate)
### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Author: pingsutw <[email protected]>
Closes #271 from pingsutw/SUBMARINE-481 and squashes the following commits:
a80b90b [pingsutw] Add License
76c3887 [pingsutw] update
c2a8e17 [pingsutw] SUBMARINE-481. Use Swagger to describe and document
submarine RESTful APIs
---
pom.xml | 1 +
submarine-server/server-core/pom.xml | 33 ++++++++++
.../org/apache/submarine/server/Bootstrap.java | 75 ++++++++++++++++++++++
.../submarine/server/rest/JobManagerRestApi.java | 38 +++++++++++
.../workbench-web-ng/src/WEB-INF/web.xml | 25 +++++++-
5 files changed, 171 insertions(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index d16b378..f7aa8ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,7 @@
<node.version>v10.12.0</node.version>
<yarn.version>v1.10.1</yarn.version>
<npm.version>6.4.1</npm.version>
+ <io.swagger.version>2.1.2</io.swagger.version>
<hadoop.common.build.dir>${basedir}/../hadoop-common-project/hadoop-common/target</hadoop.common.build.dir>
<slf4j.version>1.7.25</slf4j.version>
diff --git a/submarine-server/server-core/pom.xml
b/submarine-server/server-core/pom.xml
index 8dcfc36..0917f48 100644
--- a/submarine-server/server-core/pom.xml
+++ b/submarine-server/server-core/pom.xml
@@ -45,6 +45,39 @@
</dependency>
<dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-jaxrs2</artifactId>
+ <version>${io.swagger.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.github.classgraph</groupId>
+ <artifactId>classgraph</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-jaxrs2-servlet-initializer-v2</artifactId>
+ <version>${io.swagger.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.submarine</groupId>
<artifactId>submarine-commons-metastore</artifactId>
<version>${project.version}</version>
diff --git
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/Bootstrap.java
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/Bootstrap.java
new file mode 100644
index 0000000..c4bee19
--- /dev/null
+++
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/Bootstrap.java
@@ -0,0 +1,75 @@
+/*
+ * 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.submarine.server;
+
+import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder;
+import io.swagger.v3.oas.integration.SwaggerConfiguration;
+import io.swagger.v3.oas.integration.OpenApiConfigurationException;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.servers.Server;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class Bootstrap extends HttpServlet {
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+
+ OpenAPI oas = new OpenAPI();
+ Info info = new Info()
+ .title("Submarine Experiment API")
+ .description("The Submarine REST API allows you to create, list,
and get experiments. The" +
+ "API is hosted under the /v1/jobs route on the Submarine
server. For example," +
+ "to list experiments on a server hosted at
http://localhost:8080, access" +
+ "http://localhost:8080/api/v1/jobs/")
+ .termsOfService("http://swagger.io/terms/")
+ .contact(new Contact()
+ .email("[email protected]"))
+ .version("0.4.0-SNAPSHOT")
+ .license(new License()
+ .name("Apache 2.0")
+ .url("http://www.apache.org/licenses/LICENSE-2.0.html"));
+
+ oas.info(info);
+ List<Server> servers = new ArrayList<>();
+ servers.add(new Server().url("/api"));
+ oas.servers(servers);
+ SwaggerConfiguration oasConfig = new SwaggerConfiguration()
+ .openAPI(oas)
+
.resourcePackages(Stream.of("org.apache.submarine.server.rest").collect(Collectors.toSet()));
+
+ try {
+ new JaxrsOpenApiContextBuilder()
+ .servletConfig(config)
+ .openApiConfiguration(oasConfig)
+ .buildContext(true);
+ } catch (OpenApiConfigurationException e) {
+ throw new ServletException(e.getMessage(), e);
+ }
+ }
+}
+
diff --git
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/JobManagerRestApi.java
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/JobManagerRestApi.java
index ef26e40..14e7ca9 100644
---
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/JobManagerRestApi.java
+++
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/JobManagerRestApi.java
@@ -32,6 +32,11 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+
import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
import org.apache.submarine.server.job.JobManager;
import org.apache.submarine.server.api.job.Job;
@@ -53,6 +58,11 @@ public class JobManagerRestApi {
@GET
@Path(RestConstants.PING)
@Consumes(MediaType.APPLICATION_JSON)
+ @Operation(summary = "Ping submarine server",
+ tags = {"jobs"},
+ description = "Return the Pong message for test the connectivity",
+ responses = {
+ @ApiResponse(responseCode = "200", description = "successful
operation")})
public Response ping() {
return new JsonResponse.Builder<String>(Response.Status.OK)
.success(true).result("Pong").build();
@@ -65,6 +75,11 @@ public class JobManagerRestApi {
*/
@POST
@Consumes({RestConstants.MEDIA_TYPE_YAML, MediaType.APPLICATION_JSON})
+ @Operation(summary = "Create a job",
+ tags = {"jobs"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = Job.class)))})
public Response createJob(JobSpec spec) {
try {
Job job = jobManager.createJob(spec);
@@ -79,6 +94,11 @@ public class JobManagerRestApi {
* @return job list
*/
@GET
+ @Operation(summary = "List jobs",
+ tags = {"jobs"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = Job.class)))})
public Response listJob(@QueryParam("status") String status) {
try {
List<Job> jobList = jobManager.listJobsByStatus(status);
@@ -95,6 +115,12 @@ public class JobManagerRestApi {
*/
@GET
@Path("/{id}")
+ @Operation(summary = "Find job by id",
+ tags = {"jobs"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = Job.class))),
+ @ApiResponse(responseCode = "404", description = "Job not
found")})
public Response getJob(@PathParam(RestConstants.JOB_ID) String id) {
try {
Job job = jobManager.getJob(id);
@@ -107,6 +133,12 @@ public class JobManagerRestApi {
@PATCH
@Path("/{id}")
@Consumes({RestConstants.MEDIA_TYPE_YAML, MediaType.APPLICATION_JSON})
+ @Operation(summary = "Update the job in the submarine server with job spec",
+ tags = {"jobs"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = Job.class))),
+ @ApiResponse(responseCode = "404", description = "Job not
found")})
public Response patchJob(@PathParam(RestConstants.JOB_ID) String id, JobSpec
spec) {
try {
Job job = jobManager.patchJob(id, spec);
@@ -124,6 +156,12 @@ public class JobManagerRestApi {
*/
@DELETE
@Path("/{id}")
+ @Operation(summary = "Delete the job",
+ tags = {"jobs"},
+ responses = {
+ @ApiResponse(description = "successful operation", content =
@Content(
+ schema = @Schema(implementation = Job.class))),
+ @ApiResponse(responseCode = "404", description = "Job not
found")})
public Response deleteJob(@PathParam(RestConstants.JOB_ID) String id) {
try {
Job job = jobManager.deleteJob(id);
diff --git a/submarine-workbench/workbench-web-ng/src/WEB-INF/web.xml
b/submarine-workbench/workbench-web-ng/src/WEB-INF/web.xml
index c7b7a29..677ece1 100644
--- a/submarine-workbench/workbench-web-ng/src/WEB-INF/web.xml
+++ b/submarine-workbench/workbench-web-ng/src/WEB-INF/web.xml
@@ -28,7 +28,19 @@
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
- <param-value>org.apache.submarine.server.rest</param-value>
+
<param-value>io.swagger.v3.jaxrs2.integration.resources,org.apache.submarine.server.rest</param-value>
+ </init-param>
+ <init-param>
+ <param-name>openApi.configuration.resourceClasses</param-name>
+
<param-value>org.apache.submarine.server.rest.JobManagerRestApi</param-value>
+ </init-param>
+ <init-param>
+ <param-name>openApi.configuration.scannerClass</param-name>
+
<param-value>io.swagger.v3.jaxrs2.integration.JaxrsAnnotationScanner</param-value>
+ </init-param>
+ <init-param>
+ <param-name>openApi.configuration.prettyPrint</param-name>
+ <param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
@@ -36,6 +48,17 @@
<param-name>configuration</param-name>
<param-value>deployment</param-value>
</context-param>
+
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/v1/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>Bootstrap</servlet-name>
+ <servlet-class>org.apache.submarine.server.Bootstrap</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
<session-config>
<cookie-config>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]