This is an automated email from the ASF dual-hosted git repository.
ulyssesyou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-kyuubi.git
The following commit(s) were added to refs/heads/master by this push:
new a5ef94a [KYUUBI #1354] Expose OpenAPI Specifications
a5ef94a is described below
commit a5ef94accc0b6e7557a085512dc8fe062d79375b
Author: Fu Chen <[email protected]>
AuthorDate: Wed Nov 17 12:17:58 2021 +0800
[KYUUBI #1354] Expose OpenAPI Specifications
<!--
Thanks for sending a pull request!
Here are some tips for you:
1. If this is your first time, please read our contributor guidelines:
https://kyuubi.readthedocs.io/en/latest/community/contributions.html
2. If the PR is related to an issue in
https://github.com/apache/incubator-kyuubi/issues, add '[KYUUBI #XXXX]' in your
PR title, e.g., '[KYUUBI #XXXX] Your PR title ...'.
3. If the PR is unfinished, add '[WIP]' in your PR title, e.g.,
'[WIP][KYUUBI #XXXX] Your PR title ...'.
-->
### _Why are the changes needed?_
<!--
Please clarify why the changes are needed. For instance,
1. If you add a feature, you can talk about the use case of it.
2. If you fix a bug, you can clarify why it is a bug.
-->
1. add a new endpoint `/openapi.json` which describes the entire restful
API of Kyuubi.
2. add a static web page `/api/v1/swagger-ui`. see
[swagger-ui](https://github.com/swagger-api/swagger-ui)
```
curl http://localhost:10099/openapi.json | jq .
```
```json
{
"openapi": "3.0.1",
"info": {
"title": "Apache Kyuubi RESTful Api Documentation",
"description": "Apache Kyuubi RESTful Api Documentation",
"contact": {
"name": "Apache Kyuubi Community",
"url": "https://kyuubi.apache.org/issue_tracking.html",
"email": "devkyuubi.apache.org"
},
"license": {
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.4.0"
},
"tags": [
{
"name": "Session"
}
],
"paths": {
"/api/v1/ping": {
"get": {
"operationId": "ping",
"responses": {
"default": {
"description": "default response",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/api/v1/sessions/{sessionHandle}": {
"get": {
"tags": [
"Session"
],
"operationId": "sessionInfo",
"parameters": [
{
"name": "sessionHandle",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "get a session via session handle identifier",
"content": {
"application/json": {}
}
}
}
},
"delete": {
"tags": [
"Session"
],
"operationId": "closeSession",
"parameters": [
{
"name": "sessionHandle",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "close a Session",
"content": {
"application/json": {}
}
}
}
}
},
"/api/v1/sessions/execPool/statistic": {
"get": {
"tags": [
"Session"
],
"operationId": "execPoolStatistic",
"responses": {
"200": {
"description": "get some statistic info of sessions",
"content": {
"application/json": {}
}
}
}
}
},
"/api/v1/sessions/{sessionHandle}/info/{infoType}": {
"get": {
"tags": [
"Session"
],
"operationId": "getInfo",
"parameters": [
{
"name": "sessionHandle",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "infoType",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "get a information detail via session handle
identifier and a specific information type",
"content": {
"application/json": {}
}
}
}
}
},
"/api/v1/sessions": {
"get": {
"tags": [
"Session"
],
"operationId": "sessionInfoList",
"responses": {
"200": {
"description": "get all the session list hosted in
SessionManager",
"content": {
"application/json": {}
}
}
}
},
"post": {
"tags": [
"Session"
],
"operationId": "openSession",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionOpenRequest"
}
}
}
},
"responses": {
"200": {
"description": "Open(create) a Session",
"content": {
"application/json": {}
}
}
}
}
},
"/api/v1/sessions/count": {
"get": {
"tags": [
"Session"
],
"operationId": "sessionCount",
"responses": {
"200": {
"description": "get open session count",
"content": {
"application/json": {}
}
}
}
}
},
"/api/v1/exception": {
"get": {
"operationId": "test",
"responses": {
"default": {
"description": "default response",
"content": {
"text/plain": {}
}
}
}
}
},
"/application.wadl/{path}": {
"get": {
"operationId": "getExternalGrammar",
"parameters": [
{
"name": "path",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"description": "default response",
"content": {
"application/xml": {}
}
}
}
}
},
"/application.wadl": {
"get": {
"operationId": "getWadl",
"responses": {
"default": {
"description": "default response",
"content": {
"application/vnd.sun.wadl+xml": {},
"application/xml": {}
}
}
}
}
}
},
"components": {
"schemas": {
"ExecPoolStatistic": {
"required": [
"execPoolSize"
],
"type": "object",
"properties": {
"execPoolSize": {
"type": "integer",
"format": "int32"
},
"execPoolActiveCount": {
"type": "integer",
"format": "int32"
}
}
},
"InfoDetail": {
"required": [
"infoType"
],
"type": "object",
"properties": {
"infoType": {
"type": "string"
},
"infoValue": {
"type": "string"
}
}
},
"HandleIdentifier": {
"required": [
"publicId"
],
"type": "object",
"properties": {
"publicId": {
"type": "string",
"format": "uuid"
},
"secretId": {
"type": "string",
"format": "uuid"
}
}
},
"SessionHandle": {
"required": [
"identifier",
"protocol"
],
"type": "object",
"properties": {
"identifier": {
"$ref": "#/components/schemas/HandleIdentifier"
},
"protocol": {
"type": "string",
"enum": [
"HIVE_CLI_SERVICE_PROTOCOL_V1",
"HIVE_CLI_SERVICE_PROTOCOL_V2",
"HIVE_CLI_SERVICE_PROTOCOL_V3",
"HIVE_CLI_SERVICE_PROTOCOL_V4",
"HIVE_CLI_SERVICE_PROTOCOL_V5",
"HIVE_CLI_SERVICE_PROTOCOL_V6",
"HIVE_CLI_SERVICE_PROTOCOL_V7",
"HIVE_CLI_SERVICE_PROTOCOL_V8",
"HIVE_CLI_SERVICE_PROTOCOL_V9",
"HIVE_CLI_SERVICE_PROTOCOL_V10"
]
}
}
},
"MapStringString": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"SessionOpenRequest": {
"required": [
"configs",
"protocolVersion",
"user"
],
"type": "object",
"properties": {
"protocolVersion": {
"type": "integer",
"format": "int32"
},
"user": {
"type": "string"
},
"password": {
"type": "string"
},
"ipAddr": {
"type": "string"
},
"configs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"SessionOpenCount": {
"required": [
"openSessionCount"
],
"type": "object",
"properties": {
"openSessionCount": {
"type": "integer",
"format": "int32"
}
}
},
"SessionDetail": {
"required": [
"configs",
"createTime",
"user"
],
"type": "object",
"properties": {
"user": {
"type": "string"
},
"ipAddr": {
"type": "string"
},
"createTime": {
"type": "integer",
"format": "int64"
},
"sessionHandle": {
"$ref": "#/components/schemas/SessionHandle"
},
"lastAccessTime": {
"type": "integer",
"format": "int64"
},
"lastIdleTime": {
"type": "integer",
"format": "int64"
},
"noOperationTime": {
"type": "integer",
"format": "int64"
},
"configs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"SeqSessionOverview": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SessionOverview"
}
},
"SessionList": {
"required": [
"sessionList"
],
"type": "object",
"properties": {
"sessionList": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SessionOverview"
}
}
}
},
"SessionOverview": {
"required": [
"createTime",
"user"
],
"type": "object",
"properties": {
"user": {
"type": "string"
},
"ipAddr": {
"type": "string"
},
"createTime": {
"type": "integer",
"format": "int64"
},
"sessionHandle": {
"$ref": "#/components/schemas/SessionHandle"
}
}
}
}
}
}
```
http://localhost:10099/api/v1/swagger-ui
> Note that this request will redirect to
http://localhost:10099/swagger-ui-redirected/index.html?url=http://localhost:10099/openapi.json

### _How was this patch tested?_
- [ ] Add some test cases that check the changes thoroughly including
negative and positive cases if possible
- [ ] Add screenshots for manual tests if appropriate
- [ ] [Run
test](https://kyuubi.readthedocs.io/en/latest/develop_tools/testing.html#running-tests)
locally before make a pull request
Closes #1363 from cfmcgrady/kyuubi-1354.
Closes #1354
8895d7fc [Fu Chen] typo
8f5dea9a [Fu Chen] addressed comment
4d325a45 [Fu Chen] constant MediaType.APPLICATION_JSON
0d96951e [Fu Chen] RESTful Api -> REST API
be7d02dc [Fu Chen] add LIABILITY-edl.txt
4ff1053e [Fu Chen] update dev/dependencyList
b126f7e6 [Fu Chen] swagger-ui 4.1.0
a35c2f29 [Fu Chen] addressed comment
7bde0534 [Fu Chen] update LICENSE-binary
38397dc2 [Fu Chen] align jackson version
923f3e7e [Fu Chen] update dev/dependencyList
7d5338c8 [Fu Chen] remove kyuubi-server static files
5cb66b33 [Fu Chen] update dev/dependencyList
e8a8c421 [Fu Chen] fix style
5b13f69c [Fu Chen] add license and remove .map files
c04d7a75 [Fu Chen] rebase master
2388dae8 [Fu Chen] fix style
8dcbd3db [Fu Chen] add static resource
4b0d6d0a [Fu Chen] expose OpenAPI
Authored-by: Fu Chen <[email protected]>
Signed-off-by: ulysses-you <[email protected]>
---
LICENSE-binary | 21 ++++++++
dev/dependencyList | 18 +++++++
kyuubi-server/pom.xml | 15 ++++++
.../apache/kyuubi/server/api/OpenAPIConfig.scala | 45 +++++++++++++++++
.../scala/org/apache/kyuubi/server/api/api.scala | 24 +++++----
.../kyuubi/server/api/v1/ApiRootResource.scala | 17 ++++++-
.../kyuubi/server/api/v1/SessionsResource.scala | 57 +++++++++++++++++++++-
.../org/apache/kyuubi/server/api/v1/dto.scala | 2 +-
licenses-binary/LICENSE-edl.txt | 13 +++++
pom.xml | 52 ++++++++++++++++++++
10 files changed, 250 insertions(+), 14 deletions(-)
diff --git a/LICENSE-binary b/LICENSE-binary
index e0a3ef1..1ad1b30 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -232,6 +232,11 @@ org.apache.htrace:htrace-core4
com.fasterxml.jackson.core:jackson-annotations
com.fasterxml.jackson.core:jackson-core
com.fasterxml.jackson.core:jackson-databind
+com.fasterxml.jackson.dataformat:jackson-dataformat-yaml
+com.fasterxml.jackson.datatype:jackson-datatype-jsr310
+com.fasterxml.jackson.jaxrs:jackson-jaxrs-base
+com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
+com.github.swagger-akka-http:swagger-scala-module_*
org.eclipse.jetty:jetty-http
org.eclipse.jetty:jetty-io
org.eclipse.jetty:jetty-security
@@ -241,6 +246,8 @@ org.eclipse.jetty:jetty-util-ajax
org.eclipse.jetty:jetty-util
org.apache.thrift:libfb303
org.apache.thrift:libthrift
+org.webjars:swagger-ui
+org.yaml:snakeyaml
log4j:log4j
io.dropwizard.metrics:metrics-core
io.dropwizard.metrics:metrics-jmx
@@ -251,12 +258,25 @@ io.prometheus:simpleclient
io.prometheus:simpleclient_common
io.prometheus:simpleclient_dropwizard
io.prometheus:simpleclient_servlet
+io.swagger.core.v3:swagger-annotations
+io.swagger.core.v3:swagger-annotations-jakarta
+io.swagger.core.v3:swagger-core
+io.swagger.core.v3:swagger-core-jakarta
+io.swagger.core.v3:swagger-integration
+io.swagger.core.v3:swagger-jaxrs2
+io.swagger.core.v3:swagger-models
+io.swagger.core.v3:swagger-models-jakarta
org.apache.zookeeper:zookeeper
BSD 3-Clause
------------
org.scala-lang:scala-library
+Eclipse Distribution License - v 1.0
+------------------------------------
+com.sun.activation:jakarta.activation
+jakarta.xml.bind:jakarta.xml.bind-api
+
Eclipse Public License (EPL) 2.0
--------------------------------
jakarta.servlet:jakarta.servlet-api
https://projects.eclipse.org/projects/ee4j.servlet
@@ -271,3 +291,4 @@ org.slf4j:slf4j-api
org.slf4j:slf4j-log4j12
org.slf4j:jcl-over-slf4j
com.github.scopt:scopt_*
+io.github.classgraph:classgraph
diff --git a/dev/dependencyList b/dev/dependencyList
index 58d9a79..e070bf2 100644
--- a/dev/dependencyList
+++ b/dev/dependencyList
@@ -16,6 +16,7 @@
#
aopalliance-repackaged/2.6.1//aopalliance-repackaged-2.6.1.jar
+classgraph/4.8.95//classgraph-4.8.95.jar
commons-codec/1.15//commons-codec-1.15.jar
commons-lang/2.6//commons-lang-2.6.jar
commons-lang3/3.10//commons-lang3-3.10.jar
@@ -39,14 +40,20 @@
htrace-core4/4.1.0-incubating//htrace-core4-4.1.0-incubating.jar
jackson-annotations/2.11.4//jackson-annotations-2.11.4.jar
jackson-core/2.11.4//jackson-core-2.11.4.jar
jackson-databind/2.11.4//jackson-databind-2.11.4.jar
+jackson-dataformat-yaml/2.11.4//jackson-dataformat-yaml-2.11.4.jar
+jackson-datatype-jsr310/2.11.4//jackson-datatype-jsr310-2.11.4.jar
+jackson-jaxrs-base/2.11.4//jackson-jaxrs-base-2.11.4.jar
+jackson-jaxrs-json-provider/2.11.4//jackson-jaxrs-json-provider-2.11.4.jar
jackson-module-jaxb-annotations/2.9.9//jackson-module-jaxb-annotations-2.9.9.jar
jackson-module-paranamer/2.11.4//jackson-module-paranamer-2.11.4.jar
jackson-module-scala_2.12/2.11.4//jackson-module-scala_2.12-2.11.4.jar
+jakarta.activation/2.0.0//jakarta.activation-2.0.0.jar
jakarta.annotation-api/1.3.5//jakarta.annotation-api-1.3.5.jar
jakarta.inject/2.6.1//jakarta.inject-2.6.1.jar
jakarta.servlet-api/4.0.4//jakarta.servlet-api-4.0.4.jar
jakarta.validation-api/2.0.2//jakarta.validation-api-2.0.2.jar
jakarta.ws.rs-api/2.1.6//jakarta.ws.rs-api-2.1.6.jar
+jakarta.xml.bind-api/3.0.0//jakarta.xml.bind-api-3.0.0.jar
javassist/3.25.0-GA//javassist-3.25.0-GA.jar
jaxb-api/2.2.11//jaxb-api-2.2.11.jar
jcl-over-slf4j/1.7.30//jcl-over-slf4j-1.7.30.jar
@@ -83,4 +90,15 @@
simpleclient_dropwizard/0.10.0//simpleclient_dropwizard-0.10.0.jar
simpleclient_servlet/0.10.0//simpleclient_servlet-0.10.0.jar
slf4j-api/1.7.30//slf4j-api-1.7.30.jar
slf4j-log4j12/1.7.30//slf4j-log4j12-1.7.30.jar
+snakeyaml/1.26//snakeyaml-1.26.jar
+swagger-annotations-jakarta/2.1.11//swagger-annotations-jakarta-2.1.11.jar
+swagger-annotations/2.1.11//swagger-annotations-2.1.11.jar
+swagger-core-jakarta/2.1.11//swagger-core-jakarta-2.1.11.jar
+swagger-core/2.1.11//swagger-core-2.1.11.jar
+swagger-integration/2.1.11//swagger-integration-2.1.11.jar
+swagger-jaxrs2/2.1.11//swagger-jaxrs2-2.1.11.jar
+swagger-models-jakarta/2.1.11//swagger-models-jakarta-2.1.11.jar
+swagger-models/2.1.11//swagger-models-2.1.11.jar
+swagger-scala-module_2.12/2.5.2//swagger-scala-module_2.12-2.5.2.jar
+swagger-ui/4.1.0//swagger-ui-4.1.0.jar
zookeeper/3.4.14//zookeeper-3.4.14.jar
diff --git a/kyuubi-server/pom.xml b/kyuubi-server/pom.xml
index ecf336b..d5b8a54 100644
--- a/kyuubi-server/pom.xml
+++ b/kyuubi-server/pom.xml
@@ -203,6 +203,16 @@
</dependency>
<dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-jaxrs2</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.github.swagger-akka-http</groupId>
+
<artifactId>swagger-scala-module_${scala.binary.version}</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
@@ -433,6 +443,11 @@
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>swagger-ui</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/OpenAPIConfig.scala
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/OpenAPIConfig.scala
new file mode 100644
index 0000000..46539e7
--- /dev/null
+++
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/OpenAPIConfig.scala
@@ -0,0 +1,45 @@
+/*
+ * 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.kyuubi.server.api
+
+import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource
+import io.swagger.v3.oas.annotations.OpenAPIDefinition
+import io.swagger.v3.oas.annotations.info.{Contact, Info, License}
+import io.swagger.v3.oas.annotations.tags.Tag
+import org.glassfish.jersey.server.ResourceConfig
+
+@OpenAPIDefinition(
+ info = new Info(
+ title = "Apache Kyuubi REST API Documentation",
+ version = "1.4.0",
+ description = "Apache Kyuubi REST API Documentation",
+ contact = new Contact(
+ name = "Apache Kyuubi Community",
+ url = "https://kyuubi.apache.org/issue_tracking.html",
+ email = "[email protected]"),
+ license = new License(
+ name = "Apache 2.0",
+ url = "https://www.apache.org/licenses/LICENSE-2.0.html")
+ ),
+ tags = Array(new Tag(name = "Session"))
+)
+class OpenAPIConfig extends ResourceConfig {
+ packages("org.apache.kyuubi.server.api.v1")
+ register(classOf[OpenApiResource]);
+ register(classOf[KyuubiScalaObjectMapper])
+}
diff --git
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/api.scala
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/api.scala
index 83068e3..6a9bddf 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/api.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/api.scala
@@ -22,8 +22,8 @@ import javax.servlet.http.HttpServletRequest
import javax.ws.rs.core.Context
import org.eclipse.jetty.server.handler.ContextHandler
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
-import org.glassfish.jersey.server.ServerProperties
+import org.eclipse.jetty.servlet.{DefaultServlet, ServletContextHandler,
ServletHolder}
+import org.glassfish.jersey.server.ResourceConfig
import org.glassfish.jersey.servlet.ServletContainer
import org.apache.kyuubi.service.BackendService
@@ -56,17 +56,21 @@ private[api] object BackendServiceProvider {
private[server] object ApiUtils {
def getServletHandler(backendService: BackendService): ServletContextHandler
= {
- val servlet = new ServletHolder(classOf[ServletContainer])
- servlet.setInitParameter(
- ServerProperties.PROVIDER_PACKAGES,
- "org.apache.kyuubi.server.api.v1")
- servlet.setInitParameter(
- ServerProperties.PROVIDER_CLASSNAMES,
- classOf[KyuubiScalaObjectMapper].getName)
+ val openapiConf: ResourceConfig = new OpenAPIConfig
+ val servlet = new ServletHolder(new ServletContainer(openapiConf))
val handler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS)
BackendServiceProvider.setBackendService(handler, backendService)
- handler.setContextPath("/api")
handler.addServlet(servlet, "/*")
+
+ // install swagger-ui, these static files are copied from
+ // https://github.com/swagger-api/swagger-ui/tree/master/dist
+ val swaggerUI = new ServletHolder("swagger-ui", classOf[DefaultServlet])
+ swaggerUI.setInitParameter("resourceBase",
+ getClass.getClassLoader()
+ .getResource("META-INF/resources/webjars/swagger-ui/4.1.0/")
+ .toExternalForm)
+ swaggerUI.setInitParameter("pathInfoOnly", "true")
+ handler.addServlet(swaggerUI, "/swagger-ui-redirected/*");
handler
}
}
diff --git
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/ApiRootResource.scala
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/ApiRootResource.scala
index 751de24..b41290b 100644
---
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/ApiRootResource.scala
+++
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/ApiRootResource.scala
@@ -17,13 +17,16 @@
package org.apache.kyuubi.server.api.v1
-import com.google.common.annotations.VisibleForTesting
+import java.net.URI
import javax.ws.rs.{GET, Path, Produces}
import javax.ws.rs.core.{MediaType, Response}
+import com.google.common.annotations.VisibleForTesting
+
+import org.apache.kyuubi.server.KyuubiServer
import org.apache.kyuubi.server.api.ApiRequestContext
-@Path("/v1")
+@Path("/api/v1")
private[v1] class ApiRootResource extends ApiRequestContext {
@GET
@@ -43,4 +46,14 @@ private[v1] class ApiRootResource extends ApiRequestContext {
Response.ok().build()
}
+ @GET
+ @Path("swagger-ui")
+ @Produces(Array(MediaType.TEXT_HTML))
+ def swaggerUi(): Response = {
+ val serverIP =
KyuubiServer.kyuubiServer.frontendServices.head.connectionUrl
+ val swaggerUi =
+
s"http://$serverIP/swagger-ui-redirected/index.html?url=http://$serverIP/openapi.json"
+ Response.temporaryRedirect(new URI(swaggerUi)).build()
+ }
+
}
diff --git
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/SessionsResource.scala
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/SessionsResource.scala
index 7ac06dc..30c5532 100644
---
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/SessionsResource.scala
+++
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/SessionsResource.scala
@@ -19,11 +19,15 @@ package org.apache.kyuubi.server.api.v1
import java.util.UUID
import javax.ws.rs._
+import javax.ws.rs.{Consumes, DELETE, GET, Path, PathParam, POST, Produces}
import javax.ws.rs.core.{MediaType, Response}
import scala.collection.JavaConverters._
import scala.util.control.NonFatal
+import io.swagger.v3.oas.annotations.media.Content
+import io.swagger.v3.oas.annotations.responses.ApiResponse
+import io.swagger.v3.oas.annotations.tags.Tag
import org.apache.hive.service.rpc.thrift.{TGetInfoType, TProtocolVersion}
import org.apache.kyuubi.Utils.error
@@ -32,19 +36,34 @@ import org.apache.kyuubi.operation.OperationHandle
import org.apache.kyuubi.server.api.ApiRequestContext
import org.apache.kyuubi.session.SessionHandle
+@Tag(name = "Session")
@Produces(Array(MediaType.APPLICATION_JSON))
private[v1] class SessionsResource extends ApiRequestContext {
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "get all the session list hosted in SessionManager"
+ )
@GET
def sessionInfoList(): SessionList = {
SessionList(
backendService.sessionManager.getSessionList().asScala.map {
case (handle, session) =>
SessionOverview(session.user, session.ipAddress, session.createTime,
handle)
- }.toList
+ }.toSeq
)
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "get a session via session handle identifier"
+ )
@GET
@Path("{sessionHandle}")
def sessionInfo(@PathParam("sessionHandle") sessionHandleStr: String):
SessionDetail = {
@@ -60,6 +79,14 @@ private[v1] class SessionsResource extends ApiRequestContext
{
}
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description =
+ "get a information detail via session handle identifier and a specific
information type"
+ )
@GET
@Path("{sessionHandle}/info/{infoType}")
def getInfo(@PathParam("sessionHandle") sessionHandleStr: String,
@@ -77,12 +104,26 @@ private[v1] class SessionsResource extends
ApiRequestContext {
}
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "Get the current open session count"
+ )
@GET
@Path("count")
def sessionCount(): SessionOpenCount = {
SessionOpenCount(backendService.sessionManager.getOpenSessionCount)
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "Get statistic info of background executors"
+ )
@GET
@Path("execPool/statistic")
def execPoolStatistic(): ExecPoolStatistic = {
@@ -90,6 +131,13 @@ private[v1] class SessionsResource extends
ApiRequestContext {
backendService.sessionManager.getActiveCount)
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "Open(create) a session"
+ )
@POST
@Consumes(Array(MediaType.APPLICATION_JSON))
def openSession(request: SessionOpenRequest): SessionHandle = {
@@ -101,6 +149,13 @@ private[v1] class SessionsResource extends
ApiRequestContext {
request.configs)
}
+ @ApiResponse(
+ responseCode = "200",
+ content = Array(new Content(
+ mediaType = MediaType.APPLICATION_JSON
+ )),
+ description = "Close a session"
+ )
@DELETE
@Path("{sessionHandle}")
def closeSession(@PathParam("sessionHandle") sessionHandleStr: String):
Response = {
diff --git
a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/dto.scala
b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/dto.scala
index 90fcde3..4abd17a 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/dto.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/v1/dto.scala
@@ -23,7 +23,7 @@ case class SessionOpenCount(openSessionCount: Int)
case class ExecPoolStatistic(execPoolSize: Int, execPoolActiveCount: Int)
-case class SessionList(sessionList: List[SessionOverview])
+case class SessionList(sessionList: Seq[SessionOverview])
case class SessionOverview(
user: String,
diff --git a/licenses-binary/LICENSE-edl.txt b/licenses-binary/LICENSE-edl.txt
new file mode 100644
index 0000000..6e96b02
--- /dev/null
+++ b/licenses-binary/LICENSE-edl.txt
@@ -0,0 +1,13 @@
+Eclipse Distribution License - v 1.0
+
+Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
+- Neither the name of the Eclipse Foundation, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFI [...]
diff --git a/pom.xml b/pom.xml
index 87d80a9..c7eadb1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -129,6 +129,9 @@
<spark.archive.name>spark-${spark.version}-bin-hadoop${hadoop.binary.version}.tgz</spark.archive.name>
<spark.archive.mirror>https://archive.apache.org/dist/spark/spark-${spark.version}</spark.archive.mirror>
<spark.archive.download.skip>false</spark.archive.download.skip>
+ <swagger.version>2.1.11</swagger.version>
+ <swagger.scala.module.version>2.5.2</swagger.scala.module.version>
+ <swagger-ui.version>4.1.0</swagger-ui.version>
<zookeeper.version>3.4.14</zookeeper.version>
<!-- only apply to kyuubi-hive-jdbc module -->
@@ -569,6 +572,30 @@
</dependency>
<dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-yaml</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jsr310</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-base</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-scala_${scala.binary.version}</artifactId>
<version>${jackson.version}</version>
@@ -591,6 +618,19 @@
</dependency>
<dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-jaxrs2</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+
+ <!-- ref:
https://github.com/swagger-akka-http/swagger-scala-module -->
+ <dependency>
+ <groupId>com.github.swagger-akka-http</groupId>
+
<artifactId>swagger-scala-module_${scala.binary.version}</artifactId>
+ <version>${swagger.scala.module.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
@@ -897,6 +937,18 @@
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.jdbc.version}</version>
</dependency>
+
+ <!--
+ 1. This library only contains swagger-ui static resource
(.html/.css/.js/.png), for more detail, see
+ https://github.com/swagger-api/swagger-ui/blob/master/dist/
+ 2. Note that when trying to upgrade swagger-ui, we should also
update the version in the file(
+
kyuubi-server/src/main/scala/org/apache/kyuubi/server/api/api.scala).
+ -->
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>swagger-ui</artifactId>
+ <version>${swagger-ui.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>