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

slange pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git


The following commit(s) were added to refs/heads/master by this push:
     new 19a1981  additional container factory dns configuration (#4176)
19a1981 is described below

commit 19a19810f35c503d1125fcff5fd7885aa199cd2b
Author: David Grove <[email protected]>
AuthorDate: Thu Jan 17 11:31:08 2019 -0500

    additional container factory dns configuration (#4176)
    
    Allow configuration of the --dns-search and --dns-opt (--dns-option)
    arguments to the docker run command of the DockerContainerFactory.
    Motivated by better support of event providers in Kubernetes when
    using the DockerContainerFactory.
---
 .../core/containerpool/ContainerFactory.scala      |  2 ++
 core/invoker/src/main/resources/application.conf   |  4 ++++
 .../core/containerpool/docker/DockerClient.scala   | 24 +++++++++++++++++++++-
 .../containerpool/docker/DockerContainer.scala     |  6 ++++++
 .../docker/DockerContainerFactory.scala            |  2 ++
 .../docker/test/DockerClientTests.scala            |  3 +++
 .../test/DockerClientWithFileAccessTests.scala     |  2 ++
 .../docker/test/DockerContainerFactoryTests.scala  |  6 +++++-
 .../docker/test/DockerContainerTests.scala         |  2 ++
 .../mesos/test/MesosContainerFactoryTest.scala     | 14 +++++++++++--
 .../test/ContainerArgsConfigTest.scala             | 10 +++++++++
 11 files changed, 71 insertions(+), 4 deletions(-)

diff --git 
a/common/scala/src/main/scala/org/apache/openwhisk/core/containerpool/ContainerFactory.scala
 
b/common/scala/src/main/scala/org/apache/openwhisk/core/containerpool/ContainerFactory.scala
index ce68010..ad78ce2 100644
--- 
a/common/scala/src/main/scala/org/apache/openwhisk/core/containerpool/ContainerFactory.scala
+++ 
b/common/scala/src/main/scala/org/apache/openwhisk/core/containerpool/ContainerFactory.scala
@@ -27,6 +27,8 @@ import scala.concurrent.Future
 
 case class ContainerArgsConfig(network: String,
                                dnsServers: Seq[String] = Seq.empty,
+                               dnsSearch: Seq[String] = Seq.empty,
+                               dnsOptions: Seq[String] = Seq.empty,
                                extraArgs: Map[String, Set[String]] = Map.empty)
 
 case class ContainerPoolConfig(userMemory: ByteSize, concurrentPeekFactor: 
Double, akkaClient: Boolean) {
diff --git a/core/invoker/src/main/resources/application.conf 
b/core/invoker/src/main/resources/application.conf
index 3efdf15..c1d4bf7 100644
--- a/core/invoker/src/main/resources/application.conf
+++ b/core/invoker/src/main/resources/application.conf
@@ -28,6 +28,7 @@ whisk {
       inspect: 1 minute
       pause: 10 seconds
       unpause: 10 seconds
+      version: 10 seconds
     }
   }
 
@@ -68,7 +69,10 @@ whisk {
   # args for 'docker run' to use
   container-factory.container-args {
     network: bridge
+    # See 
https://docs.docker.com/config/containers/container-networking/#dns-services 
for documentation of dns-*
     dns-servers: []
+    dns-search: []
+    dns-options: []
     extra-args: {}   # to pass additional args to 'docker run'; format is 
`{key1: [v1, v2], key2: [v1, v2]}`
   }
 
diff --git 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala
 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala
index 355c3ab..db42d93 100644
--- 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala
+++ 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerClient.scala
@@ -27,7 +27,7 @@ import akka.actor.ActorSystem
 import scala.collection.concurrent.TrieMap
 import scala.concurrent.blocking
 import scala.concurrent.ExecutionContext
-import scala.concurrent.Future
+import scala.concurrent.{Await, Future}
 import scala.util.Failure
 import scala.util.Success
 import scala.util.Try
@@ -61,6 +61,7 @@ case class DockerClientTimeoutConfig(run: Duration,
                                      ps: Duration,
                                      pause: Duration,
                                      unpause: Duration,
+                                     version: Duration,
                                      inspect: Duration)
 
 /**
@@ -98,6 +99,20 @@ class DockerClient(dockerHost: Option[String] = None,
     Seq(dockerBin) ++ host
   }
 
+  // Invoke docker CLI to determine client version.
+  // If the docker client version cannot be determined, an exception will be 
thrown and instance initialization will fail.
+  // Rationale: if we cannot invoke `docker version` successfully, it is 
unlikely subsequent `docker` invocations will succeed.
+  protected def getClientVersion(): String = {
+    val vf = executeProcess(dockerCmd ++ Seq("version", "--format", 
"{{.Client.Version}}"), config.timeouts.version)
+      .andThen {
+        case Success(version) => log.info(this, s"Detected docker client 
version $version")
+        case Failure(e) =>
+          log.error(this, s"Failed to determine docker client version: 
${e.getClass} - ${e.getMessage}")
+      }
+    Await.result(vf, 2 * config.timeouts.version)
+  }
+  val clientVersion: String = getClientVersion()
+
   protected val maxParallelRuns = config.parallelRuns
   protected val runSemaphore =
     new Semaphore( /* permits= */ if (maxParallelRuns > 0) maxParallelRuns 
else Int.MaxValue, /* fair= */ true)
@@ -198,6 +213,13 @@ class DockerClient(dockerHost: Option[String] = None,
 trait DockerApi {
 
   /**
+   * The version number of the docker client cli
+   *
+   * @return The version of the docker client cli being used by the invoker
+   */
+  def clientVersion: String
+
+  /**
    * Spawns a container in detached mode.
    *
    * @param image the image to start the container with
diff --git 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainer.scala
 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainer.scala
index b8b4057..7ac95e4 100644
--- 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainer.scala
+++ 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainer.scala
@@ -65,6 +65,8 @@ object DockerContainer {
              environment: Map[String, String] = Map.empty,
              network: String = "bridge",
              dnsServers: Seq[String] = Seq.empty,
+             dnsSearch: Seq[String] = Seq.empty,
+             dnsOptions: Seq[String] = Seq.empty,
              name: Option[String] = None,
              useRunc: Boolean = true,
              dockerRunParameters: Map[String, Set[String]])(implicit docker: 
DockerApiWithFileAccess,
@@ -82,6 +84,8 @@ object DockerContainer {
       case (key, valueList) => valueList.toList.flatMap(Seq(key, _))
     }
 
+    // NOTE: --dns-option on modern versions of docker, but is --dns-opt on 
docker 1.12
+    val dnsOptString = if (docker.clientVersion.startsWith("1.12")) { 
"--dns-opt" } else { "--dns-option" }
     val args = Seq(
       "--cpu-shares",
       cpuShares.toString,
@@ -93,6 +97,8 @@ object DockerContainer {
       network) ++
       environmentArgs ++
       dnsServers.flatMap(d => Seq("--dns", d)) ++
+      dnsSearch.flatMap(d => Seq("--dns-search", d)) ++
+      dnsOptions.flatMap(d => Seq(dnsOptString, d)) ++
       name.map(n => Seq("--name", n)).getOrElse(Seq.empty) ++
       params
 
diff --git 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainerFactory.scala
 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainerFactory.scala
index c4ceff3..0fad560 100644
--- 
a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainerFactory.scala
+++ 
b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/docker/DockerContainerFactory.scala
@@ -69,6 +69,8 @@ class DockerContainerFactory(instance: InvokerInstanceId,
       environment = Map("__OW_API_HOST" -> config.wskApiHost),
       network = containerArgsConfig.network,
       dnsServers = containerArgsConfig.dnsServers,
+      dnsSearch = containerArgsConfig.dnsSearch,
+      dnsOptions = containerArgsConfig.dnsOptions,
       name = Some(name),
       useRunc = dockerContainerFactoryConfig.useRunc,
       parameters ++ containerArgsConfig.extraArgs.map { case (k, v) => ("--" + 
k, v) })
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientTests.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientTests.scala
index 1633a02..7de2a35 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientTests.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientTests.scala
@@ -67,6 +67,7 @@ class DockerClientTests
   /** Returns a DockerClient with a mocked result for 'executeProcess' */
   def dockerClient(execResult: => Future[String]) = new DockerClient()(global) 
{
     override val dockerCmd = Seq(dockerCommand)
+    override def getClientVersion() = "mock-test-client"
     override def executeProcess(args: Seq[String], timeout: Duration)(implicit 
ec: ExecutionContext, as: ActorSystem) =
       execResult
   }
@@ -189,6 +190,7 @@ class DockerClientTests
     var runCmdCount = 0
     val dc = new DockerClient()(global) {
       override val dockerCmd = Seq(dockerCommand)
+      override def getClientVersion() = "mock-test-client"
       override def executeProcess(args: Seq[String], timeout: 
Duration)(implicit ec: ExecutionContext,
                                                                         as: 
ActorSystem) = {
         runCmdCount += 1
@@ -237,6 +239,7 @@ class DockerClientTests
     var runCmdCount = 0
     val dc = new DockerClient()(global) {
       override val dockerCmd = Seq(dockerCommand)
+      override def getClientVersion() = "mock-test-client"
       override def executeProcess(args: Seq[String], timeout: 
Duration)(implicit ec: ExecutionContext,
                                                                         as: 
ActorSystem) = {
         runCmdCount += 1
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientWithFileAccessTests.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientWithFileAccessTests.scala
index a3936ac..f21063d 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientWithFileAccessTests.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerClientWithFileAccessTests.scala
@@ -73,6 +73,7 @@ class DockerClientWithFileAccessTestsIp
                    readResult: Future[JsObject] = 
Future.successful(dockerConfig)) =
     new DockerClientWithFileAccess()(global) {
       override val dockerCmd = Seq(dockerCommand)
+      override def getClientVersion() = "mock-test-client"
       override def executeProcess(args: Seq[String], timeout: 
Duration)(implicit ec: ExecutionContext,
                                                                         as: 
ActorSystem) = execResult
       override def configFileContents(configFile: File) = readResult
@@ -129,6 +130,7 @@ class DockerClientWithFileAccessTestsOom
   def dockerClient(readResult: Future[JsObject]) =
     new DockerClientWithFileAccess()(global) {
       override val dockerCmd = Seq("docker")
+      override def getClientVersion() = "mock-test-client"
       override def configFileContents(configFile: File) = readResult
     }
 
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
index 80b400d..212de56 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
@@ -102,12 +102,16 @@ class DockerContainerFactoryTests
       .rm(_: ContainerId)(_: TransactionId))
       .expects(ContainerId("fakecontainerid"), *)
       .returning(Future.successful(Unit))
+    //setup clientVersion exceptation
+    (dockerApiStub.clientVersion _)
+      .expects()
+      .returning("mock_test_client")
 
     val factory =
       new DockerContainerFactory(
         InvokerInstanceId(0, userMemory = defaultUserMemory),
         Map.empty,
-        ContainerArgsConfig("net1", Seq("dns1", "dns2"), Map("env" -> 
Set("e1", "e2"))),
+        ContainerArgsConfig("net1", Seq("dns1", "dns2"), Seq.empty, Seq.empty, 
Map("env" -> Set("e1", "e2"))),
         DockerContainerFactoryConfig(true))(actorSystem, executionContext, 
logging, dockerApiStub, mock[RuncApi])
 
     val cf = factory.createContainer(tid, "testContainer", image, false, 
10.MB, 32)
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerTests.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerTests.scala
index e1253a1..5edef3c 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerTests.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/docker/test/DockerContainerTests.scala
@@ -807,6 +807,8 @@ class DockerContainerTests
     var pulls = mutable.Buffer.empty[String]
     var rawContainerLogsInvocations = mutable.Buffer.empty[(ContainerId, Long, 
Option[FiniteDuration])]
 
+    def clientVersion: String = "mock-test-client"
+
     def run(image: String, args: Seq[String] = Seq.empty[String])(
       implicit transid: TransactionId): Future[ContainerId] = {
       runs += ((image, args))
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/mesos/test/MesosContainerFactoryTest.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/mesos/test/MesosContainerFactoryTest.scala
index 0178bc8..225a79b 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/mesos/test/MesosContainerFactoryTest.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/mesos/test/MesosContainerFactoryTest.scala
@@ -86,7 +86,12 @@ class MesosContainerFactoryTest
   val mesosCpus = poolConfig.cpuShare(actionMemory) / 1024.0
 
   val containerArgsConfig =
-    new ContainerArgsConfig("net1", Seq("dns1", "dns2"), Map("extra1" -> 
Set("e1", "e2"), "extra2" -> Set("e3", "e4")))
+    new ContainerArgsConfig(
+      "net1",
+      Seq("dns1", "dns2"),
+      Seq.empty,
+      Seq.empty,
+      Map("extra1" -> Set("e1", "e2"), "extra2" -> Set("e3", "e4")))
 
   override def beforeEach() = {
     stream.reset()
@@ -247,7 +252,12 @@ class MesosContainerFactoryTest
         system,
         logging,
         Map("--arg1" -> Set("v1", "v2"), "--arg2" -> Set("v3", "v4"), "other" 
-> Set("v5", "v6")),
-        new ContainerArgsConfig("bridge", Seq.empty, Map("extra1" -> Set("e1", 
"e2"), "extra2" -> Set("e3", "e4"))),
+        new ContainerArgsConfig(
+          "bridge",
+          Seq.empty,
+          Seq.empty,
+          Seq.empty,
+          Map("extra1" -> Set("e1", "e2"), "extra2" -> Set("e3", "e4"))),
         mesosConfig,
         (system, mesosConfig) => probe.testActor,
         testTaskId _)
diff --git 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/test/ContainerArgsConfigTest.scala
 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/test/ContainerArgsConfigTest.scala
index 7edd3e8..40add24 100644
--- 
a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/test/ContainerArgsConfigTest.scala
+++ 
b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/test/ContainerArgsConfigTest.scala
@@ -34,6 +34,8 @@ class ContainerArgsConfigTest extends FlatSpec with Matchers {
     //check defaults
     config.network shouldBe "bridge"
     config.dnsServers shouldBe Seq[String]()
+    config.dnsSearch shouldBe Seq[String]()
+    config.dnsOptions shouldBe Seq[String]()
     config.extraArgs shouldBe Map[String, Set[String]]()
   }
 
@@ -46,10 +48,18 @@ class ContainerArgsConfigTest extends FlatSpec with 
Matchers {
 
     System.setProperty("whisk.container-factory.container-args.dns-servers.0", 
"google.com")
     System.setProperty("whisk.container-factory.container-args.dns-servers.1", 
"1.2.3.4")
+
+    System.setProperty("whisk.container-factory.container-args.dns-search.0", 
"a.b.c")
+    System.setProperty("whisk.container-factory.container-args.dns-search.1", 
"a.b")
+
+    System.setProperty("whisk.container-factory.container-args.dns-options.0", 
"ndots:5")
+
     val config = 
loadConfigOrThrow[ContainerArgsConfig](ConfigKeys.containerArgs)
     //check defaults
     config.network shouldBe "bridge"
     config.dnsServers shouldBe Seq[String]("google.com", "1.2.3.4")
+    config.dnsSearch shouldBe Seq[String]("a.b.c", "a.b")
+    config.dnsOptions shouldBe Seq[String]("ndots:5")
     //check map parsing of extra-args config
     config.extraArgs.get("label") shouldBe Some(Set("l1", "l2", "l3"))
     config.extraArgs.get("env") shouldBe Some(Set("e1", "e2"))

Reply via email to