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

feiwang 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 fc3d282  [KYUUBI #1052] Implement api: /sessions (POST)
fc3d282 is described below

commit fc3d28295dd03f24e101068adb49337e3c1f6dbf
Author: yanghua <[email protected]>
AuthorDate: Sat Sep 11 22:52:48 2021 +0800

    [KYUUBI #1052] Implement api: /sessions (POST)
    
    <!--
    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.
    -->
    
    ### _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 #1073 from yanghua/KYUUBI-1052.
    
    Closes #1052
    
    926a6a62 [yanghua] Addressed review suggestion
    f227c042 [yanghua] [KYUUBI #1052] Implement api: /sessions (POST)
    
    Authored-by: yanghua <[email protected]>
    Signed-off-by: fwang12 <[email protected]>
---
 kyuubi-server/pom.xml                              | 12 ++++
 .../server/api/v1/dto/SessionOpenRequest.java      | 72 ++++++++++++++++++++
 .../server/api/v1/dto/SessionOpenedCount.java      | 18 +++++
 .../kyuubi/server/api/v1/SessionsResource.scala    | 21 +++++-
 .../kyuubi/server/RestFrontendServiceSuite.scala   | 46 ++++---------
 .../server/api/v1/SessionsResourceSuite.scala      | 78 ++++++++++++++++++++++
 pom.xml                                            | 22 ++++++
 7 files changed, 233 insertions(+), 36 deletions(-)

diff --git a/kyuubi-server/pom.xml b/kyuubi-server/pom.xml
index 8b18244..df79a6b 100644
--- a/kyuubi-server/pom.xml
+++ b/kyuubi-server/pom.xml
@@ -133,6 +133,18 @@
         </dependency>
 
         <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-jetty</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.kyuubi</groupId>
             <artifactId>kyuubi-common_${scala.binary.version}</artifactId>
             <version>${project.version}</version>
diff --git 
a/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenRequest.java
 
b/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenRequest.java
new file mode 100644
index 0000000..68f2c3a
--- /dev/null
+++ 
b/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenRequest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.v1.dto;
+
+import java.util.Map;
+
+public class SessionOpenRequest {
+
+  private int protocolVersion;
+  private String user;
+  private String password;
+  private String ipAddr;
+  private Map configs;
+
+  public SessionOpenRequest() {
+  }
+
+  public int getProtocolVersion() {
+    return protocolVersion;
+  }
+
+  public void setProtocolVersion(int protocolVersion) {
+    this.protocolVersion = protocolVersion;
+  }
+
+  public String getUser() {
+    return user;
+  }
+
+  public void setUser(String user) {
+    this.user = user;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public String getIpAddr() {
+    return ipAddr;
+  }
+
+  public void setIpAddr(String ipAddr) {
+    this.ipAddr = ipAddr;
+  }
+
+  public Map<String, String> getConfigs() {
+    return configs;
+  }
+
+  public void setConfigs(Map<String, String> configs) {
+    this.configs = configs;
+  }
+}
diff --git 
a/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenedCount.java
 
b/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenedCount.java
index 914793b..84964b4 100644
--- 
a/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenedCount.java
+++ 
b/kyuubi-server/src/main/java/org/apache/kyuubi/server/api/v1/dto/SessionOpenedCount.java
@@ -18,6 +18,7 @@
 package org.apache.kyuubi.server.api.v1.dto;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 public class SessionOpenedCount implements Serializable {
 
@@ -33,4 +34,21 @@ public class SessionOpenedCount implements Serializable {
   public void setOpenSessionCount(int openSessionCount) {
     this.openSessionCount = openSessionCount;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof SessionOpenedCount)) {
+      return false;
+    }
+    SessionOpenedCount that = (SessionOpenedCount) o;
+    return openSessionCount == that.getOpenSessionCount();
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(openSessionCount);
+  }
 }
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 9fcc9dd..201b2fc 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
@@ -17,15 +17,21 @@
 
 package org.apache.kyuubi.server.api.v1
 
-import javax.ws.rs.{GET, Path, Produces}
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.scala.DefaultScalaModule
+import javax.ws.rs.{Consumes, GET, Path, POST, Produces}
 import javax.ws.rs.core.MediaType
+import org.apache.hive.service.rpc.thrift.TProtocolVersion
+import scala.collection.JavaConverters.mapAsScalaMapConverter
 
 import org.apache.kyuubi.server.api.ApiRequestContext
-import org.apache.kyuubi.server.api.v1.dto.SessionOpenedCount
+import org.apache.kyuubi.server.api.v1.dto.{SessionOpenedCount, 
SessionOpenRequest}
 
 @Produces(Array(MediaType.APPLICATION_JSON))
 private[v1] class SessionsResource extends ApiRequestContext {
 
+  private val mapper = new ObjectMapper().registerModule(DefaultScalaModule)
+
   @GET
   @Path("count")
   def sessionCount(): SessionOpenedCount = {
@@ -36,4 +42,15 @@ private[v1] class SessionsResource extends ApiRequestContext 
{
     sessionOpenedCount
   }
 
+  @POST
+  @Consumes(Array(MediaType.APPLICATION_JSON))
+  def openSession(request : SessionOpenRequest): String = {
+    val sessionHandle = backendService.openSession(
+      TProtocolVersion.findByValue(request.getProtocolVersion),
+      request.getUser,
+      request.getPassword,
+      request.getIpAddr,
+      request.getConfigs.asScala.toMap)
+    mapper.writeValueAsString(sessionHandle)
+  }
 }
diff --git 
a/kyuubi-server/src/test/scala/org/apache/kyuubi/server/RestFrontendServiceSuite.scala
 
b/kyuubi-server/src/test/scala/org/apache/kyuubi/server/RestFrontendServiceSuite.scala
index 531bda6..4c73b7a 100644
--- 
a/kyuubi-server/src/test/scala/org/apache/kyuubi/server/RestFrontendServiceSuite.scala
+++ 
b/kyuubi-server/src/test/scala/org/apache/kyuubi/server/RestFrontendServiceSuite.scala
@@ -20,20 +20,19 @@ package org.apache.kyuubi.server
 import java.util.Locale
 
 import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.scala.DefaultScalaModule
 import org.scalatest.time.SpanSugar._
 import scala.io.Source
 
 import org.apache.kyuubi.KyuubiFunSuite
 import org.apache.kyuubi.config.KyuubiConf
-import org.apache.kyuubi.server.api.v1.dto.SessionOpenedCount
-import org.apache.kyuubi.service.{NoopBackendService, NoopServer}
+import org.apache.kyuubi.service.NoopServer
 import org.apache.kyuubi.service.ServiceState._
-import org.apache.kyuubi.session.{NoopSessionImpl, NoopSessionManager, 
SessionManager}
 
 class RestFrontendServiceSuite extends KyuubiFunSuite{
 
   test("kyuubi rest frontend service basic") {
-    val server = new RestNoopServer()
+    val server = new RestFrontendServiceSuite.RestNoopServer()
     server.stop()
     val conf = KyuubiConf()
     assert(server.getServices.isEmpty)
@@ -64,7 +63,7 @@ class RestFrontendServiceSuite extends KyuubiFunSuite{
   }
 
   test("kyuubi rest frontend service http basic") {
-    withKyuubiRestServer {
+    RestFrontendServiceSuite.withKyuubiRestServer {
       (_, host, port) =>
         eventually(timeout(10.seconds), interval(50.milliseconds)) {
           val html = Source.fromURL(s"http://$host:$port/api/v1/ping";).mkString
@@ -72,21 +71,17 @@ class RestFrontendServiceSuite extends KyuubiFunSuite{
         }
     }
   }
+}
 
-  test("kyuubi rest frontend service for sessions resource") {
-    withKyuubiRestServer {
-      (_, host, port) =>
-        val expectedCount = new SessionOpenedCount()
-        expectedCount.setOpenSessionCount(1)
-        val expectedStr = new ObjectMapper().writeValueAsString(expectedCount)
+object RestFrontendServiceSuite {
 
-        eventually(timeout(10.seconds), interval(50.milliseconds)) {
-          val html = 
Source.fromURL(s"http://$host:$port/api/v1/sessions/count";).mkString
-          assert(html.toLowerCase(Locale.ROOT).equalsIgnoreCase(expectedStr))
-        }
-    }
+  class RestNoopServer extends NoopServer {
+    override val frontendService = new RestFrontendService(backendService)
   }
 
+  val OBJECT_MAPPER = new ObjectMapper().registerModule(DefaultScalaModule)
+  val TEST_SERVER_PORT = KyuubiConf().get(KyuubiConf.FRONTEND_REST_BIND_PORT)
+
   def withKyuubiRestServer(f: (RestFrontendService, String, Int) => Unit): 
Unit = {
     val server = new RestNoopServer()
     server.stop()
@@ -100,27 +95,10 @@ class RestFrontendServiceSuite extends KyuubiFunSuite{
 
     try {
       f(frontendService, conf.get(KyuubiConf.FRONTEND_REST_BIND_HOST).get,
-        conf.get(KyuubiConf.FRONTEND_REST_BIND_PORT))
+        TEST_SERVER_PORT)
     } finally {
       server.stop()
     }
   }
 
-  class RestNoopServer extends NoopServer {
-    override val backendService: NoopBackendService = new RestMockedBeService
-    override val frontendService = new RestFrontendService(backendService)
-  }
-
-  class RestMockedBeService extends NoopBackendService {
-    override val sessionManager: SessionManager = new 
RestMockedSessionManager()
-  }
-
-  class RestMockedSessionManager extends NoopSessionManager {
-    // It's a ugly and temporally implementation will replace it via creation 
rest API.
-    var session = new NoopSessionImpl(null, null, null, null, Map(), this)
-    setSession(session.handle, session)
-
-    override protected def isServer: Boolean = true
-  }
-
 }
diff --git 
a/kyuubi-server/src/test/scala/org/apache/kyuubi/server/api/v1/SessionsResourceSuite.scala
 
b/kyuubi-server/src/test/scala/org/apache/kyuubi/server/api/v1/SessionsResourceSuite.scala
new file mode 100644
index 0000000..41ca013
--- /dev/null
+++ 
b/kyuubi-server/src/test/scala/org/apache/kyuubi/server/api/v1/SessionsResourceSuite.scala
@@ -0,0 +1,78 @@
+/*
+ * 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.v1
+
+import javax.ws.rs.client.Entity
+import javax.ws.rs.core.{Application, MediaType}
+
+import org.glassfish.jersey.server.ResourceConfig
+import org.glassfish.jersey.test.{JerseyTest, TestProperties}
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory
+import org.glassfish.jersey.test.spi.TestContainerFactory
+import org.junit.Test
+
+import org.apache.kyuubi.server.RestFrontendServiceSuite
+import org.apache.kyuubi.server.RestFrontendServiceSuite.{OBJECT_MAPPER, 
TEST_SERVER_PORT}
+import org.apache.kyuubi.server.api.v1.dto.{SessionOpenedCount, 
SessionOpenRequest}
+import org.apache.kyuubi.session.SessionHandle
+
+class SessionsResourceSuite extends JerseyTest {
+
+  override def configure: Application = {
+    forceSet(TestProperties.CONTAINER_PORT, TEST_SERVER_PORT.toString)
+    new ResourceConfig(getClass)
+  }
+
+  override def getTestContainerFactory: TestContainerFactory = new 
JettyTestContainerFactory
+
+  @Test
+  def testOpenAndCountSession: Unit = {
+    val requestObj = new SessionOpenRequest
+    requestObj.setProtocolVersion(1)
+    requestObj.setUser("admin")
+    requestObj.setPassword("123456")
+    requestObj.setIpAddr("localhost")
+    val configs = new java.util.HashMap[String, String]
+    configs.put("testConfig", "testValue")
+    requestObj.setConfigs(configs)
+
+    RestFrontendServiceSuite.withKyuubiRestServer {
+      (_, _, _) =>
+        var response = target(s"api/v1/sessions")
+          .request(MediaType.APPLICATION_JSON_TYPE)
+          .post(Entity.entity(requestObj, MediaType.APPLICATION_JSON_TYPE))
+
+        assert(200 == response.getStatus)
+
+        val sessionHandle = OBJECT_MAPPER.readValue(
+          response.readEntity(classOf[String]), classOf[SessionHandle])
+
+        assert(sessionHandle.protocol.getValue == 1)
+        assert(sessionHandle.identifier != null)
+
+        // verify the open session count
+        val expectedCount = new SessionOpenedCount()
+        expectedCount.setOpenSessionCount(1)
+
+        response = target("api/v1/sessions/count").request().get()
+        val responseObj = response.readEntity(classOf[SessionOpenedCount])
+        assert(responseObj.equals(expectedCount))
+    }
+  }
+
+}
diff --git a/pom.xml b/pom.xml
index be40371..2212752 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1292,6 +1292,28 @@
                 <artifactId>jersey-media-json-jackson</artifactId>
                 <version>${jersey.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>org.glassfish.jersey.test-framework</groupId>
+                <artifactId>jersey-test-framework-core</artifactId>
+                <version>${jersey.version}</version>
+            </dependency>
+
+            <dependency>
+                
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
+                <artifactId>jersey-test-framework-provider-jetty</artifactId>
+                <version>${jersey.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.eclipse.jetty</groupId>
+                        <artifactId>jetty-util</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>org.eclipse.jetty</groupId>
+                        <artifactId>jetty-continuation</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

Reply via email to