Pārlūkot izejas kodu

LIVY-275. Add livy REST API to detect Livy version info (#262)

* Add livy REST API to get Livy build info

Change-Id: I56c5116f6f74357d06ceabcad38ac5988003ccf5

* Change some typos

Change-Id: If47570766e19b98b88de521aa57dfae1ae5b48d9

* Address the comments

Change-Id: I961979534281e7bb5030a8c471e5245c7dedca82
Saisai Shao 8 gadi atpakaļ
vecāks
revīzija
c9f947efc7

+ 38 - 0
dev/livy-build-info.sh

@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+# This script generates the build info for Livy and places it into the livy-version-info.properties file.
+# Arguments:
+#   build_tgt_directory - The target directory where properties file would be created. [./server/target/extra-resources]
+#   livy_version - The current version of livy
+
+RESOURCE_DIR="$1"
+mkdir -p "$RESOURCE_DIR"
+LIVY_BUILD_INFO="${RESOURCE_DIR}"/livy-version-info.properties
+
+echo_build_properties() {
+  echo version=$1
+  echo user=$USER
+  echo revision=$(git rev-parse HEAD)
+  echo branch=$(git rev-parse --abbrev-ref HEAD)
+  echo date=$(date -u +%Y-%m-%dT%H:%M:%SZ)
+  echo url=$(git config --get remote.origin.url)
+}
+
+echo_build_properties $2 > "$LIVY_BUILD_INFO"

+ 31 - 0
server/pom.xml

@@ -221,6 +221,14 @@
     </dependencies>
 
     <build>
+        <resources>
+            <resource>
+                <!-- Include the properties file to provide the build information. -->
+                <directory>${project.build.directory}/extra-resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
@@ -248,6 +256,29 @@
                 </executions>
             </plugin>
 
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-resources</phase>
+                        <configuration>
+                            <!-- Execute the shell script to generate the spark build information. -->
+                            <target>
+                                <exec executable="bash">
+                                    <arg value="${project.basedir}/../dev/livy-build-info.sh"/>
+                                    <arg value="${project.build.directory}/extra-resources"/>
+                                    <arg value="${project.version}"/>
+                                </exec>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
         </plugins>
     </build>
 

+ 74 - 0
server/src/main/scala/com/cloudera/livy/package.scala

@@ -0,0 +1,74 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera
+
+import java.util.Properties
+
+import scala.util.control.NonFatal
+
+package object livy {
+
+  private object LivyBuildInfo {
+    val (
+        livyVersion: String,
+        livyBuildUser: String,
+        livyRevision: String,
+        livyBranch: String,
+        livyBuildDate: String,
+        livyRepo: String
+      ) = {
+      val unknown = "<unknown>"
+      val defaultValue = (unknown, unknown, unknown, unknown, unknown, unknown)
+      val resource = Option(Thread.currentThread().getContextClassLoader
+        .getResourceAsStream("livy-version-info.properties"))
+
+      try {
+        resource.map { r =>
+          val properties = new Properties()
+          properties.load(r)
+          (
+            properties.getProperty("version", unknown),
+            properties.getProperty("user", unknown),
+            properties.getProperty("revision", unknown),
+            properties.getProperty("branch", unknown),
+            properties.getProperty("date", unknown),
+            properties.getProperty("url", unknown)
+          )
+        }.getOrElse(defaultValue)
+      } catch {
+        case NonFatal(e) =>
+          // swallow the exception
+          defaultValue
+      } finally {
+        try {
+          resource.foreach(_.close())
+        } catch {
+          case NonFatal(e) => // swallow the exception in closing the stream
+        }
+      }
+    }
+  }
+
+  val LIVY_VERSION = LivyBuildInfo.livyVersion
+  val LIVY_BUILD_USER = LivyBuildInfo.livyBuildUser
+  val LIVY_REVISION = LivyBuildInfo.livyRevision
+  val LIVY_BRANCH = LivyBuildInfo.livyBranch
+  val LIVY_BUILD_DATE = LivyBuildInfo.livyBuildDate
+  val LIVY_REPO_URL = LivyBuildInfo.livyRepo
+}

+ 16 - 0
server/src/main/scala/com/cloudera/livy/server/LivyServer.scala

@@ -100,6 +100,20 @@ class LivyServer extends Logging {
 
     server = new WebServer(livyConf, host, port)
     server.context.setResourceBase("src/main/com/cloudera/livy/server")
+
+    val livyVersionServlet = new JsonServlet {
+      before() { contentType = "application/json" }
+
+      get("/") {
+        Map("version" -> LIVY_VERSION,
+          "user" -> LIVY_BUILD_USER,
+          "revision" -> LIVY_REVISION,
+          "branch" -> LIVY_BRANCH,
+          "date" -> LIVY_BUILD_DATE,
+          "url" -> LIVY_REPO_URL)
+      }
+    }
+
     server.context.addEventListener(
       new ServletContextListener() with MetricsBootstrap with ServletApiImplicits {
 
@@ -126,6 +140,8 @@ class LivyServer extends Logging {
             mount(context, batchServlet, "/batches/*")
 
             context.mountMetricsAdminServlet("/")
+
+            mount(context, livyVersionServlet, "/version/*")
           } catch {
             case e: Throwable =>
               error("Exception thrown when initializing server", e)