This is an automated email from the ASF dual-hosted git repository.
houshengbo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git
The following commit(s) were added to refs/heads/master by this push:
new 8da6e3b enable use of concurrency action limits via cli (#383)
8da6e3b is described below
commit 8da6e3bbd904e738205d568c46654ce5c0631937
Author: tysonnorris <[email protected]>
AuthorDate: Mon Nov 26 13:01:34 2018 -0800
enable use of concurrency action limits via cli (#383)
* enable --concurrency flag to set intra-container concurrency limit via
wsk cli
* formatting
* update incubator-openwhisk-client-go git version to latest
* missing ConcurrencyLimit
* formatting
* update client-go sha
* test env needs to override default max concurrency-limit in order to test
concurrency > 1
* missing license
* missing EOL
* add concurrency limit to limits test assertions
---
build.gradle | 2 +-
commands/action.go | 15 +++++--
commands/flags.go | 46 +++++++++++-----------
tests/src/test/resources/application.conf | 11 ++++++
.../core/cli/test/WskCliBasicUsageTests.scala | 33 +++++++++++-----
.../test/scala/system/basic/WskCliBasicTests.scala | 4 +-
wski18n/resources/en_US.all.json | 4 ++
7 files changed, 77 insertions(+), 38 deletions(-)
diff --git a/build.gradle b/build.gradle
index 945f879..eca828e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -57,7 +57,7 @@ dependencies {
build(['name':'golang.org/x/sys/unix',
'version':'7f918dd405547ecb864d14a8ecbbfe205b5f930f', 'transitive':false])
build(['name':'gopkg.in/yaml.v2',
'version':'cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b', 'transitive':false])
build(['name':'github.com/ghodss/yaml',
'version':'0ca9ea5df5451ffdf184b4428c902747c2c11cd7', 'transitive':false])
-
build(['name':'github.com/apache/incubator-openwhisk-client-go/whisk','version':'d7cee96e83a1f38413a1f5286bd524dac72686c9','transitive':false])
+
build(['name':'github.com/apache/incubator-openwhisk-client-go/whisk','version':'c7013c9f456f35be34b3bf166535aaa03b834331','transitive':false])
// END - Imported from Godeps
test name:'github.com/stretchr/testify',
version:'b91bfb9ebec76498946beb6af7c0230c7cc7ba6c', transitive:false //, tag:
'v1.2.0'
test name:'github.com/spf13/viper',
version:'aafc9e6bc7b7bb53ddaa75a5ef49a17d6e654be5', transitive:false
diff --git a/commands/action.go b/commands/action.go
index 4d0ad4e..e6429bc 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -42,6 +42,7 @@ const (
MEMORY_LIMIT = 256
TIMEOUT_LIMIT = 60000
LOGSIZE_LIMIT = 10
+ CONCURRENCY_LIMIT = 1
ACTIVATION_ID = "activationId"
WEB_EXPORT_ANNOT = "web-export"
RAW_HTTP_ANNOT = "raw-http"
@@ -413,9 +414,11 @@ func parseAction(cmd *cobra.Command, args []string, update
bool) (*whisk.Action,
cmd.LocalFlags().Changed(MEMORY_FLAG),
cmd.LocalFlags().Changed(LOG_SIZE_FLAG),
cmd.LocalFlags().Changed(TIMEOUT_FLAG),
+ cmd.LocalFlags().Changed(CONCURRENCY_FLAG),
Flags.action.memory,
Flags.action.logsize,
- Flags.action.timeout)
+ Flags.action.timeout,
+ Flags.action.concurrency)
paramArgs = Flags.common.param
annotArgs = Flags.common.annotation
@@ -886,10 +889,10 @@ func webSecureSecret(webSecureMode string) interface{} {
}
}
-func getLimits(memorySet bool, logSizeSet bool, timeoutSet bool, memory int,
logSize int, timeout int) *whisk.Limits {
+func getLimits(memorySet bool, logSizeSet bool, timeoutSet bool,
concurrencySet bool, memory int, logSize int, timeout int, concurrency int)
*whisk.Limits {
var limits *whisk.Limits
- if memorySet || logSizeSet || timeoutSet {
+ if memorySet || logSizeSet || timeoutSet || concurrencySet {
limits = new(whisk.Limits)
if memorySet {
@@ -903,6 +906,10 @@ func getLimits(memorySet bool, logSizeSet bool, timeoutSet
bool, memory int, log
if timeoutSet {
limits.Timeout = &timeout
}
+
+ if concurrencySet {
+ limits.Concurrency = &concurrency
+ }
}
return limits
@@ -1268,6 +1275,7 @@ func init() {
actionCreateCmd.Flags().IntVarP(&Flags.action.timeout, TIMEOUT_FLAG,
"t", TIMEOUT_LIMIT, wski18n.T("the timeout `LIMIT` in milliseconds after which
the action is terminated"))
actionCreateCmd.Flags().IntVarP(&Flags.action.memory, MEMORY_FLAG, "m",
MEMORY_LIMIT, wski18n.T("the maximum memory `LIMIT` in MB for the action"))
actionCreateCmd.Flags().IntVarP(&Flags.action.logsize, LOG_SIZE_FLAG,
"l", LOGSIZE_LIMIT, wski18n.T("the maximum log size `LIMIT` in MB for the
action"))
+ actionCreateCmd.Flags().IntVarP(&Flags.action.concurrency,
CONCURRENCY_FLAG, "c", CONCURRENCY_LIMIT, wski18n.T("the maximum
intra-container concurrent activation `LIMIT` for the action"))
actionCreateCmd.Flags().StringSliceVarP(&Flags.common.annotation,
"annotation", "a", nil, wski18n.T("annotation values in `KEY VALUE` format"))
actionCreateCmd.Flags().StringVarP(&Flags.common.annotFile,
"annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in
JSON format"))
actionCreateCmd.Flags().StringSliceVarP(&Flags.common.param, "param",
"p", nil, wski18n.T("parameter values in `KEY VALUE` format"))
@@ -1284,6 +1292,7 @@ func init() {
actionUpdateCmd.Flags().IntVarP(&Flags.action.timeout, TIMEOUT_FLAG,
"t", TIMEOUT_LIMIT, wski18n.T("the timeout `LIMIT` in milliseconds after which
the action is terminated"))
actionUpdateCmd.Flags().IntVarP(&Flags.action.memory, MEMORY_FLAG, "m",
MEMORY_LIMIT, wski18n.T("the maximum memory `LIMIT` in MB for the action"))
actionUpdateCmd.Flags().IntVarP(&Flags.action.logsize, LOG_SIZE_FLAG,
"l", LOGSIZE_LIMIT, wski18n.T("the maximum log size `LIMIT` in MB for the
action"))
+ actionUpdateCmd.Flags().IntVarP(&Flags.action.concurrency,
CONCURRENCY_FLAG, "c", CONCURRENCY_LIMIT, wski18n.T("the maximum
intra-container concurrent activation `LIMIT` for the action"))
actionUpdateCmd.Flags().StringSliceVarP(&Flags.common.annotation,
"annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE`
format"))
actionUpdateCmd.Flags().StringVarP(&Flags.common.annotFile,
"annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in
JSON format"))
actionUpdateCmd.Flags().StringSliceVarP(&Flags.common.param, "param",
"p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
diff --git a/commands/flags.go b/commands/flags.go
index 223ccfe..d9761d2 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -26,13 +26,14 @@ import (
///////////
const (
- MEMORY_FLAG = "memory"
- LOG_SIZE_FLAG = "logsize"
- TIMEOUT_FLAG = "timeout"
- WEB_FLAG = "web"
- WEB_SECURE_FLAG = "web-secure"
- SAVE_FLAG = "save"
- SAVE_AS_FLAG = "save-as"
+ MEMORY_FLAG = "memory"
+ LOG_SIZE_FLAG = "logsize"
+ CONCURRENCY_FLAG = "concurrency"
+ TIMEOUT_FLAG = "timeout"
+ WEB_FLAG = "web"
+ WEB_SECURE_FLAG = "web-secure"
+ SAVE_FLAG = "save"
+ SAVE_AS_FLAG = "save-as"
)
var cliDebug = os.Getenv("WSK_CLI_DEBUG") // Useful for tracing init() code
@@ -130,21 +131,22 @@ type FlagsStruct struct {
}
type ActionFlags struct {
- docker string
- native bool
- copy bool
- web string
- websecure string
- sequence bool
- timeout int
- memory int
- logsize int
- result bool
- kind string
- main string
- url bool
- save bool
- saveAs string
+ docker string
+ native bool
+ copy bool
+ web string
+ websecure string
+ sequence bool
+ timeout int
+ memory int
+ logsize int
+ concurrency int
+ result bool
+ kind string
+ main string
+ url bool
+ save bool
+ saveAs string
}
func IsVerbose() bool {
diff --git a/tests/src/test/resources/application.conf
b/tests/src/test/resources/application.conf
new file mode 100644
index 0000000..0abcab4
--- /dev/null
+++ b/tests/src/test/resources/application.conf
@@ -0,0 +1,11 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+#test-only overrides so that tests can override defaults in application.conf
(todo: move all defaults to reference.conf)
+test {
+ whisk {
+ concurrency-limit {
+ max = 500
+ }
+ }
+}
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala
b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala
index 5e44197..c7681eb 100644
---
a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala
+++
b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala
@@ -39,6 +39,7 @@ import common.WskTestHelpers
import spray.json.DefaultJsonProtocol._
import spray.json._
import org.apache.openwhisk.core.entity._
+import org.apache.openwhisk.core.entity.ConcurrencyLimit._
import org.apache.openwhisk.core.entity.LogLimit._
import org.apache.openwhisk.core.entity.MemoryLimit._
import org.apache.openwhisk.core.entity.TimeLimit._
@@ -390,6 +391,7 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
val memoryLimit = 512 MB
val logLimit = 1 MB
val timeLimit = 60 seconds
+ val concurrencyLimit = 500
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
action.create(
@@ -397,7 +399,8 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
Some(TestUtils.getTestActionFilename("helloAsync.js")),
memory = Some(memoryLimit),
timeout = Some(timeLimit),
- logsize = Some(logLimit))
+ logsize = Some(logLimit),
+ concurrency = Some(concurrencyLimit))
}
val run = wsk.action.invoke(name, Map("payload" -> "this is a
test".toJson))
@@ -408,7 +411,11 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
val limitsObj =
JsObject(
"key" -> JsString("limits"),
- "value" -> ActionLimits(TimeLimit(timeLimit),
MemoryLimit(memoryLimit), LogLimit(logLimit)).toJson)
+ "value" -> ActionLimits(
+ TimeLimit(timeLimit),
+ MemoryLimit(memoryLimit),
+ LogLimit(logLimit),
+ ConcurrencyLimit(concurrencyLimit)).toJson)
val path = annotations.find {
_.fields("key").convertTo[String] == "path"
@@ -2041,12 +2048,14 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
def testLimit(timeout: Option[Duration] = None,
memory: Option[ByteSize] = None,
logs: Option[ByteSize] = None,
+ concurrency: Option[Int] = None,
ec: Int = SUCCESS_EXIT) = {
// Limits to assert, standard values if CLI omits certain values
val limits = JsObject(
"timeout" -> timeout.getOrElse(STD_DURATION).toMillis.toJson,
"memory" -> memory.getOrElse(stdMemory).toMB.toInt.toJson,
- "logs" -> logs.getOrElse(stdLogSize).toMB.toInt.toJson)
+ "logs" -> logs.getOrElse(stdLogSize).toMB.toInt.toJson,
+ "concurrency" -> concurrency.getOrElse(stdConcurrent).toJson)
val name = "ActionLimitTests" + Instant.now.toEpochMilli
val createResult =
@@ -2057,8 +2066,10 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
logsize = logs,
memory = memory,
timeout = timeout,
+ concurrency = concurrency,
expectedExitCode = DONTCARE_EXIT)
- withClue(s"create failed for parameters: timeout = $timeout,
memory = $memory, logsize = $logs:") {
+ withClue(
+ s"create failed for parameters: timeout = $timeout, memory =
$memory, logsize = $logs, concurrency = $concurrency:") {
result.exitCode should be(ec)
}
result
@@ -2084,13 +2095,15 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
time <- Seq(None, Some(MIN_DURATION), Some(MAX_DURATION))
mem <- Seq(None, Some(minMemory), Some(maxMemory))
log <- Seq(None, Some(minLogSize), Some(maxLogSize))
- } testLimit(time, mem, log)
+ concurrency <- Seq(None, Some(minConcurrent), Some(maxConcurrent))
+ } testLimit(time, mem, log, concurrency)
// Assert that invalid permutation are rejected
- testLimit(Some(0.milliseconds), None, None, BAD_REQUEST)
- testLimit(Some(100.minutes), None, None, BAD_REQUEST)
- testLimit(None, Some(0.MB), None, BAD_REQUEST)
- testLimit(None, Some(32768.MB), None, BAD_REQUEST)
- testLimit(None, None, Some(32768.MB), BAD_REQUEST)
+ testLimit(Some(0.milliseconds), None, None, None, BAD_REQUEST)
+ testLimit(Some(100.minutes), None, None, None, BAD_REQUEST)
+ testLimit(None, Some(0.MB), None, None, BAD_REQUEST)
+ testLimit(None, Some(32768.MB), None, None, BAD_REQUEST)
+ testLimit(None, None, Some(32768.MB), None, BAD_REQUEST)
+ testLimit(None, None, None, Some(5000), BAD_REQUEST)
}
}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala
b/tests/src/test/scala/system/basic/WskCliBasicTests.scala
index ba98949..2acbfaf 100644
--- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala
@@ -313,8 +313,8 @@ class WskCliBasicTests extends TestHelpers with
WskTestHelpers {
.get(name, fieldFilter = Some("annotations"))
.stdout should include regex (s"""$successMsg
annotations\n\\[\\s+\\{\\s+"key":\\s+"exec",\\s+"value":\\s+"nodejs:6"\\s+\\}\\s+\\]""")
wsk.action
- .get(name, fieldFilter = Some("limits"))
- .stdout should include regex (s"""$successMsg
limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10\\s+\\}""")
+ .get(name, fieldFilter = Some("limits")) //
+ .stdout should include regex (s"""$successMsg
limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10,\\s+"concurrency":\\s+1\\s+\\}""")
wsk.action
.get(name, fieldFilter = Some("namespace"))
.stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 3e7024e..a837d5e 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -928,6 +928,10 @@
"translation": "the maximum memory `LIMIT` in MB for the action"
},
{
+ "id": "the maximum intra-container concurrent activation `LIMIT` for the
action",
+ "translation": "the maximum intra-container concurrent activation `LIMIT`
for the action"
+ },
+ {
"id": "the maximum log size `LIMIT` in MB for the action",
"translation": "the maximum log size `LIMIT` in MB for the action"
},