You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by va...@apache.org on 2016/11/20 00:05:10 UTC
spark git commit: [SPARK-17062][MESOS] add conf option to mesos
dispatcher
Repository: spark
Updated Branches:
refs/heads/master ded5fefb6 -> ea77c81ec
[SPARK-17062][MESOS] add conf option to mesos dispatcher
Adds --conf option to set spark configuration properties in mesos dispacther.
Properties provided with --conf take precedence over properties within the properties file.
The reason for this PR is that for simple configuration or testing purposes we need to provide a property file (ideally a shared one for a cluster) even if we just provide a single property.
Manually tested.
Author: Stavros Kontopoulos <st...@gmail.com>
Author: Stavros Kontopoulos <st...@lightbend.com>
Closes #14650 from skonto/dipatcher_conf.
Project: http://git-wip-us.apache.org/repos/asf/spark/repo
Commit: http://git-wip-us.apache.org/repos/asf/spark/commit/ea77c81e
Tree: http://git-wip-us.apache.org/repos/asf/spark/tree/ea77c81e
Diff: http://git-wip-us.apache.org/repos/asf/spark/diff/ea77c81e
Branch: refs/heads/master
Commit: ea77c81ec0db27ea4709f71dc080d00167505a7d
Parents: ded5fef
Author: Stavros Kontopoulos <st...@gmail.com>
Authored: Sat Nov 19 16:02:59 2016 -0800
Committer: Marcelo Vanzin <va...@cloudera.com>
Committed: Sat Nov 19 16:04:49 2016 -0800
----------------------------------------------------------------------
.../org/apache/spark/deploy/SparkSubmit.scala | 18 ++---
.../spark/deploy/SparkSubmitArguments.scala | 6 +-
.../apache/spark/util/CommandLineUtils.scala | 56 ++++++++++++++++
.../scala/org/apache/spark/util/Utils.scala | 14 ++++
.../apache/spark/deploy/SparkSubmitSuite.scala | 43 +++++++-----
.../deploy/mesos/MesosClusterDispatcher.scala | 9 ++-
.../mesos/MesosClusterDispatcherArguments.scala | 70 +++++++++++++++-----
.../MesosClusterDispatcherArgumentsSuite.scala | 63 ++++++++++++++++++
.../mesos/MesosClusterDispatcherSuite.scala | 40 +++++++++++
9 files changed, 266 insertions(+), 53 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala
----------------------------------------------------------------------
diff --git a/core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala b/core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala
index c70061b..85f80b6 100644
--- a/core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/SparkSubmit.scala
@@ -41,12 +41,11 @@ import org.apache.ivy.plugins.matcher.GlobPatternMatcher
import org.apache.ivy.plugins.repository.file.FileRepository
import org.apache.ivy.plugins.resolver.{ChainResolver, FileSystemResolver, IBiblioResolver}
-import org.apache.spark.{SPARK_REVISION, SPARK_VERSION, SparkException, SparkUserAppException}
-import org.apache.spark.{SPARK_BRANCH, SPARK_BUILD_DATE, SPARK_BUILD_USER, SPARK_REPO_URL}
+import org.apache.spark._
import org.apache.spark.api.r.RUtils
import org.apache.spark.deploy.rest._
import org.apache.spark.launcher.SparkLauncher
-import org.apache.spark.util.{ChildFirstURLClassLoader, MutableURLClassLoader, Utils}
+import org.apache.spark.util._
/**
* Whether to submit, kill, or request the status of an application.
@@ -63,7 +62,7 @@ private[deploy] object SparkSubmitAction extends Enumeration {
* This program handles setting up the classpath with relevant Spark dependencies and provides
* a layer over the different cluster managers and deploy modes that Spark supports.
*/
-object SparkSubmit {
+object SparkSubmit extends CommandLineUtils {
// Cluster managers
private val YARN = 1
@@ -87,15 +86,6 @@ object SparkSubmit {
private val CLASS_NOT_FOUND_EXIT_STATUS = 101
// scalastyle:off println
- // Exposed for testing
- private[spark] var exitFn: Int => Unit = (exitCode: Int) => System.exit(exitCode)
- private[spark] var printStream: PrintStream = System.err
- private[spark] def printWarning(str: String): Unit = printStream.println("Warning: " + str)
- private[spark] def printErrorAndExit(str: String): Unit = {
- printStream.println("Error: " + str)
- printStream.println("Run with --help for usage help or --verbose for debug output")
- exitFn(1)
- }
private[spark] def printVersionAndExit(): Unit = {
printStream.println("""Welcome to
____ __
@@ -115,7 +105,7 @@ object SparkSubmit {
}
// scalastyle:on println
- def main(args: Array[String]): Unit = {
+ override def main(args: Array[String]): Unit = {
val appArgs = new SparkSubmitArguments(args)
if (appArgs.verbose) {
// scalastyle:off println
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala
----------------------------------------------------------------------
diff --git a/core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala b/core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala
index f1761e7..b1d36e1 100644
--- a/core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/SparkSubmitArguments.scala
@@ -412,10 +412,8 @@ private[deploy] class SparkSubmitArguments(args: Seq[String], env: Map[String, S
repositories = value
case CONF =>
- value.split("=", 2).toSeq match {
- case Seq(k, v) => sparkProperties(k) = v
- case _ => SparkSubmit.printErrorAndExit(s"Spark config without '=': $value")
- }
+ val (confName, confValue) = SparkSubmit.parseSparkConfProperty(value)
+ sparkProperties(confName) = confValue
case PROXY_USER =>
proxyUser = value
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/core/src/main/scala/org/apache/spark/util/CommandLineUtils.scala
----------------------------------------------------------------------
diff --git a/core/src/main/scala/org/apache/spark/util/CommandLineUtils.scala b/core/src/main/scala/org/apache/spark/util/CommandLineUtils.scala
new file mode 100644
index 0000000..d739016
--- /dev/null
+++ b/core/src/main/scala/org/apache/spark/util/CommandLineUtils.scala
@@ -0,0 +1,56 @@
+/*
+ * 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.spark.util
+
+import java.io.PrintStream
+
+import org.apache.spark.SparkException
+
+/**
+ * Contains basic command line parsing functionality and methods to parse some common Spark CLI
+ * options.
+ */
+private[spark] trait CommandLineUtils {
+
+ // Exposed for testing
+ private[spark] var exitFn: Int => Unit = (exitCode: Int) => System.exit(exitCode)
+
+ private[spark] var printStream: PrintStream = System.err
+
+ // scalastyle:off println
+
+ private[spark] def printWarning(str: String): Unit = printStream.println("Warning: " + str)
+
+ private[spark] def printErrorAndExit(str: String): Unit = {
+ printStream.println("Error: " + str)
+ printStream.println("Run with --help for usage help or --verbose for debug output")
+ exitFn(1)
+ }
+
+ // scalastyle:on println
+
+ private[spark] def parseSparkConfProperty(pair: String): (String, String) = {
+ pair.split("=", 2).toSeq match {
+ case Seq(k, v) => (k, v)
+ case _ => printErrorAndExit(s"Spark config without '=': $pair")
+ throw new SparkException(s"Spark config without '=': $pair")
+ }
+ }
+
+ def main(args: Array[String]): Unit
+}
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/core/src/main/scala/org/apache/spark/util/Utils.scala
----------------------------------------------------------------------
diff --git a/core/src/main/scala/org/apache/spark/util/Utils.scala b/core/src/main/scala/org/apache/spark/util/Utils.scala
index 23b95b9..748d729 100644
--- a/core/src/main/scala/org/apache/spark/util/Utils.scala
+++ b/core/src/main/scala/org/apache/spark/util/Utils.scala
@@ -2056,6 +2056,20 @@ private[spark] object Utils extends Logging {
path
}
+ /**
+ * Updates Spark config with properties from a set of Properties.
+ * Provided properties have the highest priority.
+ */
+ def updateSparkConfigFromProperties(
+ conf: SparkConf,
+ properties: Map[String, String]) : Unit = {
+ properties.filter { case (k, v) =>
+ k.startsWith("spark.")
+ }.foreach { case (k, v) =>
+ conf.set(k, v)
+ }
+ }
+
/** Load properties present in the given file. */
def getPropertiesFromFile(filename: String): Map[String, String] = {
val file = new File(filename)
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/core/src/test/scala/org/apache/spark/deploy/SparkSubmitSuite.scala
----------------------------------------------------------------------
diff --git a/core/src/test/scala/org/apache/spark/deploy/SparkSubmitSuite.scala b/core/src/test/scala/org/apache/spark/deploy/SparkSubmitSuite.scala
index 7c649e3..6268880 100644
--- a/core/src/test/scala/org/apache/spark/deploy/SparkSubmitSuite.scala
+++ b/core/src/test/scala/org/apache/spark/deploy/SparkSubmitSuite.scala
@@ -34,21 +34,11 @@ import org.apache.spark.deploy.SparkSubmitUtils.MavenCoordinate
import org.apache.spark.internal.config._
import org.apache.spark.internal.Logging
import org.apache.spark.TestUtils.JavaSourceFromString
-import org.apache.spark.util.{ResetSystemProperties, Utils}
+import org.apache.spark.util.{CommandLineUtils, ResetSystemProperties, Utils}
-// Note: this suite mixes in ResetSystemProperties because SparkSubmit.main() sets a bunch
-// of properties that needed to be cleared after tests.
-class SparkSubmitSuite
- extends SparkFunSuite
- with Matchers
- with BeforeAndAfterEach
- with ResetSystemProperties
- with Timeouts {
- override def beforeEach() {
- super.beforeEach()
- System.setProperty("spark.testing", "true")
- }
+trait TestPrematureExit {
+ suite: SparkFunSuite =>
private val noOpOutputStream = new OutputStream {
def write(b: Int) = {}
@@ -65,16 +55,19 @@ class SparkSubmitSuite
}
/** Returns true if the script exits and the given search string is printed. */
- private def testPrematureExit(input: Array[String], searchString: String) = {
+ private[spark] def testPrematureExit(
+ input: Array[String],
+ searchString: String,
+ mainObject: CommandLineUtils = SparkSubmit) : Unit = {
val printStream = new BufferPrintStream()
- SparkSubmit.printStream = printStream
+ mainObject.printStream = printStream
@volatile var exitedCleanly = false
- SparkSubmit.exitFn = (_) => exitedCleanly = true
+ mainObject.exitFn = (_) => exitedCleanly = true
val thread = new Thread {
override def run() = try {
- SparkSubmit.main(input)
+ mainObject.main(input)
} catch {
// If exceptions occur after the "exit" has happened, fine to ignore them.
// These represent code paths not reachable during normal execution.
@@ -88,6 +81,22 @@ class SparkSubmitSuite
fail(s"Search string '$searchString' not found in $joined")
}
}
+}
+
+// Note: this suite mixes in ResetSystemProperties because SparkSubmit.main() sets a bunch
+// of properties that needed to be cleared after tests.
+class SparkSubmitSuite
+ extends SparkFunSuite
+ with Matchers
+ with BeforeAndAfterEach
+ with ResetSystemProperties
+ with Timeouts
+ with TestPrematureExit {
+
+ override def beforeEach() {
+ super.beforeEach()
+ System.setProperty("spark.testing", "true")
+ }
// scalastyle:off println
test("prints usage on empty input") {
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcher.scala
----------------------------------------------------------------------
diff --git a/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcher.scala b/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcher.scala
index 7d6693b..792ade8 100644
--- a/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcher.scala
+++ b/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcher.scala
@@ -25,7 +25,7 @@ import org.apache.spark.deploy.mesos.ui.MesosClusterUI
import org.apache.spark.deploy.rest.mesos.MesosRestServer
import org.apache.spark.internal.Logging
import org.apache.spark.scheduler.cluster.mesos._
-import org.apache.spark.util.{ShutdownHookManager, Utils}
+import org.apache.spark.util.{CommandLineUtils, ShutdownHookManager, Utils}
/*
* A dispatcher that is responsible for managing and launching drivers, and is intended to be
@@ -92,8 +92,11 @@ private[mesos] class MesosClusterDispatcher(
}
}
-private[mesos] object MesosClusterDispatcher extends Logging {
- def main(args: Array[String]) {
+private[mesos] object MesosClusterDispatcher
+ extends Logging
+ with CommandLineUtils {
+
+ override def main(args: Array[String]) {
Utils.initDaemon(log)
val conf = new SparkConf
val dispatcherArgs = new MesosClusterDispatcherArguments(args, conf)
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArguments.scala
----------------------------------------------------------------------
diff --git a/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArguments.scala b/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArguments.scala
index 11e1344..ef08502 100644
--- a/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArguments.scala
+++ b/mesos/src/main/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArguments.scala
@@ -18,23 +18,43 @@
package org.apache.spark.deploy.mesos
import scala.annotation.tailrec
+import scala.collection.mutable
-import org.apache.spark.SparkConf
import org.apache.spark.util.{IntParam, Utils}
-
+import org.apache.spark.SparkConf
private[mesos] class MesosClusterDispatcherArguments(args: Array[String], conf: SparkConf) {
- var host = Utils.localHostName()
- var port = 7077
- var name = "Spark Cluster"
- var webUiPort = 8081
+ var host: String = Utils.localHostName()
+ var port: Int = 7077
+ var name: String = "Spark Cluster"
+ var webUiPort: Int = 8081
+ var verbose: Boolean = false
var masterUrl: String = _
var zookeeperUrl: Option[String] = None
var propertiesFile: String = _
+ val confProperties: mutable.HashMap[String, String] =
+ new mutable.HashMap[String, String]()
parse(args.toList)
+ // scalastyle:on println
propertiesFile = Utils.loadDefaultSparkProperties(conf, propertiesFile)
+ Utils.updateSparkConfigFromProperties(conf, confProperties)
+
+ // scalastyle:off println
+ if (verbose) {
+ MesosClusterDispatcher.printStream.println(s"Using host: $host")
+ MesosClusterDispatcher.printStream.println(s"Using port: $port")
+ MesosClusterDispatcher.printStream.println(s"Using webUiPort: $webUiPort")
+ MesosClusterDispatcher.printStream.println(s"Framework Name: $name")
+
+ Option(propertiesFile).foreach { file =>
+ MesosClusterDispatcher.printStream.println(s"Using properties file: $file")
+ }
+
+ MesosClusterDispatcher.printStream.println(s"Spark Config properties set:")
+ conf.getAll.foreach(println)
+ }
@tailrec
private def parse(args: List[String]): Unit = args match {
@@ -58,9 +78,10 @@ private[mesos] class MesosClusterDispatcherArguments(args: Array[String], conf:
case ("--master" | "-m") :: value :: tail =>
if (!value.startsWith("mesos://")) {
// scalastyle:off println
- System.err.println("Cluster dispatcher only supports mesos (uri begins with mesos://)")
+ MesosClusterDispatcher.printStream
+ .println("Cluster dispatcher only supports mesos (uri begins with mesos://)")
// scalastyle:on println
- System.exit(1)
+ MesosClusterDispatcher.exitFn(1)
}
masterUrl = value.stripPrefix("mesos://")
parse(tail)
@@ -73,28 +94,45 @@ private[mesos] class MesosClusterDispatcherArguments(args: Array[String], conf:
propertiesFile = value
parse(tail)
+ case ("--conf") :: value :: tail =>
+ val pair = MesosClusterDispatcher.
+ parseSparkConfProperty(value)
+ confProperties(pair._1) = pair._2
+ parse(tail)
+
case ("--help") :: tail =>
- printUsageAndExit(0)
+ printUsageAndExit(0)
+
+ case ("--verbose") :: tail =>
+ verbose = true
+ parse(tail)
case Nil =>
- if (masterUrl == null) {
+ if (Option(masterUrl).isEmpty) {
// scalastyle:off println
- System.err.println("--master is required")
+ MesosClusterDispatcher.printStream.println("--master is required")
// scalastyle:on println
printUsageAndExit(1)
}
- case _ =>
+ case value =>
+ // scalastyle:off println
+ MesosClusterDispatcher.printStream.println(s"Unrecognized option: '${value.head}'")
+ // scalastyle:on println
printUsageAndExit(1)
}
private def printUsageAndExit(exitCode: Int): Unit = {
+ val outStream = MesosClusterDispatcher.printStream
+
// scalastyle:off println
- System.err.println(
+ outStream.println(
"Usage: MesosClusterDispatcher [options]\n" +
"\n" +
"Options:\n" +
" -h HOST, --host HOST Hostname to listen on\n" +
+ " --help Show this help message and exit.\n" +
+ " --verbose, Print additional debug output.\n" +
" -p PORT, --port PORT Port to listen on (default: 7077)\n" +
" --webui-port WEBUI_PORT WebUI Port to listen on (default: 8081)\n" +
" --name NAME Framework name to show in Mesos UI\n" +
@@ -102,8 +140,10 @@ private[mesos] class MesosClusterDispatcherArguments(args: Array[String], conf:
" -z --zk ZOOKEEPER Comma delimited URLs for connecting to \n" +
" Zookeeper for persistence\n" +
" --properties-file FILE Path to a custom Spark properties file.\n" +
- " Default is conf/spark-defaults.conf.")
+ " Default is conf/spark-defaults.conf \n" +
+ " --conf PROP=VALUE Arbitrary Spark configuration property.\n" +
+ " Takes precedence over defined properties in properties-file.")
// scalastyle:on println
- System.exit(exitCode)
+ MesosClusterDispatcher.exitFn(exitCode)
}
}
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArgumentsSuite.scala
----------------------------------------------------------------------
diff --git a/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArgumentsSuite.scala b/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArgumentsSuite.scala
new file mode 100644
index 0000000..b6c0b32
--- /dev/null
+++ b/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherArgumentsSuite.scala
@@ -0,0 +1,63 @@
+/*
+ * 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.spark.deploy.mesos
+
+import org.apache.spark.{SparkConf, SparkFunSuite}
+import org.apache.spark.deploy.TestPrematureExit
+
+class MesosClusterDispatcherArgumentsSuite extends SparkFunSuite
+ with TestPrematureExit {
+
+ test("test if spark config args are passed sucessfully") {
+ val args = Array[String]("--master", "mesos://localhost:5050", "--conf", "key1=value1",
+ "--conf", "spark.mesos.key2=value2", "--verbose")
+ val conf = new SparkConf()
+ new MesosClusterDispatcherArguments(args, conf)
+
+ assert(conf.getOption("key1").isEmpty)
+ assert(conf.get("spark.mesos.key2") == "value2")
+ }
+
+ test("test non conf settings") {
+ val masterUrl = "mesos://localhost:5050"
+ val port = "1212"
+ val zookeeperUrl = "zk://localhost:2181"
+ val host = "localhost"
+ val webUiPort = "2323"
+ val name = "myFramework"
+
+ val args1 = Array("--master", masterUrl, "--verbose", "--name", name)
+ val args2 = Array("-p", port, "-h", host, "-z", zookeeperUrl)
+ val args3 = Array("--webui-port", webUiPort)
+
+ val args = args1 ++ args2 ++ args3
+ val conf = new SparkConf()
+ val mesosDispClusterArgs = new MesosClusterDispatcherArguments(args, conf)
+
+ assert(mesosDispClusterArgs.verbose)
+ assert(mesosDispClusterArgs.confProperties.isEmpty)
+ assert(mesosDispClusterArgs.host == host)
+ assert(Option(mesosDispClusterArgs.masterUrl).isDefined)
+ assert(mesosDispClusterArgs.masterUrl == masterUrl.stripPrefix("mesos://"))
+ assert(Option(mesosDispClusterArgs.zookeeperUrl).isDefined)
+ assert(mesosDispClusterArgs.zookeeperUrl contains zookeeperUrl)
+ assert(mesosDispClusterArgs.name == name)
+ assert(mesosDispClusterArgs.webUiPort == webUiPort.toInt)
+ assert(mesosDispClusterArgs.port == port.toInt)
+ }
+}
http://git-wip-us.apache.org/repos/asf/spark/blob/ea77c81e/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherSuite.scala
----------------------------------------------------------------------
diff --git a/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherSuite.scala b/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherSuite.scala
new file mode 100644
index 0000000..7484e3b
--- /dev/null
+++ b/mesos/src/test/scala/org/apache/spark/deploy/mesos/MesosClusterDispatcherSuite.scala
@@ -0,0 +1,40 @@
+/*
+ * 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.spark.deploy.mesos
+
+import org.apache.spark.SparkFunSuite
+import org.apache.spark.deploy.TestPrematureExit
+
+class MesosClusterDispatcherSuite extends SparkFunSuite
+ with TestPrematureExit{
+
+ test("prints usage on empty input") {
+ testPrematureExit(Array[String](),
+ "Usage: MesosClusterDispatcher", MesosClusterDispatcher)
+ }
+
+ test("prints usage with only --help") {
+ testPrematureExit(Array("--help"),
+ "Usage: MesosClusterDispatcher", MesosClusterDispatcher)
+ }
+
+ test("prints error with unrecognized options") {
+ testPrematureExit(Array("--blarg"), "Unrecognized option: '--blarg'", MesosClusterDispatcher)
+ testPrematureExit(Array("-bleg"), "Unrecognized option: '-bleg'", MesosClusterDispatcher)
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org