dubeejw closed pull request #2402: Add Configurable Limits to Controller
URL: https://github.com/apache/incubator-openwhisk/pull/2402
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/ansible/environments/local/group_vars/all 
b/ansible/environments/local/group_vars/all
index 27b8515c07..e3e96659d5 100755
--- a/ansible/environments/local/group_vars/all
+++ b/ansible/environments/local/group_vars/all
@@ -17,9 +17,13 @@ db_port: "{{ lookup('ini', 'db_port section=db_creds file={{ 
playbook_dir }}/db_
 limits:
   actions:
     invokes:
-      perMinute: 60
+      blockingTimeout: 60
       concurrent: 30
       concurrentInSystem: 5000
+      perMinute: 60
+  activations:
+    polls:
+      maxRecords: 200
   triggers:
     fires:
       perMinute: 60
diff --git a/ansible/environments/mac/group_vars/all 
b/ansible/environments/mac/group_vars/all
index 6d14d1ddb7..6177b96030 100644
--- a/ansible/environments/mac/group_vars/all
+++ b/ansible/environments/mac/group_vars/all
@@ -22,9 +22,13 @@ db_port: "{{ lookup('ini', 'db_port section=db_creds file={{ 
playbook_dir }}/db_
 limits:
   actions:
     invokes:
-      perMinute: 60
+      blockingTimeout: 60
       concurrent: 30
       concurrentInSystem: 5000
+      perMinute: 60
+  activations:
+    polls:
+      maxRecords: 200
   triggers:
     fires:
       perMinute: 60
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
index 4e42368c7c..d792b0372e 100644
--- a/ansible/group_vars/all
+++ b/ansible/group_vars/all
@@ -78,11 +78,15 @@ runtimesManifest:
 defaultLimits:
   actions:
     invokes:
-      perMinute: 120
+      blockingTimeout: 60
       concurrent: 100
       concurrentInSystem: 5000
+      perMinute: 120
     sequence:
       maxLength: 50
+  activations:
+    polls:
+      maxRecords: 200
   triggers:
     fires:
       perMinute: 60
diff --git a/ansible/templates/whisk.properties.j2 
b/ansible/templates/whisk.properties.j2
index 5ee84f7f4b..32f235e849 100644
--- a/ansible/templates/whisk.properties.j2
+++ b/ansible/templates/whisk.properties.j2
@@ -33,16 +33,20 @@ whisk.api.localhost.name={{ whisk_api_localhost_name | 
default(whisk_api_host_na
 whisk.api.vanity.subdomain.parts=1
 
 runtimes.manifest={{ runtimesManifest | to_json }}
-defaultLimits.actions.invokes.perMinute={{ 
defaultLimits.actions.invokes.perMinute }}
+defaultLimits.actions.invokes.blockingTimeout={{ 
defaultLimits.actions.invokes.blockingTimeout }}
 defaultLimits.actions.invokes.concurrent={{ 
defaultLimits.actions.invokes.concurrent }}
-defaultLimits.triggers.fires.perMinute={{ 
defaultLimits.triggers.fires.perMinute }}
 defaultLimits.actions.invokes.concurrentInSystem={{ 
defaultLimits.actions.invokes.concurrentInSystem }}
+defaultLimits.actions.invokes.perMinute={{ 
defaultLimits.actions.invokes.perMinute }}
 defaultLimits.actions.sequence.maxLength={{ 
defaultLimits.actions.sequence.maxLength }}
+defaultLimits.activations.polls.maxRecords={{ 
defaultLimits.activations.polls.maxRecords }}
+defaultLimits.triggers.fires.perMinute={{ 
defaultLimits.triggers.fires.perMinute }}
 
 {% if limits is defined %}
-limits.actions.invokes.perMinute={{ limits.actions.invokes.perMinute }}
+limits.actions.invokes.blockingTimeout={{ 
limits.actions.invokes.blockingTimeout }}
 limits.actions.invokes.concurrent={{ limits.actions.invokes.concurrent }}
 limits.actions.invokes.concurrentInSystem={{ 
limits.actions.invokes.concurrentInSystem }}
+limits.actions.invokes.perMinute={{ limits.actions.invokes.perMinute }}
+limits.activations.polls.maxRecords={{ limits.activations.polls.maxRecords }}
 limits.triggers.fires.perMinute={{ limits.triggers.fires.perMinute }}
 {% endif %}
 
diff --git a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala 
b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
index 267ad382ee..d39747291c 100644
--- a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
+++ b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
@@ -112,11 +112,13 @@ class WhiskConfig(
 
     val runtimesManifest = this(WhiskConfig.runtimesManifest)
 
-    val actionInvokePerMinuteLimit = 
this(WhiskConfig.actionInvokePerMinuteDefaultLimit, 
WhiskConfig.actionInvokePerMinuteLimit)
+    val actionInvokeBlockingTimeoutLimit = 
this(WhiskConfig.actionInvokeBlockingTimeoutDefaultLimit, 
WhiskConfig.actionInvokeBlockingTimeoutLimit)
     val actionInvokeConcurrentLimit = 
this(WhiskConfig.actionInvokeConcurrentDefaultLimit, 
WhiskConfig.actionInvokeConcurrentLimit)
-    val triggerFirePerMinuteLimit = 
this(WhiskConfig.triggerFirePerMinuteDefaultLimit, 
WhiskConfig.triggerFirePerMinuteLimit)
     val actionInvokeSystemOverloadLimit = 
this(WhiskConfig.actionInvokeSystemOverloadDefaultLimit, 
WhiskConfig.actionInvokeSystemOverloadLimit)
+    val actionInvokePerMinuteLimit = 
this(WhiskConfig.actionInvokePerMinuteDefaultLimit, 
WhiskConfig.actionInvokePerMinuteLimit)
     val actionSequenceLimit = this(WhiskConfig.actionSequenceDefaultLimit)
+    val activationPollMaxRecordLimit = 
this(WhiskConfig.activationPollMaxRecordDefaultLimit, 
WhiskConfig.activationPollMaxRecordLimit)
+    val triggerFirePerMinuteLimit = 
this(WhiskConfig.triggerFirePerMinuteDefaultLimit, 
WhiskConfig.triggerFirePerMinuteLimit)
 }
 
 object WhiskConfig {
@@ -275,13 +277,18 @@ object WhiskConfig {
 
     val runtimesManifest = "runtimes.manifest"
 
-    val actionInvokePerMinuteDefaultLimit = 
"defaultLimits.actions.invokes.perMinute"
+    val actionInvokeBlockingTimeoutLimit = 
"limits.actions.invokes.blockingTimeout"
+    val actionInvokeBlockingTimeoutDefaultLimit = 
"defaultLimits.actions.invokes.blockingTimeout"
+    val actionInvokeConcurrentLimit = "limits.actions.invokes.concurrent"
     val actionInvokeConcurrentDefaultLimit = 
"defaultLimits.actions.invokes.concurrent"
-    val actionInvokeSystemOverloadDefaultLimit = 
"defaultLimits.actions.invokes.concurrentInSystem"
-    val triggerFirePerMinuteDefaultLimit = 
"defaultLimits.triggers.fires.perMinute"
-    val actionSequenceDefaultLimit = "defaultLimits.actions.sequence.maxLength"
     val actionInvokePerMinuteLimit = "limits.actions.invokes.perMinute"
-    val actionInvokeConcurrentLimit = "limits.actions.invokes.concurrent"
+    val actionInvokePerMinuteDefaultLimit = 
"defaultLimits.actions.invokes.perMinute"
     val actionInvokeSystemOverloadLimit = 
"limits.actions.invokes.concurrentInSystem"
+    val actionInvokeSystemOverloadDefaultLimit = 
"defaultLimits.actions.invokes.concurrentInSystem"
+    val actionSequenceDefaultLimit = "defaultLimits.actions.sequence.maxLength"
+    val activationPollMaxRecordLimit = "limits.activations.polls.maxRecords"
+    val activationPollMaxRecordDefaultLimit = 
"defaultLimits.activations.polls.maxRecords"
     val triggerFirePerMinuteLimit = "limits.triggers.fires.perMinute"
+    val triggerFirePerMinuteDefaultLimit = 
"defaultLimits.triggers.fires.perMinute"
+
 }
diff --git a/core/controller/src/main/scala/whisk/core/controller/Actions.scala 
b/core/controller/src/main/scala/whisk/core/controller/Actions.scala
index e685bf478a..222d7c7451 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Actions.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Actions.scala
@@ -54,13 +54,13 @@ import whisk.http.Messages._
  * in order to implement the actions API.
  */
 object WhiskActionsApi {
-    def requiredProperties = Map(WhiskConfig.actionSequenceDefaultLimit -> 
null)
+    def requiredProperties = Map(WhiskConfig.actionSequenceDefaultLimit -> 
null,
+        WhiskConfig.actionInvokeBlockingTimeoutDefaultLimit -> null)
+
+    def optionalProperties = Set(WhiskConfig.actionInvokeBlockingTimeoutLimit)
 
     /** Grace period after action timeout limit to poll for result. */
     protected[core] val blockingInvokeGrace = 5 seconds
-
-    /** Max duration to wait for a blocking activation. */
-    protected[core] val maxWaitForBlockingActivation = 60 seconds
 }
 
 /** A trait implementing the actions API. */
@@ -212,7 +212,7 @@ trait WhiskActionsApi
      * - 500 Internal Server Error
      */
     override def activate(user: Identity, entityName: 
FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: 
TransactionId) = {
-        parameter('blocking ? false, 'result ? false, 'timeout ? 
WhiskActionsApi.maxWaitForBlockingActivation) { (blocking, result, 
waitOverride) =>
+        parameter('blocking ? false, 'result ? false, 'timeout ? 
actionInvokeBlockingTimeoutLimit) { (blocking, result, waitOverride) =>
             entity(as[Option[JsObject]]) { payload =>
                 getEntity(WhiskAction, entityStore, entityName.toDocId, Some {
                     act: WhiskAction =>
@@ -625,14 +625,16 @@ trait WhiskActionsApi
     /** Max atomic action count allowed for sequences */
     private lazy val actionSequenceLimit = 
whiskConfig.actionSequenceLimit.toInt
 
+    lazy val actionInvokeBlockingTimeoutLimit = 
whiskConfig.actionInvokeBlockingTimeoutLimit.toInt.seconds
+
     /** Custom deserializer for timeout query parameter. */
     private implicit val stringToTimeoutDeserializer = new 
FromStringDeserializer[FiniteDuration] {
-        val max = WhiskActionsApi.maxWaitForBlockingActivation.toMillis
+        val max = actionInvokeBlockingTimeoutLimit.toMillis
         def apply(msecs: String): Either[DeserializationError, FiniteDuration] 
= {
             Try { msecs.toInt } match {
                 case Success(i) if i > 0 && i <= max => Right(i.milliseconds)
                 case _ => Left {
-                    
MalformedContent(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
+                    
MalformedContent(Messages.invalidTimeout(actionInvokeBlockingTimeoutLimit))
                 }
             }
         }
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/Activations.scala 
b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
index 294dfd80a0..cc3d7baf6e 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Activations.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
@@ -39,8 +39,15 @@ import whisk.core.entitlement.Privilege.READ
 import whisk.core.entitlement.Resource
 import whisk.core.entity._
 import whisk.core.entity.types.ActivationStore
+import whisk.core.WhiskConfig
 import whisk.http.Messages
 
+object WhiskActivationsApi {
+    def requiredProperties = 
Map(WhiskConfig.activationPollMaxRecordDefaultLimit -> null)
+
+    def optionalProperties = Set(WhiskConfig.activationPollMaxRecordLimit)
+}
+
 /** A trait implementing the activations API. */
 trait WhiskActivationsApi
     extends Directives
@@ -63,6 +70,10 @@ trait WhiskActivationsApi
     /** Only GET is supported in this API. */
     protected override lazy val entityOps = get
 
+    protected val whiskConfig: WhiskConfig
+
+    private lazy val activationPollMaxRecordLimit = 
whiskConfig.activationPollMaxRecordLimit.toInt
+
     /** Validated entity name as an ActivationId from the matched path 
segment. */
     protected override def entityname(n: String) = {
         val activationId = Try { ActivationId(n) }
@@ -111,7 +122,7 @@ trait WhiskActivationsApi
         parameter('skip ? 0, 'limit ? collection.listLimit, 'count ? false, 
'docs ? false, 'name.as[EntityName]?, 'since.as[Instant]?, 'upto.as[Instant]?) {
             (skip, limit, count, docs, name, since, upto) =>
                 // regardless of limit, cap at 200 records, client must 
paginate
-                val cappedLimit = if (limit == 0 || limit > 200) 200 else limit
+                val cappedLimit = if (limit == 0 || limit > 
activationPollMaxRecordLimit) activationPollMaxRecordLimit else limit
                 val activations = name match {
                     case Some(action) =>
                         WhiskActivation.listCollectionByName(activationStore, 
namespace, action, skip, cappedLimit, docs, since, upto)
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/Controller.scala 
b/core/controller/src/main/scala/whisk/core/controller/Controller.scala
index f383cd0b3e..383f3424e6 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Controller.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Controller.scala
@@ -146,8 +146,7 @@ object Controller {
     def requiredProperties = Map(WhiskConfig.servicePort -> 8080.toString) ++
         ExecManifest.requiredProperties ++
         RestApiCommons.requiredProperties ++
-        LoadBalancerService.requiredProperties ++
-        EntitlementProvider.requiredProperties
+        LoadBalancerService.requiredProperties
 
     def optionalProperties = EntitlementProvider.optionalProperties
 
@@ -160,7 +159,9 @@ object Controller {
         "limits" -> JsObject(
             "actions_per_minute" -> 
config.actionInvokePerMinuteLimit.toInt.toJson,
             "triggers_per_minute" -> 
config.triggerFirePerMinuteLimit.toInt.toJson,
-            "concurrent_actions" -> 
config.actionInvokeConcurrentLimit.toInt.toJson),
+            "concurrent_actions" -> 
config.actionInvokeConcurrentLimit.toInt.toJson,
+            "action_blocking_timeout" -> 
config.actionInvokeBlockingTimeoutLimit.toInt.toJson,
+            "activation_poll_record_limit" -> 
config.activationPollMaxRecordLimit.toInt.toJson),
         "runtimes" -> runtimes.toJson)
 
     // akka-style factory to create a Controller object
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala 
b/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
index 6202868ad3..83f2d9930a 100644
--- a/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
@@ -95,7 +95,8 @@ protected[controller] object RestApiCommons {
             EntitlementProvider.requiredProperties ++
             WhiskActionsApi.requiredProperties ++
             Authenticate.requiredProperties ++
-            Collection.requiredProperties
+            Collection.requiredProperties ++
+            WhiskActivationsApi.requiredProperties
 
     /**
      * The web actions API is available in both v1 and v2.
@@ -273,7 +274,8 @@ protected[controller] class RestAPIVersion(apipath: String, 
apiversion: String)(
             implicit override val activationStore: ActivationStore,
             override val entitlementProvider: EntitlementProvider,
             override val executionContext: ExecutionContext,
-            override val logging: Logging)
+            override val logging: Logging,
+            override val whiskConfig: WhiskConfig)
         extends WhiskActivationsApi
 
     class PackagesApi(
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala 
b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
index 9d30d706f9..e1aa4fddef 100644
--- a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
@@ -25,6 +25,7 @@ import scala.concurrent.Future
 import scala.util.Failure
 import scala.util.Success
 import scala.util.Try
+import scala.concurrent.duration._
 
 import WhiskWebActionsApi.MediaExtension
 import spray.http._
@@ -43,6 +44,7 @@ import spray.routing.RequestContext
 import spray.routing.Route
 import spray.http.HttpMethods.{ OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH }
 import whisk.common.TransactionId
+import whisk.core.WhiskConfig
 import whisk.core.controller.actions.BlockingInvokeTimeout
 import whisk.core.controller.actions.PostActionActivation
 import whisk.core.database._
@@ -69,6 +71,10 @@ protected[controller] sealed class WebApiDirectives private 
(prefix: String) {
 
     lazy val reservedProperties: Set[String] = Set(method, headers, path, 
namespace, query, body)
     protected final def fields(f: String) = s"$prefix$f"
+
+    def requiredProperties = 
Map(WhiskConfig.actionInvokeBlockingTimeoutDefaultLimit -> null)
+
+    def optionalProperties = Set(WhiskConfig.actionInvokeBlockingTimeoutLimit)
 }
 
 // field names for /web with raw-http action
@@ -322,6 +328,8 @@ trait WhiskWebActionsApi
     private val allowOrigin = `Access-Control-Allow-Origin`(AllOrigins)
     private val allowMethods = `Access-Control-Allow-Methods`(OPTIONS, GET, 
DELETE, POST, PUT, HEAD, PATCH)
 
+    private lazy val actionInvokeBlockingTimeoutLimit = 
whiskConfig.actionInvokeBlockingTimeoutLimit.toInt.seconds
+
     /** Extracts the HTTP method, headers, query params and unmatched 
(remaining) path. */
     private val requestMethodParamsAndPath = {
         extract { ctx =>
@@ -540,7 +548,7 @@ trait WhiskWebActionsApi
             // they will be overwritten
             if (isRawHttpAction || 
context.overrides(webApiDirectives.reservedProperties ++ 
action.immutableParameters).isEmpty) {
                 val content = context.toActionArgument(onBehalfOf, 
isRawHttpAction)
-                val waitOverride = 
Some(WhiskActionsApi.maxWaitForBlockingActivation)
+                val waitOverride = Some(actionInvokeBlockingTimeoutLimit)
                 invokeAction(actionOwnerIdentity, action, 
Some(JsObject(content)), blocking = true, waitOverride)
             } else {
                 Future.failed(RejectRequest(BadRequest, 
Messages.parametersNotAllowed))
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala
 
b/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala
index 9f98a71cd6..8e861c800b 100644
--- 
a/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala
+++ 
b/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala
@@ -30,7 +30,6 @@ import whisk.common.LoggingMarkers
 import whisk.common.TransactionId
 import whisk.core.connector.ActivationMessage
 import whisk.core.controller.WhiskServices
-import whisk.core.controller.WhiskActionsApi
 import whisk.core.database.NoDocumentException
 import whisk.core.entity._
 import whisk.core.entity.types.ActivationStore
@@ -55,7 +54,7 @@ protected[actions] trait PrimitiveActions {
     protected val activationStore: ActivationStore
 
     /** Max duration for active ack. */
-    protected val activeAckTimeout = 
WhiskActionsApi.maxWaitForBlockingActivation
+    protected val activeAckTimeout = 
whiskConfig.actionInvokeBlockingTimeoutLimit.toInt.seconds
 
     /**
      * Gets document from datastore to confirm a valid action activation then 
posts request to loadbalancer.
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
 
b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
index 042bc0854f..19329b2ac0 100644
--- 
a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
+++ 
b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
@@ -111,7 +111,7 @@ protected[actions] trait SequenceActions {
         if (topmost) { // need to deal with blocking and closing connection
             if (blocking) {
                 logging.info(this, s"invoke sequence blocking topmost!")
-                val timeout = maxWaitForBlockingActivation + 
blockingInvokeGrace
+                val timeout = 
whiskConfig.actionInvokeBlockingTimeoutLimit.toInt.seconds + blockingInvokeGrace
                 // if the future fails with a timeout, the failure is dealt 
with at the caller level
                 futureSeqResult.withTimeout(timeout, new 
BlockingInvokeTimeout(seqActivationId))
             } else {
diff --git a/tests/src/test/scala/common/WhiskProperties.java 
b/tests/src/test/scala/common/WhiskProperties.java
index 3591225f94..6e908c063d 100644
--- a/tests/src/test/scala/common/WhiskProperties.java
+++ b/tests/src/test/scala/common/WhiskProperties.java
@@ -254,10 +254,38 @@ public static int getControllerPort() {
         return 
Integer.parseInt(whiskProperties.getProperty("controller.host.port"));
     }
 
+    public static int getActionInvokeBlockingTimeout() {
+        return getPropertyLimit("limits.actions.invokes.blockingTimeout", 
"defaultLimits.actions.invokes.blockingTimeout");
+    }
+
+    public static int getActionInvokeConcurent() {
+        return getPropertyLimit("limits.actions.invokes.concurrent", 
"defaultLimits.actions.invokes.concurrent");
+    }
+
+    public static int getActionInvokeConcurentInSystem() {
+        return getPropertyLimit("limits.actions.invokes.concurrentInSystem", 
"defaultLimits.actions.invokes.concurrentInSystem");
+    }
+
     public static int getMaxActionInvokesPerMinute() {
-        String valStr = 
whiskProperties.getProperty("limits.actions.invokes.perMinute");
+        return getPropertyLimit("limits.actions.invokes.perMinute", 
"defaultLimits.actions.invokes.perMinute");
+    }
+
+    public static int getActionSequenceMaxLength() {
+        return getPropertyLimit("limits.actions.sequence.maxLength", 
"defaultLimits.actions.sequence.maxLength");
+    }
+
+    public static int getActivationPollMaxRecords() {
+        return getPropertyLimit("limits.activations.polls.maxRecords", 
"defaultLimits.activations.polls.maxRecords");
+    }
+
+    public static int getTriggerFiresPerMinute() {
+        return getPropertyLimit("limits.triggers.fires.perMinute", 
"defaultLimits.triggers.fires.perMinute");
+    }
+
+    private static int getPropertyLimit(String property, String 
defaultProperty) {
+        String valStr = whiskProperties.getProperty(property);
         if (null == valStr) {
-            valStr = 
whiskProperties.getProperty("defaultLimits.actions.invokes.perMinute");
+            valStr = whiskProperties.getProperty(defaultProperty);
         }
         return Integer.parseInt(valStr);
     }
diff --git a/tests/src/test/scala/system/rest/ControllerInfo.scala 
b/tests/src/test/scala/system/rest/ControllerInfo.scala
new file mode 100644
index 0000000000..5171b27fe9
--- /dev/null
+++ b/tests/src/test/scala/system/rest/ControllerInfo.scala
@@ -0,0 +1,55 @@
+/*
+ * 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 system.rest
+
+import org.junit.runner.RunWith
+import org.scalatest.FlatSpec
+import org.scalatest.Matchers
+import org.scalatest.junit.JUnitRunner
+
+import com.jayway.restassured.RestAssured
+
+import common.WhiskProperties
+
+import spray.json._
+
+@RunWith(classOf[JUnitRunner])
+class ControllerInfo extends FlatSpec with Matchers with RestUtil {
+
+    it should "get info route from controller" in {
+        val response = RestAssured.given.config(sslconfig).get(getServiceURL)
+
+        response.statusCode shouldBe 200
+        response.body.asString.contains("\"support\":") shouldBe true
+        response.body.asString.contains("\"description\":") shouldBe true
+        response.body.asString.contains("\"runtimes\":") shouldBe true
+        response.body.asString.contains("\"limits\":") shouldBe true
+
+        val limits = 
response.body.asString.parseJson.asJsObject.fields("limits").asJsObject
+        val expectedLimits = JsObject(
+            "action_blocking_timeout" -> 
JsNumber(WhiskProperties.getActionInvokeBlockingTimeout),
+            "concurrent_actions" -> 
JsNumber(WhiskProperties.getActionInvokeConcurent),
+            //"concurrent_actions_in_system" -> 
JsNumber(WhiskProperties.getActionInvokeConcurentInSystem),
+            "actions_per_minute" -> 
JsNumber(WhiskProperties.getMaxActionInvokesPerMinute),
+            //"action_sequence_max" -> 
JsNumber(WhiskProperties.getActionSequenceMaxLength),
+            "activation_poll_record_limit" -> 
JsNumber(WhiskProperties.getActivationPollMaxRecords),
+            "triggers_per_minute" -> 
JsNumber(WhiskProperties.getTriggerFiresPerMinute))
+
+        limits shouldBe expectedLimits
+    }
+}
diff --git 
a/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala 
b/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
index a41e3287b9..ae22db2a93 100644
--- a/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
@@ -661,12 +661,12 @@ class ActionsApiTests extends ControllerTestCommon with 
WhiskActionsApi {
 
             Post(s"$collectionPath/${action.name}?blocking=true&timeout=0") ~> 
sealRoute(routes(creds)) ~> check {
                 status shouldBe BadRequest
-                responseAs[String] should 
include(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
+                responseAs[String] should 
include(Messages.invalidTimeout(actionInvokeBlockingTimeoutLimit))
             }
 
             
Post(s"$collectionPath/${action.name}?blocking=true&timeout=65000") ~> 
sealRoute(routes(creds)) ~> check {
                 status shouldBe BadRequest
-                responseAs[String] should 
include(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
+                responseAs[String] should 
include(Messages.invalidTimeout(actionInvokeBlockingTimeoutLimit))
             }
 
             // will not wait long enough should get accepted status


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to