From 361d91a57835c55110719d9fd15f89442bd3dab1 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Mon, 23 Mar 2015 23:26:46 +0100 Subject: [PATCH] + improves conductr url setting from the console, and smater default Resolves #44 #46 --- README.md | 2 +- .../conductr/sbt/SbtTypesafeConductR.scala | 34 +++++++++++++-- .../client/ConductRControllerSpec.scala | 4 +- .../sbt/SbtTypesafeConductRSpec.scala | 42 +++++++++++++++++++ 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src/test/scala/com/typesafe/conductr/sbt/SbtTypesafeConductRSpec.scala diff --git a/README.md b/README.md index 417d7ae..6a2a9c2 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ The following `sbt-typesafe-conductr` commands are available: Property | Description -------------|------------ -conductr | Sets the ConductR's address to a provided url (the default here is http://127.0.0.1:9005) +conductr | Sets the ConductR's address to a provided url (defaults to env varialbe `CONDUCTR_IP:[CONDUCTR_PORT]` if set, otherwise uses the default: `http://127.0.0.1:9005`) loadBundle | Loads a bundle and an optional configuration to the ConductR startBundle | Starts a bundle given a bundle id with an optional absolute scale value stopBundle | Stops all executions of a bundle given a bundle id diff --git a/src/main/scala/com/typesafe/conductr/sbt/SbtTypesafeConductR.scala b/src/main/scala/com/typesafe/conductr/sbt/SbtTypesafeConductR.scala index dc073eb..cf51606 100644 --- a/src/main/scala/com/typesafe/conductr/sbt/SbtTypesafeConductR.scala +++ b/src/main/scala/com/typesafe/conductr/sbt/SbtTypesafeConductR.scala @@ -35,7 +35,7 @@ object Import { object ConductRKeys { val discoveredDist = TaskKey[File]("conductr-discovered-dist", "Any distribution produced by the current project") - val conductrUrl = SettingKey[URL]("conductr-url", "The URL of the ConductR. Defaults to 'http://127.0.0.1:9005'") + val conductrUrl = SettingKey[URL]("conductr-url", "The URL of the ConductR. Defaults to the env variables 'CONDUCTR_IP:[CONDUCTR_PORT]', otherwise uses the default: 'http://127.0.0.1:9005'") val conductrConnectTimeout = SettingKey[Timeout]("conductr-connect-timeout", "The timeout for ConductR communications when connecting") val conductrLoadTimeout = SettingKey[Timeout]("conductr-load-timeout", "The timeout for ConductR communications when loading") val conductrRequestTimeout = SettingKey[Timeout]("conductr-request-timeout", "The timeout for ConductR communications when requesting") @@ -54,6 +54,10 @@ object SbtTypesafeConductR extends AutoPlugin { val autoImport = Import + val DefaultConductrProtocol = "http" + val DefaultConductrHost = "127.0.0.1" + val DefaultConductrPort = 9005 + override def `requires`: Plugins = plugins.CorePlugin @@ -61,7 +65,7 @@ object SbtTypesafeConductR extends AutoPlugin { super.globalSettings ++ List( onLoad := onLoad.value.andThen(loadActorSystem).andThen(loadConductRController), onUnload := (unloadConductRController _).andThen(unloadActorSystem).andThen(onUnload.value), - conductrUrl := new URL(s"http://127.0.0.1:9005"), + conductrUrl := envConductrUrl getOrElse new URL(s"$DefaultConductrProtocol://$DefaultConductrHost:$DefaultConductrPort"), conductrConnectTimeout := 30.seconds ) @@ -106,8 +110,25 @@ object SbtTypesafeConductR extends AutoPlugin { } private def conductr: Command = Command.single("conductr") { (prevState, url) => + require(url != null && url.nonEmpty, "ConductR URL must NOT be empty!") val extracted = Project.extract(prevState) - extracted.append(Seq(conductrUrl in Global := new URL(url)), prevState) + val furl = prepareUrl(url) + extracted.append(Seq(conductrUrl in Global := furl), prevState) + } + + private def prepareUrl(url: String): sbt.URL = { + def insertPort(url: String, port: Int): String = + url.indexOf("/", "http://".length) match { + case -1 => s"""$url:$port""" + case firstPathSlash => s"""${url.substring(0, firstPathSlash)}:$port${url.substring(firstPathSlash)}""" + } + val surl = if (url.contains("://")) url else s"$DefaultConductrProtocol://$url" + val nurl = new sbt.URL(surl) + + nurl.getPort match { + case -1 => new sbt.URL(insertPort(surl, DefaultConductrPort)) + case _ => nurl + } } private def loadBundleTask: Def.Initialize[InputTask[String]] = @@ -217,6 +238,13 @@ object SbtTypesafeConductR extends AutoPlugin { } } + private def envConductrUrl(): Option[URL] = { + val ip = sys.env.get("CONDUCTR_IP") + val port = sys.env.getOrElse("CONDUCTR_PORT", 9005) + + ip.map(i => new URL(s"http://$i:$port")) + } + // Actor system management and API private val actorSystemAttrKey = AttributeKey[ActorSystem]("sbt-typesafe-conductr-actor-system") diff --git a/src/test/scala/com/typesafe/conductr/client/ConductRControllerSpec.scala b/src/test/scala/com/typesafe/conductr/client/ConductRControllerSpec.scala index 29a3f5e..c1ec1fc 100644 --- a/src/test/scala/com/typesafe/conductr/client/ConductRControllerSpec.scala +++ b/src/test/scala/com/typesafe/conductr/client/ConductRControllerSpec.scala @@ -9,14 +9,14 @@ import akka.http.Http import akka.http.model.{ HttpMethods, HttpRequest, HttpResponse, StatusCodes, Uri } import akka.stream.scaladsl.Flow import akka.testkit.{ TestActorRef, TestProbe } -import com.typesafe.conductr.TestBundle import org.scalatest.{ BeforeAndAfterAll, Matchers, PrivateMethodTester, WordSpec } + import scala.concurrent.Future import scala.concurrent.duration.DurationInt class ConductRControllerSpec extends WordSpec with Matchers with BeforeAndAfterAll with PrivateMethodTester { - import TestBundle._ + import com.typesafe.conductr.TestBundle._ // FIXME: Test required for GetBundleStream diff --git a/src/test/scala/com/typesafe/conductr/sbt/SbtTypesafeConductRSpec.scala b/src/test/scala/com/typesafe/conductr/sbt/SbtTypesafeConductRSpec.scala new file mode 100644 index 0000000..07f3859 --- /dev/null +++ b/src/test/scala/com/typesafe/conductr/sbt/SbtTypesafeConductRSpec.scala @@ -0,0 +1,42 @@ +/* + * Copyright © 2014 Typesafe, Inc. All rights reserved. + */ + +package com.typesafe.conductr.sbt + +import akka.actor.ActorSystem +import org.scalatest.{ BeforeAndAfterAll, Matchers, PrivateMethodTester, WordSpec } + +class SbtTypesafeConductRSpec extends WordSpec with Matchers with BeforeAndAfterAll with PrivateMethodTester { + + "Setting ConductR URL" should { + "be prepared to full format given partial input" in { + val inputToUrls = Map( + "192.1.1.28" -> "http://192.1.1.28:9005", + "http://192.1.1.28" -> "http://192.1.1.28:9005", + "http://192.1.1.28/my/example" -> "http://192.1.1.28:9005/my/example", + "http://192.1.1.28/my/example/" -> "http://192.1.1.28:9005/my/example/", + "http://192.1.1.28/example" -> "http://192.1.1.28:9005/example", + "http://192.1.1.28/example/" -> "http://192.1.1.28:9005/example/", + "http://192.1.1.28:9999" -> "http://192.1.1.28:9999", + "http://192.1.1.28:9999/example" -> "http://192.1.1.28:9999/example", + "192.1.1.28/example" -> "http://192.1.1.28:9005/example", + "192.1.1.28:9999/example" -> "http://192.1.1.28:9999/example" + ) + + val prepareUrl = PrivateMethod[sbt.URL]('prepareUrl) + inputToUrls foreach { + case (input, fullUrl) => SbtTypesafeConductR.invokePrivate(prepareUrl(input)).toString shouldBe fullUrl + } + } + } + + private implicit val system = + ActorSystem() + + override protected def afterAll(): Unit = { + system.shutdown() + system.awaitTermination() + } + +}