diff --git a/ansible/templates/whisk.properties.j2 b/ansible/templates/whisk.properties.j2 index 5951788bcde..c3e9329f803 100644 --- a/ansible/templates/whisk.properties.j2 +++ b/ansible/templates/whisk.properties.j2 @@ -46,7 +46,10 @@ kafka.hosts={{ kafka_connect_string }} redis.host={{ groups["redis"]|default([""])|first }} router.host={{ groups["edge"]|first }} zookeeper.hosts={{ zookeeper_connect_string }} +invoker.protocol={{ invoker.protocol }} invoker.hosts={{ groups["invokers"] | map('extract', hostvars, 'ansible_host') | list | join(",") }} +invoker.username={{ invoker.username }} +invoker.password={{ invoker.password }} edge.host.apiport=443 kafkaras.host.port={{ kafka.ras.port }} @@ -57,6 +60,8 @@ controller.hosts={{ groups["controllers"] | map('extract', hostvars, 'ansible_ho controller.host.basePort={{ controller.basePort }} controller.instances={{ controller.instances }} controller.protocol={{ controller.protocol }} +controller.username={{ controller.username }} +controller.password={{ controller.password }} invoker.container.network=bridge invoker.container.policy={{ invoker_container_policy_name | default()}} diff --git a/tests/build.gradle b/tests/build.gradle index d3e04e70407..32330445e65 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -52,6 +52,7 @@ def systemIncludes = [ "org/apache/openwhisk/core/apigw/actions/test/**", "org/apache/openwhisk/core/database/test/*CacheConcurrencyTests*", "org/apache/openwhisk/core/controller/test/*ControllerApiTests*", + "org/apache/openwhisk/operation/**", "apigw/healthtests/**", "ha/**", "services/**", @@ -70,6 +71,7 @@ ext.testSets = [ "org/apache/openwhisk/standalone/**", "org/apache/openwhisk/core/cli/test/**", "org/apache/openwhisk/core/limits/**", + "org/apache/openwhisk/operation/**", "**/*CacheConcurrencyTests*", "**/*ControllerApiTests*", "org/apache/openwhisk/testEntities/**", diff --git a/tests/src/test/scala/common/WhiskProperties.java b/tests/src/test/scala/common/WhiskProperties.java index 540d72ccae8..fcbfbcba65f 100644 --- a/tests/src/test/scala/common/WhiskProperties.java +++ b/tests/src/test/scala/common/WhiskProperties.java @@ -258,10 +258,40 @@ public static int getControllerBasePort() { return Integer.parseInt(whiskProperties.getProperty("controller.host.basePort")); } + public static String getControllerProtocol() { + return whiskProperties.getProperty("controller.protocol"); + } + public static String getBaseControllerHost() { return getControllerHosts().split(",")[0]; } + public static String getInvokerProtocol() { + return whiskProperties.getProperty("invoker.protocol"); + } + + + public static String getBaseInvokerAddress(){ + return getInvokerHosts()[0] + ":" + whiskProperties.getProperty("invoker.hosts.basePort"); + } + + public static String getControllerUsername() { + return whiskProperties.getProperty("controller.username"); + } + + public static String getControllerPassword() { + return whiskProperties.getProperty("controller.password"); + } + + + public static String getInvokerUsername() { + return whiskProperties.getProperty("invoker.username"); + } + + public static String getInvokerPassword() { + return whiskProperties.getProperty("invoker.password"); + } + public static String getBaseDBHost() { return getDBHosts().split(",")[0]; } diff --git a/tests/src/test/scala/org/apache/openwhisk/operation/RuntimeConfiguration.scala b/tests/src/test/scala/org/apache/openwhisk/operation/RuntimeConfiguration.scala new file mode 100644 index 00000000000..6b107c8f274 --- /dev/null +++ b/tests/src/test/scala/org/apache/openwhisk/operation/RuntimeConfiguration.scala @@ -0,0 +1,142 @@ +package org.apache.openwhisk.operation + +import akka.http.scaladsl.Http +import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials} +import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpMethods, HttpRequest, StatusCodes} +import akka.http.scaladsl.unmarshalling.Unmarshal +import akka.stream.ActorMaterializer +import common._ +import common.rest.HttpConnection +import org.apache.openwhisk.core.connector.PrewarmContainerDataList +import org.apache.openwhisk.core.connector.PrewarmContainerDataProtocol._ +import org.junit.runner.RunWith +import org.scalatest.Matchers +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.junit.JUnitRunner +import spray.json._ +import system.rest.RestUtil + +import scala.concurrent.duration._ +import scala.util.Random + +@RunWith(classOf[JUnitRunner]) +class RuntimeConfigurationTests + extends TestHelpers + with RestUtil + with Matchers + with ScalaFutures + with WskActorSystem + with StreamLogging { + + implicit val materializer = ActorMaterializer() + + val kind = "nodejs:10" + val memory = 128 + var count = new Random().nextInt(3) + 1 + + def getRuntimes = { + s""" { + "runtimes": { + "nodejs": [{ + "kind": "${kind}", + "default": true, + "image": { + "prefix": "openwhisk", + "name": "action-nodejs-v10", + "tag": "nightly" + }, + "deprecated": false, + "attached": { + "attachmentName": "codefile", + "attachmentType": "text/plain" + }, + "stemCells": [{ + "count": ${count}, + "memory": "${memory} MB" + }] + }] + } + }""" + } + + val invokerProtocol = WhiskProperties.getInvokerProtocol + val invokerAddress = WhiskProperties.getBaseInvokerAddress + val invokerUsername = WhiskProperties.getInvokerUsername + val invokerPassword = WhiskProperties.getInvokerPassword + val invokerAuthHeader = Authorization(BasicHttpCredentials(invokerUsername, invokerPassword)) + + val controllerProtocol = WhiskProperties.getControllerProtocol + val controllerAddress = WhiskProperties.getBaseControllerAddress + val controllerUsername = WhiskProperties.getControllerUsername + val controllerPassword = WhiskProperties.getControllerPassword + val controllerAuthHeader = Authorization(BasicHttpCredentials(controllerUsername, controllerPassword)) + + val getRuntimeUrl = s"${invokerProtocol}://${invokerAddress}/getRuntime" + val invokerChangeRuntimeUrl = s"${invokerProtocol}://${invokerAddress}/config/runtime" + val controllerChangeRuntimeUrl = + s"${controllerProtocol}://${controllerAddress}/config/runtime" + + it should "change assigned invoker node's runtime config directly" in { + //Change config + Http() + .singleRequest( + HttpRequest( + method = HttpMethods.POST, + uri = s"${invokerChangeRuntimeUrl}", + headers = List(invokerAuthHeader), + entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, getRuntimes)), + connectionContext = HttpConnection.getContext(invokerProtocol)) + .map { response => + response.status shouldBe StatusCodes.OK + } + + Thread.sleep(5.seconds.toMillis) + + //Cal the prewarm container number whether right + Http() + .singleRequest( + HttpRequest(method = HttpMethods.GET, uri = s"${getRuntimeUrl}", headers = List(invokerAuthHeader)), + connectionContext = HttpConnection.getContext(invokerProtocol)) + .map { response => + response.status shouldBe StatusCodes.OK + val prewarmContainerDataList = + Unmarshal(response).to[String].futureValue.parseJson.convertTo[PrewarmContainerDataList] + val nodejs10ContainerData = prewarmContainerDataList.items.filter { prewarmContainerData => + prewarmContainerData.kind == kind && prewarmContainerData.memory == memory + } + nodejs10ContainerData.head.number shouldBe count + } + } + + it should "change all managed invokers's prewarm config via controller" in { + //Change runtime config + Http() + .singleRequest( + HttpRequest( + method = HttpMethods.POST, + uri = s"${controllerChangeRuntimeUrl}", + headers = List(controllerAuthHeader), + entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, getRuntimes)), + connectionContext = HttpConnection.getContext(controllerProtocol)) + .map { response => + response.status shouldBe StatusCodes.OK + } + + Thread.sleep(5.seconds.toMillis) + + //Cal the prewarm container number whether right + Http() + .singleRequest( + HttpRequest(method = HttpMethods.GET, uri = s"${getRuntimeUrl}", headers = List(invokerAuthHeader)), + connectionContext = HttpConnection.getContext(invokerProtocol)) + .map { response => + response.status shouldBe StatusCodes.OK + val prewarmContainerDataList = + Unmarshal(response).to[String].futureValue.parseJson.convertTo[PrewarmContainerDataList] + val nodejs10ContainerData = prewarmContainerDataList.items.filter { prewarmContainerData => + prewarmContainerData.kind == kind && prewarmContainerData.memory == memory + } + nodejs10ContainerData.head.number shouldBe count + } + } +}