LIVY-287. Add Deprecation to Livy Configurations and update naming. (#300)

Updates to Livy configurations

- Added config deprecation with alternatives to ClientConf, HTTPConf, RSCConf, 
and LivyConf.
- Added framework for deprecation without alternatives when the need arises.
- Updated naming conventions in code and templates to use - instead of _ or 
camelCase and deprecated previous configs.
- Updated TestClientConf and added a new test.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/221aa9cf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/221aa9cf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/221aa9cf

Branch: refs/heads/master
Commit: 221aa9cf8f33b48fd9c792f67c61b78708bfae99
Parents: 0de0e28
Author: Alex Bozarth <ajboz...@us.ibm.com>
Authored: Wed Apr 5 15:56:48 2017 -0700
Committer: Alex Man <alex-the-...@users.noreply.github.com>
Committed: Wed Apr 5 15:56:48 2017 -0700

----------------------------------------------------------------------
 client-common/pom.xml                           |  5 ++
 .../cloudera/livy/client/common/ClientConf.java | 61 ++++++++++++-
 .../livy/client/common/TestClientConf.java      | 75 +++++++++++++++-
 .../com/cloudera/livy/client/http/HttpConf.java | 59 ++++++++++++-
 conf/livy-client.conf.template                  | 18 ++--
 conf/livy.conf.template                         | 10 +--
 conf/spark-blacklist.conf.template              |  2 +-
 .../livy/test/framework/MiniCluster.scala       |  4 +-
 .../livy/repl/SparkContextInitializer.scala     |  4 +-
 .../java/com/cloudera/livy/rsc/RSCConf.java     | 91 ++++++++++++++++----
 .../main/scala/com/cloudera/livy/LivyConf.scala | 65 +++++++++++---
 .../com/cloudera/livy/server/LivyServer.scala   |  2 +-
 .../server/interactive/InteractiveSession.scala |  2 +-
 13 files changed, 344 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index 9cc713c..e41aaae 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -45,5 +45,10 @@
       <artifactId>jackson-databind</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
----------------------------------------------------------------------
diff --git 
a/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java 
b/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
index 59cce37..4eb7929 100644
--- 
a/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
+++ 
b/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
@@ -28,6 +28,9 @@ import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.cloudera.livy.annotations.Private;
 
 /**
@@ -37,6 +40,8 @@ import com.cloudera.livy.annotations.Private;
 public abstract class ClientConf<T extends ClientConf>
   implements Iterable<Map.Entry<String, String>> {
 
+  protected Logger LOG = LoggerFactory.getLogger(getClass());
+
   public static interface ConfEntry {
 
     /** The key in the configuration file. */
@@ -71,24 +76,37 @@ public abstract class ClientConf<T extends ClientConf>
     this.config = new ConcurrentHashMap<>();
     if (config != null) {
       for (String key : config.stringPropertyNames()) {
+        logDeprecationWarning(key);
         this.config.put(key, config.getProperty(key));
       }
     }
   }
 
   public String get(String key) {
-    return config.get(key);
+    String val = config.get(key);
+    if (val != null) {
+      return val;
+    }
+    DeprecatedConf depConf = getConfigsWithAlternatives().get(key);
+    if (depConf != null) {
+      return config.get(depConf.key());
+    } else {
+      return val;
+    }
   }
 
   @SuppressWarnings("unchecked")
   public T set(String key, String value) {
+    logDeprecationWarning(key);
     config.put(key, value);
     return (T) this;
   }
 
   @SuppressWarnings("unchecked")
   public T setIfMissing(String key, String value) {
-    config.putIfAbsent(key, value);
+    if (config.putIfAbsent(key, value) == null) {
+      logDeprecationWarning(key);
+    }
     return (T) this;
   }
 
@@ -163,6 +181,7 @@ public abstract class ClientConf<T extends ClientConf>
     if (value == null) {
       config.remove(e.key());
     } else {
+      logDeprecationWarning(e.key());
       config.put(e.key(), value.toString());
     }
     return (T) this;
@@ -176,7 +195,7 @@ public abstract class ClientConf<T extends ClientConf>
   private String get(ConfEntry e, Class<?> requestedType) {
     check(getType(e.dflt()).equals(requestedType), "Invalid type conversion 
requested for %s.",
       e.key());
-    return config.get(e.key());
+    return this.get(e.key());
   }
 
   private boolean typesMatch(Object test, Object expected) {
@@ -193,4 +212,40 @@ public abstract class ClientConf<T extends ClientConf>
     }
   }
 
+  /** Logs a warning message if the given config key is deprecated. */
+  private void logDeprecationWarning(String key) {
+    DeprecatedConf altConfs = getConfigsWithAlternatives().get(key);
+    if (altConfs != null) {
+      LOG.warn("The configuration key " + altConfs.key() + " has been 
deprecated as of Livy "
+        + altConfs.version() + " and may be removed in the future. Please use 
the new key "
+        + key + " instead.");
+      return;
+    }
+
+    DeprecatedConf depConfs = getDeprecatedConfigs().get(key);
+    if (depConfs != null) {
+      LOG.warn("The configuration key " + depConfs.key() + " has been 
deprecated as of Livy "
+        + depConfs.version() + " and may be removed in the future. "
+        + depConfs.deprecationMessage());
+    }
+  }
+
+  /** Maps valid key to DeprecatedConf with the deprecated key. */
+  protected abstract Map<String, DeprecatedConf> getConfigsWithAlternatives();
+
+  /** Maps deprecated key to DeprecatedConf with the same key. */
+  protected abstract Map<String, DeprecatedConf> getDeprecatedConfigs();
+
+  public static interface DeprecatedConf {
+
+    /** The key in the configuration file. */
+    String key();
+
+    /** The Livy version in which the key was deprecated. */
+    String version();
+
+    /** Message to include in the deprecation warning for configs without 
alternatives */
+    String deprecationMessage();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
----------------------------------------------------------------------
diff --git 
a/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
 
b/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
index c8bd9c9..afb7798 100644
--- 
a/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
+++ 
b/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
@@ -18,6 +18,8 @@
 
 package com.cloudera.livy.client.common;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
@@ -122,6 +124,31 @@ public class TestClientConf {
     conf.getTimeAsMs(TestConf.Entry.TIME_NO_DEFAULT);
   }
 
+
+  @Test
+  public void testDeprecation() {
+    TestConf conf = new TestConf(null);
+
+    assertNull(conf.get("depKey"));
+    assertNull(conf.get("dep_alt"));
+    assertNull(conf.get("new-key"));
+    assertEquals("value", conf.get(TestConf.Entry.NEW_CONF));
+
+    TestConf depProps = new TestConf(null);
+    depProps.set("depKey", "dep-val");
+    depProps.set("dep_alt", "alt-val");
+    conf.setAll(depProps);
+    assertEquals("dep-val", conf.get("depKey"));
+    assertEquals("alt-val", conf.get("dep_alt"));
+    assertEquals("alt-val", conf.get(TestConf.Entry.NEW_CONF));
+    assertEquals("alt-val", conf.get("new-key"));
+
+    conf.set("new-key", "new-val");
+    assertEquals("new-val", conf.get(TestConf.Entry.NEW_CONF));
+    assertEquals("alt-val", conf.get("dep_alt"));
+    assertEquals("new-val", conf.get("new-key"));
+  }
+
   private static class TestConf extends ClientConf<TestConf> {
 
     static enum Entry implements ConfEntry {
@@ -131,7 +158,8 @@ public class TestClientConf {
       INT("int", 42),
       LONG("long", 84L),
       TIME("time", "168ms"),
-      TIME_NO_DEFAULT("time2", null);
+      TIME_NO_DEFAULT("time2", null),
+      NEW_CONF("new-key", "value");
 
       private final String key;
       private final Object dflt;
@@ -153,6 +181,51 @@ public class TestClientConf {
       super(p);
     }
 
+    private static final Map<String, DeprecatedConf> configsWithAlternatives
+      = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(TestConf.Entry.NEW_CONF.key, DepConf.DEP_WITH_ALT);
+    }});
+
+    private static final Map<String, DeprecatedConf> deprecatedConfigs
+      = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(DepConf.DEP_NO_ALT.key, DepConf.DEP_NO_ALT);
+    }});
+
+    protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+      return configsWithAlternatives;
+    }
+
+    protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+      return deprecatedConfigs;
+    }
+
+    static enum DepConf implements DeprecatedConf {
+      DEP_WITH_ALT("dep_alt", "0.4"),
+      DEP_NO_ALT("depKey", "1.0");
+
+      private final String key;
+      private final String version;
+      private final String deprecationMessage;
+
+      private DepConf(String key, String version) {
+        this(key, version, "");
+      }
+
+      private DepConf(String key, String version, String deprecationMessage) {
+        this.key = key;
+        this.version = version;
+        this.deprecationMessage = deprecationMessage;
+      }
+
+      @Override
+      public String key() { return key; }
+
+      @Override
+      public String version() { return version; }
+
+      @Override
+      public String deprecationMessage() { return deprecationMessage; }
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
----------------------------------------------------------------------
diff --git 
a/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java 
b/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
index 24c191c..2ae25e5 100644
--- a/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
+++ b/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
@@ -18,19 +18,24 @@
 
 package com.cloudera.livy.client.http;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 
 import com.cloudera.livy.client.common.ClientConf;
 
 class HttpConf extends ClientConf<HttpConf> {
 
+  private static final String HTTP_CONF_PREFIX = "livy.client.http.";
+
   static enum Entry implements ConfEntry {
     CONNECTION_TIMEOUT("connection.timeout", "10s"),
     CONNECTION_IDLE_TIMEOUT("connection.idle.timeout", "10m"),
     SOCKET_TIMEOUT("connection.socket.timeout", "5m"),
 
-    JOB_INITIAL_POLL_INTERVAL("job.initial_poll_interval", "100ms"),
-    JOB_MAX_POLL_INTERVAL("job.max_poll_interval", "5s"),
+    JOB_INITIAL_POLL_INTERVAL("job.initial-poll-interval", "100ms"),
+    JOB_MAX_POLL_INTERVAL("job.max-poll-interval", "5s"),
 
     CONTENT_COMPRESS_ENABLE("content.compress.enable", true),
 
@@ -44,7 +49,7 @@ class HttpConf extends ClientConf<HttpConf> {
     private final Object dflt;
 
     private Entry(String key, Object dflt) {
-      this.key = "livy.client.http." + key;
+      this.key = HTTP_CONF_PREFIX + key;
       this.dflt = dflt;
     }
 
@@ -80,4 +85,52 @@ class HttpConf extends ClientConf<HttpConf> {
   boolean isSpnegoEnabled() {
     return getBoolean(Entry.SPNEGO_ENABLED);
   }
+
+  private static final Map<String, DeprecatedConf> configsWithAlternatives
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(HttpConf.Entry.JOB_INITIAL_POLL_INTERVAL.key, 
DepConf.JOB_INITIAL_POLL_INTERVAL);
+      put(HttpConf.Entry.JOB_MAX_POLL_INTERVAL.key, 
DepConf.JOB_MAX_POLL_INTERVAL);
+  }});
+
+  // Maps deprecated key to DeprecatedConf with the same key.
+  // There are no deprecated configs without alternatives currently.
+  private static final Map<String, DeprecatedConf> deprecatedConfigs
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>());
+
+  protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+    return configsWithAlternatives;
+  }
+
+  protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+    return deprecatedConfigs;
+  }
+
+  static enum DepConf implements DeprecatedConf {
+    JOB_INITIAL_POLL_INTERVAL("job.initial_poll_interval", "0.4"),
+    JOB_MAX_POLL_INTERVAL("job.max_poll_interval", "0.4");
+
+    private final String key;
+    private final String version;
+    private final String deprecationMessage;
+
+    private DepConf(String key, String version) {
+      this(key, version, "");
+    }
+
+    private DepConf(String key, String version, String deprecationMessage) {
+      this.key = HTTP_CONF_PREFIX + key;
+      this.version = version;
+      this.deprecationMessage = deprecationMessage;
+    }
+
+    @Override
+    public String key() { return key; }
+
+    @Override
+    public String version() { return version; }
+
+    @Override
+    public String deprecationMessage() { return deprecationMessage; }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/livy-client.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy-client.conf.template b/conf/livy-client.conf.template
index c0adb30..2a92b57 100644
--- a/conf/livy-client.conf.template
+++ b/conf/livy-client.conf.template
@@ -22,9 +22,9 @@
 # livy.client.http.connection.idle.timeout = 10m
 
 # Initial interval before polling for Job results
-# livy.client.http.job.initial_poll_interval = 100ms
+# livy.client.http.job.initial-poll-interval = 100ms
 # Maximum interval between successive polls
-# livy.client.http.job.max_poll_interval = 5s
+# livy.client.http.job.max-poll-interval = 5s
 
 #
 # Configurations for Livy RSCClient
@@ -37,10 +37,10 @@
 # livy.rsc.client.auth.secret =
 
 # Timeout when stopping a rsc client
-# livy.rsc.client.shutdown_timeout = 10s
+# livy.rsc.client.shutdown-timeout = 10s
 
 # Class of the rsc driver to use
-# livy.rsc.driver_class =
+# livy.rsc.driver-class =
 # The kind of rsc session. Examples: pyspark or sparkr
 # livy.rsc.session.kind =
 
@@ -58,10 +58,10 @@
 # livy.rsc.launcher.port = -1
 
 # How long will the RSC wait for a connection for a Livy server before 
shutting itself down.
-# livy.rsc.server.idle_timeout = 10m
+# livy.rsc.server.idle-timeout = 10m
 
 # The user that should be impersonated when requesting a Livy session
-# livy.rsc.proxy_user =
+# livy.rsc.proxy-user =
 
 # Host or IP adress of the rpc server
 # livy.rsc.rpc.server.address =
@@ -78,9 +78,9 @@
 # livy.rsc.rpc.sasl.qop =
 
 # Time between status checks for cancelled a Job
-# livy.rsc.job_cancel.trigger_interval = 100ms
+# livy.rsc.job-cancel.trigger-interval = 100ms
 # Time before a cancelled a Job is forced into a Cancelled state
-# livy.rsc.job_cancel.timeout = 30s
+# livy.rsc.job-cancel.timeout = 30s
 
 # Number of statements kept in driver's memory
-# livy.rsc.retained_statements = 100
\ No newline at end of file
+# livy.rsc.retained-statements = 100
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
index 8c5fe03..dd2f054 100644
--- a/conf/livy.conf.template
+++ b/conf/livy.conf.template
@@ -17,7 +17,7 @@
 # livy.spark.master = local
 
 # What spark deploy mode Livy sessions should use.
-# livy.spark.deployMode =
+# livy.spark.deploy-mode =
 
 # Enabled to check whether timeout Livy sessions should be stopped.
 # livy.server.session.timeout-check = true
@@ -58,11 +58,11 @@
 
 # Whether to enable csrf protection, by default it is false. If it is enabled, 
client should add
 # http-header "X-Requested-By" in request if the http method is 
POST/DELETE/PUT/PATCH.
-# livy.server.csrf_protection.enabled =
+# livy.server.csrf-protection.enabled =
 
 # Whether to enable HiveContext in livy interpreter, if it is true 
hive-site.xml will be detected
 # on user request and then livy server classpath automatically.
-# livy.repl.enableHiveContext =
+# livy.repl.enable-hive-context =
 
 # Recovery mode of Livy. Possible values:
 # off: Default. Turn off recovery. Every time Livy shuts down, it stops and 
forgets all sessions.
@@ -88,9 +88,9 @@
 # When the cluster is busy, we may fail to launch yarn app in 
app-lookup-timeout, then it would
 # cause session leakage, so we need to check session leakage.
 # How long to check livy session leakage
-# livy.server.yarn.app-leakage.check_timeout = 600s
+# livy.server.yarn.app-leakage.check-timeout = 600s
 # how often to check livy session leakage
-# livy.server.yarn.app-leakage.check_interval = 60s
+# livy.server.yarn.app-leakage.check-interval = 60s
 
 # How often Livy polls YARN to refresh YARN app state.
 # livy.server.yarn.poll-interval = 1s

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/spark-blacklist.conf.template
----------------------------------------------------------------------
diff --git a/conf/spark-blacklist.conf.template 
b/conf/spark-blacklist.conf.template
index f0919b0..b9f0ec2 100644
--- a/conf/spark-blacklist.conf.template
+++ b/conf/spark-blacklist.conf.template
@@ -16,4 +16,4 @@ spark.yarn.jars
 spark.yarn.archive
 
 # Don't allow users to override the RSC timeout.
-livy.rsc.server.idle_timeout
+livy.rsc.server.idle-timeout

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
----------------------------------------------------------------------
diff --git 
a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
 
b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
index d520269..6aa02f1 100644
--- 
a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
+++ 
b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
@@ -176,7 +176,7 @@ object MiniLivyMain extends MiniClusterBase {
     // server. Do it atomically since it's used by MiniCluster to detect when 
the Livy server
     // is up and ready.
     eventually(timeout(30 seconds), interval(1 second)) {
-      val serverUrlConf = Map("livy.server.serverUrl" -> server.serverUrl())
+      val serverUrlConf = Map("livy.server.server-url" -> server.serverUrl())
       saveProperties(serverUrlConf, new File(configPath + "/serverUrl.conf"))
     }
   }
@@ -297,7 +297,7 @@ class MiniCluster(config: Map[String, String]) extends 
Cluster with MiniClusterU
     val localLivy = start(MiniLivyMain.getClass, confFile, extraJavaArgs = 
jacocoArgs)
 
     val props = loadProperties(confFile)
-    livyUrl = props("livy.server.serverUrl")
+    livyUrl = props("livy.server.server-url")
 
     // Wait until Livy server responds.
     val httpClient = new AsyncHttpClient()

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
----------------------------------------------------------------------
diff --git 
a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala 
b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
index fd082eb..533741d 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
@@ -46,7 +46,7 @@ trait SparkContextInitializer extends Logging {
         val loader = Option(Thread.currentThread().getContextClassLoader)
           .getOrElse(getClass.getClassLoader)
         if (loader.getResource("hive-site.xml") == null) {
-          warn("livy.repl.enableHiveContext is true but no hive-site.xml found 
on classpath.")
+          warn("livy.repl.enable-hive-context is true but no hive-site.xml 
found on classpath.")
         }
 
         sqlContext = Class.forName("org.apache.spark.sql.hive.HiveContext")
@@ -87,7 +87,7 @@ trait SparkContextInitializer extends Logging {
         val loader = Option(Thread.currentThread().getContextClassLoader)
           .getOrElse(getClass.getClassLoader)
         if (loader.getResource("hive-site.xml") == null) {
-          warn("livy.repl.enableHiveContext is true but no hive-site.xml found 
on classpath.")
+          warn("livy.repl.enable-hive-context is true but no hive-site.xml 
found on classpath.")
         }
 
         builder.getClass.getMethod("enableHiveSupport").invoke(builder)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java 
b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
index 0d7b1c1..d1b8b39 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
@@ -21,15 +21,13 @@ import java.io.IOException;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 import javax.security.sasl.Sasl;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.cloudera.livy.client.common.ClientConf;
 
 public class RSCConf extends ClientConf<RSCConf> {
@@ -37,14 +35,14 @@ public class RSCConf extends ClientConf<RSCConf> {
   public static final String SPARK_CONF_PREFIX = "spark.";
   public static final String LIVY_SPARK_PREFIX = SPARK_CONF_PREFIX + 
"__livy__.";
 
-  private static final Logger LOG = LoggerFactory.getLogger(RSCConf.class);
+  private static final String RSC_CONF_PREFIX = "livy.rsc.";
 
   public static enum Entry implements ConfEntry {
     CLIENT_ID("client.auth.id", null),
     CLIENT_SECRET("client.auth.secret", null),
-    CLIENT_IN_PROCESS("client.do_not_use.run_driver_in_process", false),
-    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown_timeout", "10s"),
-    DRIVER_CLASS("driver_class", null),
+    CLIENT_IN_PROCESS("client.do-not-use.run-driver-in-process", false),
+    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown-timeout", "10s"),
+    DRIVER_CLASS("driver-class", null),
     SESSION_KIND("session.kind", null),
 
     LIVY_JARS("jars", null),
@@ -56,9 +54,9 @@ public class RSCConf extends ClientConf<RSCConf> {
     LAUNCHER_PORT("launcher.port", -1),
 
     // How long will the RSC wait for a connection for a Livy server before 
shutting itself down.
-    SERVER_IDLE_TIMEOUT("server.idle_timeout", "10m"),
+    SERVER_IDLE_TIMEOUT("server.idle-timeout", "10m"),
 
-    PROXY_USER("proxy_user", null),
+    PROXY_USER("proxy-user", null),
 
     RPC_SERVER_ADDRESS("rpc.server.address", null),
     RPC_CLIENT_HANDSHAKE_TIMEOUT("server.connect.timeout", "90s"),
@@ -71,19 +69,19 @@ public class RSCConf extends ClientConf<RSCConf> {
     SASL_MECHANISMS("rpc.sasl.mechanisms", "DIGEST-MD5"),
     SASL_QOP("rpc.sasl.qop", null),
 
-    TEST_STUCK_END_SESSION("test.do_not_use.stuck_end_session", false),
-    TEST_STUCK_START_DRIVER("test.do_not_use.stuck_start_driver", false),
+    TEST_STUCK_END_SESSION("test.do-not-use.stuck-end-session", false),
+    TEST_STUCK_START_DRIVER("test.do-not-use.stuck-start-driver", false),
 
-    JOB_CANCEL_TRIGGER_INTERVAL("job_cancel.trigger_interval", "100ms"),
-    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "30s"),
+    JOB_CANCEL_TRIGGER_INTERVAL("job-cancel.trigger-interval", "100ms"),
+    JOB_CANCEL_TIMEOUT("job-cancel.timeout", "30s"),
 
-    RETAINED_STATEMENT_NUMBER("retained_statements", 100);
+    RETAINED_STATEMENT_NUMBER("retained-statements", 100);
 
     private final String key;
     private final Object dflt;
 
     private Entry(String key, Object dflt) {
-      this.key = "livy.rsc." + key;
+      this.key = RSC_CONF_PREFIX + key;
       this.dflt = dflt;
     }
 
@@ -146,4 +144,67 @@ public class RSCConf extends ClientConf<RSCConf> {
     return address.getCanonicalHostName();
   }
 
+  private static final Map<String, DeprecatedConf> configsWithAlternatives
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(RSCConf.Entry.CLIENT_IN_PROCESS.key, DepConf.CLIENT_IN_PROCESS);
+      put(RSCConf.Entry.CLIENT_SHUTDOWN_TIMEOUT.key, 
DepConf.CLIENT_SHUTDOWN_TIMEOUT);
+      put(RSCConf.Entry.DRIVER_CLASS.key, DepConf.DRIVER_CLASS);
+      put(RSCConf.Entry.SERVER_IDLE_TIMEOUT.key, DepConf.SERVER_IDLE_TIMEOUT);
+      put(RSCConf.Entry.PROXY_USER.key, DepConf.PROXY_USER);
+      put(RSCConf.Entry.TEST_STUCK_END_SESSION.key, 
DepConf.TEST_STUCK_END_SESSION);
+      put(RSCConf.Entry.TEST_STUCK_START_DRIVER.key, 
DepConf.TEST_STUCK_START_DRIVER);
+      put(RSCConf.Entry.JOB_CANCEL_TRIGGER_INTERVAL.key, 
DepConf.JOB_CANCEL_TRIGGER_INTERVAL);
+      put(RSCConf.Entry.JOB_CANCEL_TIMEOUT.key, DepConf.JOB_CANCEL_TIMEOUT);
+      put(RSCConf.Entry.RETAINED_STATEMENT_NUMBER.key, 
DepConf.RETAINED_STATEMENT_NUMBER);
+  }});
+
+  // Maps deprecated key to DeprecatedConf with the same key.
+  // There are no deprecated configs without alternatives currently.
+  private static final Map<String, DeprecatedConf> deprecatedConfigs
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>());
+
+  protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+    return configsWithAlternatives;
+  }
+
+  protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+    return deprecatedConfigs;
+  }
+
+  static enum DepConf implements DeprecatedConf {
+    CLIENT_IN_PROCESS("client.do_not_use.run_driver_in_process", "0.4"),
+    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown_timeout", "0.4"),
+    DRIVER_CLASS("driver_class", "0.4"),
+    SERVER_IDLE_TIMEOUT("server.idle_timeout", "0.4"),
+    PROXY_USER("proxy_user", "0.4"),
+    TEST_STUCK_END_SESSION("test.do_not_use.stuck_end_session", "0.4"),
+    TEST_STUCK_START_DRIVER("test.do_not_use.stuck_start_driver", "0.4"),
+    JOB_CANCEL_TRIGGER_INTERVAL("job_cancel.trigger_interval", "0.4"),
+    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "0.4"),
+    RETAINED_STATEMENT_NUMBER("retained_statements", "0.4");
+
+    private final String key;
+    private final String version;
+    private final String deprecationMessage;
+
+    private DepConf(String key, String version) {
+      this(key, version, "");
+    }
+
+    private DepConf(String key, String version, String deprecationMessage) {
+      this.key = RSC_CONF_PREFIX + key;
+      this.version = version;
+      this.deprecationMessage = deprecationMessage;
+    }
+
+    @Override
+    public String key() { return key; }
+
+    @Override
+    public String version() { return version; }
+
+    @Override
+    public String deprecationMessage() { return deprecationMessage; }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala 
b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index 1db1b8f..8fc4777 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -20,11 +20,15 @@ package com.cloudera.livy
 
 import java.io.File
 import java.lang.{Boolean => JBoolean, Long => JLong}
+import java.util.{Map => JMap}
+
+import scala.collection.JavaConverters._
 
 import org.apache.hadoop.conf.Configuration
 
 import com.cloudera.livy.client.common.ClientConf
 import com.cloudera.livy.client.common.ClientConf.ConfEntry
+import com.cloudera.livy.client.common.ClientConf.DeprecatedConf
 
 object LivyConf {
 
@@ -40,31 +44,31 @@ object LivyConf {
 
   val SPARK_HOME = Entry("livy.server.spark-home", null)
   val LIVY_SPARK_MASTER = Entry("livy.spark.master", "local")
-  val LIVY_SPARK_DEPLOY_MODE = Entry("livy.spark.deployMode", null)
+  val LIVY_SPARK_DEPLOY_MODE = Entry("livy.spark.deploy-mode", null)
 
   // Two configurations to specify Spark and related Scala version. These are 
internal
   // configurations will be set by LivyServer and used in session creation. It 
is not required to
   // set usually unless running with unofficial Spark + Scala versions
   // (like Spark 2.0 + Scala 2.10, Spark 1.6 + Scala 2.11)
-  val LIVY_SPARK_SCALA_VERSION = Entry("livy.spark.scalaVersion", null)
+  val LIVY_SPARK_SCALA_VERSION = Entry("livy.spark.scala-version", null)
   val LIVY_SPARK_VERSION = Entry("livy.spark.version", null)
 
   val SESSION_STAGING_DIR = Entry("livy.session.staging-dir", null)
   val FILE_UPLOAD_MAX_SIZE = Entry("livy.file.upload.max.size", 100L * 1024 * 
1024)
   val LOCAL_FS_WHITELIST = Entry("livy.file.local-dir-whitelist", null)
-  val ENABLE_HIVE_CONTEXT = Entry("livy.repl.enableHiveContext", false)
+  val ENABLE_HIVE_CONTEXT = Entry("livy.repl.enable-hive-context", false)
 
   val ENVIRONMENT = Entry("livy.environment", "production")
 
   val SERVER_HOST = Entry("livy.server.host", "0.0.0.0")
   val SERVER_PORT = Entry("livy.server.port", 8998)
-  val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf_protection.enabled", 
false)
+  val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf-protection.enabled", 
false)
 
   val IMPERSONATION_ENABLED = Entry("livy.impersonation.enabled", false)
   val SUPERUSERS = Entry("livy.superusers", null)
 
-  val ACCESS_CONTROL_ENABLED = Entry("livy.server.access_control.enabled", 
false)
-  val ACCESS_CONTROL_USERS = Entry("livy.server.access_control.users", null)
+  val ACCESS_CONTROL_ENABLED = Entry("livy.server.access-control.enabled", 
false)
+  val ACCESS_CONTROL_USERS = Entry("livy.server.access-control.users", null)
 
   val SSL_KEYSTORE = Entry("livy.keystore", null)
   val SSL_KEYSTORE_PASSWORD = Entry("livy.keystore.password", null)
@@ -73,7 +77,7 @@ object LivyConf {
   val AUTH_TYPE = Entry("livy.server.auth.type", null)
   val AUTH_KERBEROS_PRINCIPAL = Entry("livy.server.auth.kerberos.principal", 
null)
   val AUTH_KERBEROS_KEYTAB = Entry("livy.server.auth.kerberos.keytab", null)
-  val AUTH_KERBEROS_NAME_RULES = Entry("livy.server.auth.kerberos.name_rules", 
"DEFAULT")
+  val AUTH_KERBEROS_NAME_RULES = Entry("livy.server.auth.kerberos.name-rules", 
"DEFAULT")
 
   val HEARTBEAT_WATCHDOG_INTERVAL = 
Entry("livy.server.heartbeat-watchdog.interval", "1m")
 
@@ -82,9 +86,9 @@ object LivyConf {
   val LAUNCH_KERBEROS_KEYTAB =
     LivyConf.Entry("livy.server.launch.kerberos.keytab", null)
   val LAUNCH_KERBEROS_REFRESH_INTERVAL =
-    LivyConf.Entry("livy.server.launch.kerberos.refresh_interval", "1h")
+    LivyConf.Entry("livy.server.launch.kerberos.refresh-interval", "1h")
   val KINIT_FAIL_THRESHOLD =
-    LivyConf.Entry("livy.server.launch.kerberos.kinit_fail_threshold", 5)
+    LivyConf.Entry("livy.server.launch.kerberos.kinit-fail-threshold", 5)
 
   /**
    * Recovery mode of Livy. Possible values:
@@ -124,9 +128,9 @@ object LivyConf {
   val RSC_JARS = Entry("livy.rsc.jars", null)
 
   // How long to check livy session leakage
-  val YARN_APP_LEAKAGE_CHECK_TIMEOUT = 
Entry("livy.server.yarn.app-leakage.check_timeout", "600s")
+  val YARN_APP_LEAKAGE_CHECK_TIMEOUT = 
Entry("livy.server.yarn.app-leakage.check-timeout", "600s")
   // how often to check livy session leakage
-  val YARN_APP_LEAKAGE_CHECK_INTERVAL = 
Entry("livy.server.yarn.app-leakage.check_interval", "60s")
+  val YARN_APP_LEAKAGE_CHECK_INTERVAL = 
Entry("livy.server.yarn.app-leakage.check-interval", "60s")
 
   // Whether session timeout should be checked, by default it will be checked, 
which means inactive
   // session will be stopped after "livy.server.session.timeout"
@@ -166,6 +170,37 @@ object LivyConf {
     "spark.yarn.jars"
   )
 
+  case class DepConf(
+      override val key: String,
+      override val version: String,
+      override val deprecationMessage: String = "")
+    extends DeprecatedConf
+
+  private val configsWithAlternatives: Map[String, DeprecatedConf] = 
Map[String, DepConf](
+    LIVY_SPARK_DEPLOY_MODE.key -> DepConf("livy.spark.deployMode", "0.4"),
+    LIVY_SPARK_SCALA_VERSION.key -> DepConf("livy.spark.scalaVersion", "0.4"),
+    ENABLE_HIVE_CONTEXT.key -> DepConf("livy.repl.enableHiveContext", "0.4"),
+    CSRF_PROTECTION.key -> DepConf("livy.server.csrf_protection.enabled", 
"0.4"),
+    ACCESS_CONTROL_ENABLED.key -> 
DepConf("livy.server.access_control.enabled", "0.4"),
+    ACCESS_CONTROL_USERS.key -> DepConf("livy.server.access_control.users", 
"0.4"),
+    AUTH_KERBEROS_NAME_RULES.key -> 
DepConf("livy.server.auth.kerberos.name_rules", "0.4"),
+    LAUNCH_KERBEROS_REFRESH_INTERVAL.key ->
+      DepConf("livy.server.launch.kerberos.refresh_interval", "0.4"),
+    KINIT_FAIL_THRESHOLD.key -> 
DepConf("livy.server.launch.kerberos.kinit_fail_threshold", "0.4"),
+    YARN_APP_LEAKAGE_CHECK_TIMEOUT.key ->
+      DepConf("livy.server.yarn.app-leakage.check_timeout", "0.4"),
+    YARN_APP_LEAKAGE_CHECK_INTERVAL.key ->
+      DepConf("livy.server.yarn.app-leakage.check_interval", "0.4")
+  )
+
+  private val deprecatedConfigs: Map[String, DeprecatedConf] = {
+    val configs: Seq[DepConf] = Seq(
+      // There are no deprecated configs without alternatives currently.
+    )
+
+    Map(configs.map { cfg => (cfg.key -> cfg) }: _*)
+  }
+
 }
 
 /**
@@ -250,4 +285,12 @@ class LivyConf(loadDefaults: Boolean) extends 
ClientConf[LivyConf](null) {
     Option(get(entry)).map(_.split("[, ]+").toSeq).getOrElse(Nil)
   }
 
+  override def getConfigsWithAlternatives: JMap[String, DeprecatedConf] = {
+    configsWithAlternatives.asJava
+  }
+
+  override def getDeprecatedConfigs: JMap[String, DeprecatedConf] = {
+    deprecatedConfigs.asJava
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala 
b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index 0499d48..4bd5635 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -232,7 +232,7 @@ class LivyServer extends Logging {
     })
 
     _serverUrl = Some(s"${server.protocol}://${server.host}:${server.port}")
-    sys.props("livy.server.serverUrl") = _serverUrl.get
+    sys.props("livy.server.server-url") = _serverUrl.get
   }
 
   def runKinit(keytab: String, principal: String): Boolean = {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
----------------------------------------------------------------------
diff --git 
a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
 
b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
index 605edc6..b53dea7 100644
--- 
a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
+++ 
b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
@@ -100,7 +100,7 @@ object InteractiveSession extends Logging {
       info(s"Creating LivyClient for sessionId: $id")
       val builder = new LivyClientBuilder()
         .setAll(builderProperties.asJava)
-        .setConf("livy.client.sessionId", id.toString)
+        .setConf("livy.client.session-id", id.toString)
         .setConf(RSCConf.Entry.DRIVER_CLASS.key(), 
"com.cloudera.livy.repl.ReplDriver")
         .setConf(RSCConf.Entry.PROXY_USER.key(), proxyUser.orNull)
         .setURI(new URI("rsc:/"))

Reply via email to