You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by du...@apache.org on 2018/03/21 21:08:24 UTC
[incubator-openwhisk-cli] branch master updated: Add --web-secure
option to action create/update (#244)
This is an automated email from the ASF dual-hosted git repository.
dubeejw 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 90f07ed Add --web-secure option to action create/update (#244)
90f07ed is described below
commit 90f07edd74b25d6785b8a152a70bd4e5d9a51e5f
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Wed Mar 21 17:08:22 2018 -0400
Add --web-secure option to action create/update (#244)
* Add --web-secure option to action create/update
- convenience wrapper around the `require-whisk-auth` annotation
- similar to the `web` option, when used to update an existing action all existing annotations will be preserved IF no other annotation is specified
* added --web-secure tests
* bump client-go
---
build.gradle | 2 +-
commands/action.go | 236 +-
commands/api.go | 15 +-
commands/flags.go | 42 +-
.../whisk/core/cli/test/WskBasicUsageTests.scala | 2608 +++++++++++++-------
wski18n/resources/en_US.all.json | 8 +
6 files changed, 1928 insertions(+), 983 deletions(-)
diff --git a/build.gradle b/build.gradle
index 2f46836..a7b321d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,7 +24,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':'012fd0fb022fd542fdd7606567d0c9b38ca56bd8','transitive':false])
+ build(['name':'github.com/apache/incubator-openwhisk-client-go/whisk','version':'1759868a61729708a8ab1a6de1b409d6e2aea00a','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 f834a9f..1fcec1f 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -19,12 +19,16 @@ package commands
import (
"encoding/base64"
+ "encoding/json"
"errors"
"fmt"
"io"
+ "math/rand"
"os"
"path/filepath"
+ "reflect"
"strings"
+ "time"
"github.com/apache/incubator-openwhisk-cli/wski18n"
"github.com/apache/incubator-openwhisk-client-go/whisk"
@@ -42,6 +46,7 @@ const (
WEB_EXPORT_ANNOT = "web-export"
RAW_HTTP_ANNOT = "raw-http"
FINAL_ANNOT = "final"
+ WEB_SECURE_ANNOT = "require-whisk-auth"
NODE_JS_EXT = ".js"
PYTHON_EXT = ".py"
JAVA_EXT = ".jar"
@@ -58,6 +63,8 @@ const (
SEQUENCE = "sequence"
FETCH_CODE = true
DO_NOT_FETCH_CODE = false
+ ACTION_UPDATE = true
+ ACTION_CREATE = false
)
var actionCmd = &cobra.Command{
@@ -88,6 +95,10 @@ var actionCreateCmd = &cobra.Command{
return actionParseError(cmd, args, err)
}
+ if action, err = augmentAction(cmd, args, action, ACTION_CREATE); err != nil {
+ return actionParseError(cmd, args, err)
+ }
+
if _, _, err = Client.Actions.Insert(action, false); err != nil {
return actionInsertError(action, err)
}
@@ -121,6 +132,10 @@ var actionUpdateCmd = &cobra.Command{
return actionParseError(cmd, args, err)
}
+ if action, err = augmentAction(cmd, args, action, ACTION_UPDATE); err != nil {
+ return actionParseError(cmd, args, err)
+ }
+
if _, _, err = Client.Actions.Insert(action, true); err != nil {
return actionInsertError(action, err)
}
@@ -442,14 +457,104 @@ func parseAction(cmd *cobra.Command, args []string, update bool) (*whisk.Action,
return nil, noArtifactError()
}
+ whisk.Debug(whisk.DbgInfo, "Parsed action struct: %#v\n", action)
+ return action, err
+}
+
+func augmentAction(cmd *cobra.Command, args []string, action *whisk.Action, update bool) (*whisk.Action, error) {
+ var err error
+ var existingAction *whisk.Action = nil
+ var augmentedAction *whisk.Action = new(whisk.Action)
+ *augmentedAction = *action
+
+ if update {
+ if existingAction, _, err = Client.Actions.Get(action.Name, DO_NOT_FETCH_CODE); err != nil {
+ whiskErr, isWhiskError := err.(*whisk.WskError)
+
+ if (isWhiskError && whiskErr.ExitCode != whisk.EXIT_CODE_NOT_FOUND) || !isWhiskError {
+ return nil, actionGetError(action.Name, DO_NOT_FETCH_CODE, err)
+ }
+ }
+ }
+
+ // Augment the action's annotations with the --web related annotations
+ if augmentedAction, err = augmentWebArg(cmd, args, action, augmentedAction, existingAction); err != nil {
+ return nil, err
+ }
+
+ // Augment the action's annotations with the --web-secure related annotations
+ if augmentedAction, err = augmentWebSecureArg(cmd, args, action, augmentedAction, existingAction); err != nil {
+ return nil, err
+ }
+
+ whisk.Debug(whisk.DbgInfo, "Augmented action struct: %#v\n", augmentedAction)
+ return augmentedAction, err
+}
+
+func augmentWebArg(cmd *cobra.Command, args []string, action *whisk.Action, augmentedAction *whisk.Action, existingAction *whisk.Action) (*whisk.Action, error) {
+ var err error
+ preserveAnnotations := action.Annotations == nil
+
if cmd.LocalFlags().Changed(WEB_FLAG) {
- preserveAnnotations := action.Annotations == nil
- action.Annotations, err = webAction(Flags.action.web, action.Annotations, qualifiedName.GetEntityName(), preserveAnnotations)
+ augmentedAction.Annotations, err = webAction(Flags.action.web, action.Annotations, action.Name, preserveAnnotations, existingAction)
+ if existingAction != nil && err == nil {
+ // Always carry forward any existing --web-secure annotation value
+ // Although it can be overwritten later if --web-secure is set
+ webSecureAnnotations := getWebSecureAnnotations(existingAction)
+ if len(webSecureAnnotations) > 0 {
+ augmentedAction.Annotations = augmentedAction.Annotations.AppendKeyValueArr(webSecureAnnotations)
+ }
+ }
}
- whisk.Debug(whisk.DbgInfo, "Parsed action struct: %#v\n", action)
+ if err != nil {
+ return nil, err
+ }
- return action, err
+ whisk.Debug(whisk.DbgInfo, "augmentWebArg: Augmented action struct: %#v\n", augmentedAction)
+ return augmentedAction, nil
+}
+
+/*
+ * Return a whisk.Action augmented with --web-secure annotation updates
+ * originalAction: a action constructed from command line argument
+ * action: an action constructed from command line args + possible other augmentation (i.e. --web annotations)
+ * existingAction: on an action update, this is the existing action
+ */
+func augmentWebSecureArg(cmd *cobra.Command, args []string, originalAction *whisk.Action, action *whisk.Action, existingAction *whisk.Action) (*whisk.Action, error) {
+ preserveAnnotations := action.Annotations == nil
+ var augmentedAction *whisk.Action = new(whisk.Action)
+ *augmentedAction = *action
+ disableWebAction := strings.ToLower(Flags.action.web) == "false" || strings.ToLower(Flags.action.web) == "no"
+ isWebSecureFlagValidToUse := action.WebAction() || (existingAction != nil && existingAction.WebAction() && !disableWebAction)
+
+ // Process the --web-secure flag when set
+ if cmd.LocalFlags().Changed(WEB_SECURE_FLAG) {
+ // The --web-secure option is only valid when:
+ // 1. action --web is set to either true or raw (i.e. web-export annotation is true)
+ // -OR-
+ // 2. existing action web-export annotation is true && action --web is not false/no
+ whisk.Debug(whisk.DbgInfo, "disableWebAction: %v isWebSecureFlagValidToUse: %v\n", disableWebAction, isWebSecureFlagValidToUse)
+ if !isWebSecureFlagValidToUse {
+ return nil, webSecureUsageError()
+ }
+
+ // Carry forward some or all of the existing action's annotations
+ // all -> if original command line had at least one annotation specified
+ // some -> if original command line had NO annotations, carry forward web/websecure annotation values
+ if existingAction != nil {
+ if preserveAnnotations {
+ augmentedAction.Annotations = action.Annotations.AppendKeyValueArr(existingAction.Annotations)
+ } else {
+ augmentedAction.Annotations = action.Annotations.AppendKeyValueArr(getWebActionAnnotations(existingAction))
+ augmentedAction.Annotations = augmentedAction.Annotations.AppendKeyValueArr(getWebSecureAnnotations(existingAction))
+ }
+ }
+ augmentedAction.Annotations = updateWebSecureAnnotation(Flags.action.websecure, augmentedAction.Annotations)
+ }
+
+ whisk.Debug(whisk.DbgInfo, "augmentWebSecureArg: Augmented action struct: %#v\n", augmentedAction)
+ return augmentedAction, nil
}
func getExec(args []string, params ActionFlags) (*whisk.Exec, error) {
@@ -604,18 +709,18 @@ func saveCode(action whisk.Action, filename string) (err error) {
return nil
}
-func webAction(webMode string, annotations whisk.KeyValueArr, entityName string, preserveAnnotations bool) (whisk.KeyValueArr, error) {
+func webAction(webMode string, annotations whisk.KeyValueArr, entityName string, preserveAnnotations bool, existingAction *whisk.Action) (whisk.KeyValueArr, error) {
switch strings.ToLower(webMode) {
case "yes":
fallthrough
case "true":
- return webActionAnnotations(preserveAnnotations, annotations, entityName, addWebAnnotations)
+ return webActionAnnotations(preserveAnnotations, annotations, entityName, addWebAnnotations, existingAction)
case "no":
fallthrough
case "false":
- return webActionAnnotations(preserveAnnotations, annotations, entityName, deleteWebAnnotations)
+ return webActionAnnotations(preserveAnnotations, annotations, entityName, deleteWebAnnotations, existingAction)
case "raw":
- return webActionAnnotations(preserveAnnotations, annotations, entityName, addRawAnnotations)
+ return webActionAnnotations(preserveAnnotations, annotations, entityName, addRawAnnotations, existingAction)
default:
return nil, webInputError(webMode)
}
@@ -627,20 +732,11 @@ func webActionAnnotations(
preserveAnnotations bool,
annotations whisk.KeyValueArr,
entityName string,
- webActionAnnotationMethod WebActionAnnotationMethod) (whisk.KeyValueArr, error) {
- var action *whisk.Action
- var err error
-
- if preserveAnnotations {
- if action, _, err = Client.Actions.Get(entityName, DO_NOT_FETCH_CODE); err != nil {
- whiskErr, isWhiskError := err.(*whisk.WskError)
+ webActionAnnotationMethod WebActionAnnotationMethod,
+ existingAction *whisk.Action) (whisk.KeyValueArr, error) {
- if (isWhiskError && whiskErr.ExitCode != whisk.EXIT_CODE_NOT_FOUND) || !isWhiskError {
- return nil, actionGetError(entityName, DO_NOT_FETCH_CODE, err)
- }
- } else {
- annotations = whisk.KeyValueArr.AppendKeyValueArr(annotations, action.Annotations)
- }
+ if preserveAnnotations && existingAction != nil {
+ annotations = whisk.KeyValueArr.AppendKeyValueArr(annotations, existingAction.Annotations)
}
annotations = webActionAnnotationMethod(annotations)
@@ -683,6 +779,87 @@ func deleteWebAnnotationKeys(annotations whisk.KeyValueArr) whisk.KeyValueArr {
return annotations
}
+func getWebActionAnnotations(action *whisk.Action) whisk.KeyValueArr {
+ var webKvArr = make(whisk.KeyValueArr, 3, 3)
+ var j = 0
+
+ var i = action.Annotations.FindKeyValue(WEB_EXPORT_ANNOT)
+ if i > -1 {
+ webKvArr[j] = action.Annotations[i]
+ j++
+ }
+ i = action.Annotations.FindKeyValue(RAW_HTTP_ANNOT)
+ if i > -1 {
+ webKvArr[j] = action.Annotations[i]
+ j++
+ }
+ i = action.Annotations.FindKeyValue(FINAL_ANNOT)
+ if i > -1 {
+ webKvArr[j] = action.Annotations[i]
+ j++
+ }
+ return webKvArr[0:j]
+}
+
+func getWebSecureAnnotations(action *whisk.Action) whisk.KeyValueArr {
+ var webKvArr = make(whisk.KeyValueArr, 1, 1)
+ var j = 0
+
+ var i = action.Annotations.FindKeyValue(WEB_SECURE_ANNOT)
+ if i > -1 {
+ webKvArr[j] = action.Annotations[i]
+ j++
+ }
+
+ return webKvArr[0:j]
+}
+
+/*
+ * Update the existing annotations with the web security annotation
+ * If the current web security setting and existing setting are the "same", keep the existing value
+ * -> checking for the same "--web-secure true" setting means just checking if the two values are integers
+ * If the current web security setting is "false", remove any existing setting
+ */
+func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) whisk.KeyValueArr {
+ secureSecret := webSecureSecret(websecure) // will be false when "--web-secure false"
+ existingSecret := annotations.GetValue(WEB_SECURE_ANNOT)
+ _, disableSecurity := secureSecret.(bool)
+ _, newSecretIsInt := secureSecret.(int64)
+ var existingSecretIsInt bool = false
+ if existingSecret != nil {
+ _, existingSecretIsInt = existingSecret.(json.Number)
+ }
+
+ if existingSecretIsInt && newSecretIsInt {
+ whisk.Debug(whisk.DbgInfo, "Retaining existing secret number\n")
+ } else if existingSecret != nil && disableSecurity {
+ whisk.Debug(whisk.DbgInfo, "disabling web-secure; deleting annotation: %v\n", WEB_SECURE_ANNOT)
+ annotations = deleteKey(WEB_SECURE_ANNOT, annotations)
+ } else {
+ whisk.Debug(whisk.DbgInfo, "Setting %v annotation; prior secret %v new secret %v\n",
+ WEB_SECURE_ANNOT, reflect.TypeOf(existingSecret), reflect.TypeOf(secureSecret))
+ annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: secureSecret})
+ }
+
+ return annotations
+}
+
+//
+// Generate a secret according to the --web-secure setting
+// true: return a random int64
+// false: return false, meaning no secret was returned
+// string: return the same string
+func webSecureSecret(webSecureMode string) interface{} {
+ switch strings.ToLower(webSecureMode) {
+ case "true":
+ return genWebActionSecureKey()
+ case "false":
+ return false
+ default:
+ return webSecureMode
+ }
+}
+
func getLimits(memorySet bool, logSizeSet bool, timeoutSet bool, memory int, logSize int, timeout int) *whisk.Limits {
var limits *whisk.Limits
@@ -850,6 +1027,11 @@ func webInputError(arg string) error {
return nonNestedError(errMsg)
}
+func webSecureUsageError() error {
+ errMsg := wski18n.T("The --web-secure option is only valid when the --web option is enabled.")
+ return nonNestedError(errMsg)
+}
+
func zipKindError() error {
errMsg := wski18n.T("creating an action from a .zip artifact requires specifying the action kind explicitly")
@@ -1012,8 +1194,14 @@ func printSavedActionCodeSuccess(name string) {
}))
}
+// Generate a random int64 number to be used as a web action's
+func genWebActionSecureKey() int64 {
+ r := rand.New(rand.NewSource(time.Now().Unix()))
+ return r.Int63()
+}
+
// Check if the specified action is a web-action
-func isWebAction(client *whisk.Client, qname QualifiedName) error {
+func isWebAction(client *whisk.Client, qname QualifiedName) (*whisk.Action, error) {
var err error = nil
savedNs := client.Namespace
@@ -1040,7 +1228,7 @@ func isWebAction(client *whisk.Client, qname QualifiedName) error {
client.Namespace = savedNs
- return err
+ return action, err
}
func init() {
@@ -1058,6 +1246,7 @@ func init() {
actionCreateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", nil, wski18n.T("parameter values in `KEY VALUE` format"))
actionCreateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
actionCreateCmd.Flags().StringVar(&Flags.action.web, WEB_FLAG, "", wski18n.T("treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"))
+ actionCreateCmd.Flags().StringVar(&Flags.action.websecure, WEB_SECURE_FLAG, "", wski18n.T("secure the web action. where `SECRET` is true, false, or any string. Only valid when the ACTION is a web action"))
actionUpdateCmd.Flags().BoolVar(&Flags.action.native, "native", false, wski18n.T("treat ACTION as native action (zip file provides a compatible executable to run)"))
actionUpdateCmd.Flags().StringVar(&Flags.action.docker, "docker", "", wski18n.T("use provided docker image (a path on DockerHub) to run the action"))
@@ -1073,6 +1262,7 @@ func init() {
actionUpdateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
actionUpdateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
actionUpdateCmd.Flags().StringVar(&Flags.action.web, WEB_FLAG, "", wski18n.T("treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"))
+ actionUpdateCmd.Flags().StringVar(&Flags.action.websecure, WEB_SECURE_FLAG, "", wski18n.T("secure the web action. where `SECRET` is true, false, or any string. Only valid when the ACTION is a web action"))
actionInvokeCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
actionInvokeCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
diff --git a/commands/api.go b/commands/api.go
index 468fb05..a79ab11 100644
--- a/commands/api.go
+++ b/commands/api.go
@@ -159,6 +159,8 @@ var apiCreateCmd = &cobra.Command{
var api *whisk.Api
var err error
var qname = new(QualifiedName)
+ var action *whisk.Action
+ var webactionSecret interface{}
if len(args) == 0 && Flags.api.configfile == "" {
whisk.Debug(whisk.DbgError, "No swagger file and no arguments\n")
@@ -191,12 +193,16 @@ var apiCreateCmd = &cobra.Command{
}
// Confirm that the specified action is a web-action
- err = isWebAction(Client, *qname)
+ action, err = isWebAction(Client, *qname)
if err != nil {
whisk.Debug(whisk.DbgError, "isWebAction(%v) is false: %s\n", qname, err)
whiskErr := whisk.MakeWskError(err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
return whiskErr
}
+
+ if webactionSecret = action.Annotations.GetValue(WEB_SECURE_ANNOT); webactionSecret != nil {
+ whisk.Debug(whisk.DbgInfo, "web action is secured\n")
+ }
}
apiCreateReq := new(whisk.ApiCreateRequest)
@@ -210,7 +216,12 @@ var apiCreateCmd = &cobra.Command{
return err
}
apiCreateReqOptions.ResponseType = Flags.api.resptype
- whisk.Debug(whisk.DbgInfo, "AccessToken: %s\nSpaceGuid: %s\nResponsType: %s",
+
+ if webactionSecret != nil {
+ apiCreateReq.ApiDoc.Action.SecureKey = webactionSecret
+ }
+
+ whisk.Debug(whisk.DbgInfo, "AccessToken: %s\nSpaceGuid: %s\nResponseType: %s",
apiCreateReqOptions.AccessToken, apiCreateReqOptions.SpaceGuid, apiCreateReqOptions.ResponseType)
retApi, _, err := Client.Apis.Insert(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
diff --git a/commands/flags.go b/commands/flags.go
index 7229586..223ccfe 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -26,12 +26,13 @@ import (
///////////
const (
- MEMORY_FLAG = "memory"
- LOG_SIZE_FLAG = "logsize"
- TIMEOUT_FLAG = "timeout"
- WEB_FLAG = "web"
- SAVE_FLAG = "save"
- SAVE_AS_FLAG = "save-as"
+ 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"
)
var cliDebug = os.Getenv("WSK_CLI_DEBUG") // Useful for tracing init() code
@@ -129,20 +130,21 @@ type FlagsStruct struct {
}
type ActionFlags struct {
- docker string
- native bool
- copy bool
- web 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
+ result bool
+ kind string
+ main string
+ url bool
+ save bool
+ saveAs string
}
func IsVerbose() bool {
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
index 22b8ab0..d0b31b3 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -48,8 +48,8 @@ import JsonArgsForTests._
import whisk.http.Messages
/**
- * Tests for basic CLI usage. Some of these tests require a deployed backend.
- */
+ * Tests for basic CLI usage. Some of these tests require a deployed backend.
+ */
@RunWith(classOf[JUnitRunner])
class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
@@ -58,6 +58,11 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
val usrAgentHeaderRegEx = """\bUser-Agent\b": \[\s+"OpenWhisk\-CLI/1.\d+.*"""
+ /**
+ * Append the current timestamp in ms
+ */
+ def withTimestamp(text: String) = s"$text-${System.currentTimeMillis}"
+
behavior of "Wsk CLI usage"
it should "show help and usage info" in {
@@ -89,64 +94,74 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
result.stderr should include regex ("""(?i)Run 'wsk --help' for usage""")
}
- it should "allow a 3 part Fully Qualified Name (FQN) without a leading '/'" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val guestNamespace = wsk.namespace.whois()
- val packageName = "packageName3ptFQN"
- val actionName = "actionName3ptFQN"
- val triggerName = "triggerName3ptFQN"
- val ruleName = "ruleName3ptFQN"
- val fullQualifiedName = s"${guestNamespace}/${packageName}/${actionName}"
- // Used for action and rule creation below
- assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
- pkg.create(packageName)
- }
- assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
- trigger.create(triggerName)
- }
- // Test action and rule creation where action name is 3 part FQN w/out leading slash
- assetHelper.withCleaner(wsk.action, fullQualifiedName) { (action, _) =>
- action.create(fullQualifiedName, defaultAction)
- }
- assetHelper.withCleaner(wsk.rule, ruleName) { (rule, _) =>
- rule.create(ruleName, trigger = triggerName, action = fullQualifiedName)
- }
+ it should "allow a 3 part Fully Qualified Name (FQN) without a leading '/'" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val guestNamespace = wsk.namespace.whois()
+ val packageName = "packageName3ptFQN"
+ val actionName = "actionName3ptFQN"
+ val triggerName = "triggerName3ptFQN"
+ val ruleName = "ruleName3ptFQN"
+ val fullQualifiedName = s"${guestNamespace}/${packageName}/${actionName}"
+ // Used for action and rule creation below
+ assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+ pkg.create(packageName)
+ }
+ assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+ trigger.create(triggerName)
+ }
+ // Test action and rule creation where action name is 3 part FQN w/out leading slash
+ assetHelper.withCleaner(wsk.action, fullQualifiedName) { (action, _) =>
+ action.create(fullQualifiedName, defaultAction)
+ }
+ assetHelper.withCleaner(wsk.rule, ruleName) { (rule, _) =>
+ rule.create(ruleName, trigger = triggerName, action = fullQualifiedName)
+ }
- wsk.action.invoke(fullQualifiedName).stdout should include(s"ok: invoked /$fullQualifiedName")
- wsk.action.get(fullQualifiedName).stdout should include(s"ok: got action ${packageName}/${actionName}")
+ wsk.action.invoke(fullQualifiedName).stdout should include(
+ s"ok: invoked /$fullQualifiedName")
+ wsk.action.get(fullQualifiedName).stdout should include(
+ s"ok: got action ${packageName}/${actionName}")
}
it should "include CLI user agent headers with outbound requests" in {
- val stdout = wsk.cli(Seq("action", "list", "--auth", wskprops.authKey) ++ wskprops.overrides, verbose = true).stdout
+ val stdout = wsk
+ .cli(
+ Seq("action", "list", "--auth", wskprops.authKey) ++ wskprops.overrides,
+ verbose = true)
+ .stdout
stdout should include regex (usrAgentHeaderRegEx)
}
behavior of "Wsk actions"
- it should "reject creating entities with invalid names" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- val names = Seq(
- ("", ERROR_EXIT),
- (" ", BAD_REQUEST),
- ("hi+there", BAD_REQUEST),
- ("$hola", BAD_REQUEST),
- ("dora?", BAD_REQUEST),
- ("|dora|dora?", BAD_REQUEST))
+ it should "reject creating entities with invalid names" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val names = Seq(("", ERROR_EXIT),
+ (" ", BAD_REQUEST),
+ ("hi+there", BAD_REQUEST),
+ ("$hola", BAD_REQUEST),
+ ("dora?", BAD_REQUEST),
+ ("|dora|dora?", BAD_REQUEST))
names foreach {
case (name, ec) =>
- assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
- action.create(name, defaultAction, expectedExitCode = ec)
+ assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
+ (action, _) =>
+ action.create(name, defaultAction, expectedExitCode = ec)
}
}
}
it should "reject create with missing file" in {
val name = "notfound"
- wsk.action.create("missingFile", Some(name), expectedExitCode = MISUSE_EXIT).stderr should include(
+ wsk.action
+ .create("missingFile", Some(name), expectedExitCode = MISUSE_EXIT)
+ .stderr should include(
s"File '$name' is not a valid file or it does not exist")
}
- it should "reject action update when specified file is missing" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "reject action update when specified file is missing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
// Create dummy action to update
val name = "updateMissingFile"
val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
@@ -154,128 +169,180 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
action.create(name, file)
}
// Update it with a missing file
- wsk.action.create(name, Some("notfound"), update = true, expectedExitCode = MISUSE_EXIT)
+ wsk.action.create(name,
+ Some("notfound"),
+ update = true,
+ expectedExitCode = MISUSE_EXIT)
}
- it should "reject action update for sequence with no components" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "reject action update for sequence with no components" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "updateMissingComponents"
val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
assetHelper.withCleaner(wsk.action, name) { (action, name) =>
action.create(name, file)
}
- wsk.action.create(name, None, update = true, kind = Some("sequence"), expectedExitCode = MISUSE_EXIT)
+ wsk.action.create(name,
+ None,
+ update = true,
+ kind = Some("sequence"),
+ expectedExitCode = MISUSE_EXIT)
}
- it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "actionAnnotations"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, file, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
- }
-
- val stdout = wsk.action.get(name).stdout
- assert(stdout.startsWith(s"ok: got action $name\n"))
+ it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "actionAnnotations"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ file,
+ annotations = getValidJSONTestArgInput,
+ parameters = getValidJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.action.get(name).stdout
+ assert(stdout.startsWith(s"ok: got action $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "actionAnnotAndParamParsing"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, file, annotationFile = argInput, parameterFile = argInput)
- }
-
- val stdout = wsk.action.get(name).stdout
- assert(stdout.startsWith(s"ok: got action $name\n"))
+ it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "actionAnnotAndParamParsing"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ file,
+ annotationFile = argInput,
+ parameterFile = argInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.action.get(name).stdout
+ assert(stdout.startsWith(s"ok: got action $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "actionEscapes"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, file, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
- }
-
- val stdout = wsk.action.get(name).stdout
- assert(stdout.startsWith(s"ok: got action $name\n"))
+ it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "actionEscapes"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ file,
+ parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.action.get(name).stdout
+ assert(stdout.startsWith(s"ok: got action $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "invoke an action that exits during initialization and get appropriate error" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "abort init"
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("initexit.js")))
- }
+ it should "invoke an action that exits during initialization and get appropriate error" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "abort init"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("initexit.js")))
+ }
- withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
- val response = activation.response
- response.result.get.fields("error") shouldBe Messages.abnormalInitialization.toJson
- response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
- }
+ withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+ val response = activation.response
+ response.result.get
+ .fields("error") shouldBe Messages.abnormalInitialization.toJson
+ response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.ContainerError)
+ }
}
- it should "invoke an action that hangs during initialization and get appropriate error" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "hang init"
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("initforever.js")), timeout = Some(3 seconds))
- }
+ it should "invoke an action that hangs during initialization and get appropriate error" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "hang init"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("initforever.js")),
+ timeout = Some(3 seconds))
+ }
- withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
- val response = activation.response
- response.result.get.fields("error") shouldBe Messages.timedoutActivation(3 seconds, true).toJson
- response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
- }
+ withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+ val response = activation.response
+ response.result.get.fields("error") shouldBe Messages
+ .timedoutActivation(3 seconds, true)
+ .toJson
+ response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.ApplicationError)
+ }
}
- it should "invoke an action that exits during run and get appropriate error" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "abort run"
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("runexit.js")))
- }
+ it should "invoke an action that exits during run and get appropriate error" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "abort run"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("runexit.js")))
+ }
- withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
- val response = activation.response
- response.result.get.fields("error") shouldBe Messages.abnormalRun.toJson
- response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
- }
+ withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+ val response = activation.response
+ response.result.get.fields("error") shouldBe Messages.abnormalRun.toJson
+ response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.ContainerError)
+ }
}
- it should "retrieve the last activation using --last flag" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "retrieve the last activation using --last flag" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val auth: Seq[String] = Seq("--auth", wskprops.authKey)
val includeStr = "hello, undefined!"
@@ -288,26 +355,36 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
withActivation(wsk.activation, lastInvoke) {
activation =>
val lastFlag = Seq(
- (Seq("activation", "get", "publish", "--last"), activation.activationId),
+ (Seq("activation", "get", "publish", "--last"),
+ activation.activationId),
(Seq("activation", "get", "--last"), activation.activationId),
(Seq("activation", "logs", "--last"), includeStr),
- (Seq("activation", "result", "--last"), includeStr))
-
- retry({
- lastFlag foreach {
- case (cmd, output) =>
- val stdout = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT).stdout
- stdout should include(output)
- }
- }, waitBeforeRetry = Some(500.milliseconds))
+ (Seq("activation", "result", "--last"), includeStr)
+ )
+
+ retry(
+ {
+ lastFlag foreach {
+ case (cmd, output) =>
+ val stdout = wsk
+ .cli(cmd ++ wskprops.overrides ++ auth,
+ expectedExitCode = SUCCESS_EXIT)
+ .stdout
+ stdout should include(output)
+ }
+ },
+ waitBeforeRetry = Some(500.milliseconds)
+ )
}
},
waitBeforeRetry = Some(1.second),
- N = 5)
+ N = 5
+ )
}
- it should "ensure timestamp and stream are stripped from log lines" in withAssetCleaner(wskprops) {
+ it should "ensure timestamp and stream are stripped from log lines" in withAssetCleaner(
+ wskprops) {
val name = "activationLogStripTest"
val auth: Seq[String] = Seq("--auth", wskprops.authKey)
@@ -318,7 +395,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
val cmd = Seq("activation", "logs", "--strip", activation.activationId)
- val run = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT)
+ val run = wsk.cli(cmd ++ wskprops.overrides ++ auth,
+ expectedExitCode = SUCCESS_EXIT)
run.stdout should {
be("this is stdout\nthis is stderr\n") or
be("this is stderr\nthis is stdout\n")
@@ -326,19 +404,22 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}
}
- it should "ensure keys are not omitted from activation record" in withAssetCleaner(wskprops) {
+ it should "ensure keys are not omitted from activation record" in withAssetCleaner(
+ wskprops) {
val name = "activationRecordTest"
(wp, assetHelper) =>
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("argCheck.js")))
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("argCheck.js")))
}
val run = wsk.action.invoke(name)
withActivation(wsk.activation, run) { activation =>
activation.start should be > Instant.EPOCH
activation.end should be > Instant.EPOCH
- activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.Success)
+ activation.response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.Success)
activation.response.success shouldBe true
activation.response.result shouldBe Some(JsObject())
activation.logs shouldBe Some(List())
@@ -346,67 +427,77 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}
}
- it should "write the action-path and the limits to the annotations" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "annotations"
- val memoryLimit = 512 MB
- val logLimit = 1 MB
- val timeLimit = 60 seconds
-
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(
- name,
- Some(TestCLIUtils.getTestActionFilename("helloAsync.js")),
- memory = Some(memoryLimit),
- timeout = Some(timeLimit),
- logsize = Some(logLimit))
- }
-
- val run = wsk.action.invoke(name, Map("payload" -> "this is a test".toJson))
- withActivation(wsk.activation, run) { activation =>
- activation.response.status shouldBe "success"
- val annotations = activation.annotations.get
-
- val limitsObj = JsObject(
- "key" -> JsString("limits"),
- "value" -> ActionLimits(TimeLimit(timeLimit), MemoryLimit(memoryLimit), LogLimit(logLimit)).toJson)
+ it should "write the action-path and the limits to the annotations" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "annotations"
+ val memoryLimit = 512 MB
+ val logLimit = 1 MB
+ val timeLimit = 60 seconds
- val path = annotations.find {
- _.fields("key").convertTo[String] == "path"
- }.get
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("helloAsync.js")),
+ memory = Some(memoryLimit),
+ timeout = Some(timeLimit),
+ logsize = Some(logLimit))
+ }
- path.fields("value").convertTo[String] should fullyMatch regex (s""".*/$name""")
- annotations should contain(limitsObj)
- }
+ val run = wsk.action.invoke(name, Map("payload" -> "this is a test".toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ val annotations = activation.annotations.get
+
+ val limitsObj =
+ JsObject("key" -> JsString("limits"),
+ "value" -> ActionLimits(TimeLimit(timeLimit),
+ MemoryLimit(memoryLimit),
+ LogLimit(logLimit)).toJson)
+
+ val path = annotations.find {
+ _.fields("key").convertTo[String] == "path"
+ }.get
+
+ path
+ .fields("value")
+ .convertTo[String] should fullyMatch regex (s""".*/$name""")
+ annotations should contain(limitsObj)
+ }
}
- it should "report error when creating an action with unknown kind" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val rr = assetHelper.withCleaner(wsk.action, "invalid kind", confirmDelete = false) { (action, name) =>
- action.create(
- name,
- Some(TestCLIUtils.getTestActionFilename("echo.js")),
- kind = Some("foobar"),
- expectedExitCode = BAD_REQUEST)
- }
- rr.stderr should include regex "kind 'foobar' not in Set"
+ it should "report error when creating an action with unknown kind" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val rr = assetHelper.withCleaner(wsk.action,
+ "invalid kind",
+ confirmDelete = false) { (action, name) =>
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("echo.js")),
+ kind = Some("foobar"),
+ expectedExitCode = BAD_REQUEST)
+ }
+ rr.stderr should include regex "kind 'foobar' not in Set"
}
- it should "report error when creating an action with zip but without kind" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "zipWithNoKind"
- val zippedPythonAction = Some(TestCLIUtils.getTestActionFilename("python.zip"))
- val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
- action.create(name, zippedPythonAction, expectedExitCode = ANY_ERROR_EXIT)
+ it should "report error when creating an action with zip but without kind" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "zipWithNoKind"
+ val zippedPythonAction =
+ Some(TestCLIUtils.getTestActionFilename("python.zip"))
+ val createResult =
+ assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
+ (action, _) =>
+ action.create(name,
+ zippedPythonAction,
+ expectedExitCode = ANY_ERROR_EXIT)
}
- createResult.stderr should include regex "requires specifying the action kind"
+ createResult.stderr should include regex "requires specifying the action kind"
}
it should "create, and invoke an action that utilizes an invalid docker container with appropriate error" in withAssetCleaner(
wskprops) {
val name = "invalidDockerContainer"
- val containerName = s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
+ val containerName =
+ s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
(wp, assetHelper) =>
assetHelper.withCleaner(wsk.action, name) {
@@ -417,11 +508,13 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val run = wsk.action.invoke(name)
withActivation(wsk.activation, run) { activation =>
- activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
+ activation.response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.ApplicationError)
activation.response.result.get
.fields("error") shouldBe s"Failed to pull container image '$containerName'.".toJson
activation.annotations shouldBe defined
- val limits = activation.annotations.get.filter(_.fields("key").convertTo[String] == "limits")
+ val limits = activation.annotations.get
+ .filter(_.fields("key").convertTo[String] == "limits")
withClue(limits) {
limits.length should be > 0
limits(0).fields("value") should not be JsNull
@@ -429,27 +522,37 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}
}
- it should "invoke an action using npm openwhisk" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- val name = "hello npm openwhisk"
- assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
- }
+ it should "invoke an action using npm openwhisk" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val name = "hello npm openwhisk"
+ assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
+ (action, _) =>
+ action.create(
+ name,
+ Some(
+ TestCLIUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
+ }
- val run = wsk.action.invoke(name, Map("ignore_certs" -> true.toJson, "name" -> name.toJson))
- withActivation(wsk.activation, run) { activation =>
- activation.response.status shouldBe "success"
- activation.response.result shouldBe Some(JsObject("delete" -> true.toJson))
- activation.logs.get.mkString(" ") should include("action list has this many actions")
- }
+ val run = wsk.action
+ .invoke(name, Map("ignore_certs" -> true.toJson, "name" -> name.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(
+ JsObject("delete" -> true.toJson))
+ activation.logs.get.mkString(" ") should include(
+ "action list has this many actions")
+ }
- wsk.action.delete(name, expectedExitCode = NOT_FOUND)
+ wsk.action.delete(name, expectedExitCode = NOT_FOUND)
}
- it should "invoke an action receiving context properties" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "invoke an action receiving context properties" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val namespace = wsk.namespace.whois()
val name = "context"
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("helloContext.js")))
+ action.create(name,
+ Some(TestCLIUtils.getTestActionFilename("helloContext.js")))
}
val start = Instant.now(Clock.systemUTC()).toEpochMilli
@@ -466,29 +569,33 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}
}
- it should "invoke an action successfully with options --blocking and --result" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "invokeResult"
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
- }
- val args = Map("hello" -> "Robert".toJson)
- val run = wsk.action.invoke(name, args, blocking = true, result = true)
- run.stdout.parseJson shouldBe args.toJson
+ it should "invoke an action successfully with options --blocking and --result" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "invokeResult"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
+ }
+ val args = Map("hello" -> "Robert".toJson)
+ val run = wsk.action.invoke(name, args, blocking = true, result = true)
+ run.stdout.parseJson shouldBe args.toJson
}
- it should "invoke an action that returns a result by the deadline" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "deadline"
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
- }
+ it should "invoke an action that returns a result by the deadline" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "deadline"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(
+ name,
+ Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")),
+ timeout = Some(3 seconds))
+ }
- val run = wsk.action.invoke(name)
- withActivation(wsk.activation, run) { activation =>
- activation.response.status shouldBe "success"
- activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
- }
+ val run = wsk.action.invoke(name)
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(
+ JsObject("timedout" -> true.toJson))
+ }
}
it should "invoke an action twice, where the first times out but the second does not and should succeed" in withAssetCleaner(
@@ -500,16 +607,21 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
(wp, assetHelper) =>
val name = "timeout"
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
+ action.create(
+ name,
+ Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")),
+ timeout = Some(3 seconds))
}
val start = Instant.now(Clock.systemUTC()).toEpochMilli
val hungRun = wsk.action.invoke(name, Map("forceHang" -> true.toJson))
withActivation(wsk.activation, hungRun) { activation =>
// the first action must fail with a timeout error
- activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
+ activation.response.status shouldBe ActivationResponse.messageForCode(
+ ActivationResponse.ApplicationError)
activation.response.result shouldBe Some(
- JsObject("error" -> Messages.timedoutActivation(3 seconds, false).toJson))
+ JsObject(
+ "error" -> Messages.timedoutActivation(3 seconds, false).toJson))
}
// run the action again, this time without forcing it to timeout
@@ -518,11 +630,13 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
withActivation(wsk.activation, goodRun) { activation =>
// the first action must fail with a timeout error
activation.response.status shouldBe "success"
- activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
+ activation.response.result shouldBe Some(
+ JsObject("timedout" -> true.toJson))
}
}
- it should "ensure --web flags set the proper annotations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "ensure --web flags set the proper annotations" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "webaction"
val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
@@ -530,20 +644,28 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
action.create(name, file)
}
- Seq("true", "faLse", "tRue", "nO", "yEs", "no", "raw", "NO", "Raw").foreach { flag =>
- val webEnabled = flag.toLowerCase == "true" || flag.toLowerCase == "yes"
- val rawEnabled = flag.toLowerCase == "raw"
+ Seq("true", "faLse", "tRue", "nO", "yEs", "no", "raw", "NO", "Raw")
+ .foreach { flag =>
+ val webEnabled = flag.toLowerCase == "true" || flag.toLowerCase == "yes"
+ val rawEnabled = flag.toLowerCase == "raw"
- wsk.action.create(name, file, web = Some(flag), update = true)
+ wsk.action.create(name, file, web = Some(flag), update = true)
- val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
- assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
- removeCLIHeader(stdout).parseJson shouldBe JsArray(
- JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")),
- JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(webEnabled || rawEnabled)),
- JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(rawEnabled)),
- JsObject("key" -> JsString("final"), "value" -> JsBoolean(webEnabled || rawEnabled)))
- }
+ val stdout =
+ wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ assert(
+ stdout.startsWith(
+ s"ok: got action $name, displaying field annotations\n"))
+ removeCLIHeader(stdout).parseJson shouldBe JsArray(
+ JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")),
+ JsObject("key" -> JsString("web-export"),
+ "value" -> JsBoolean(webEnabled || rawEnabled)),
+ JsObject("key" -> JsString("raw-http"),
+ "value" -> JsBoolean(rawEnabled)),
+ JsObject("key" -> JsString("final"),
+ "value" -> JsBoolean(webEnabled || rawEnabled))
+ )
+ }
}
it should "ensure action update with --web flag only copies existing annotations when new annotations are not provided" in withAssetCleaner(
@@ -558,7 +680,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val origValue = JsString("origValue")
val overwrittenValue = JsString("overwrittenValue")
val createAnnots = Map(createKey -> createValue, origKey -> origValue)
- val updateAnnots = Map(updateKey -> updateValue, origKey -> overwrittenValue)
+ val updateAnnots =
+ Map(updateKey -> updateValue, origKey -> overwrittenValue)
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
action.create(name, file, annotations = createAnnots)
@@ -566,216 +689,534 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
wsk.action.create(name, file, web = Some("true"), update = true)
- val existinAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
- assert(existinAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
+ val existinAnnots =
+ wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ assert(
+ existinAnnots.startsWith(
+ s"ok: got action $name, displaying field annotations\n"))
removeCLIHeader(existinAnnots).parseJson shouldBe JsArray(
JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
JsObject("key" -> JsString(origKey), "value" -> origValue),
JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
JsObject("key" -> JsString(createKey), "value" -> createValue),
- JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
-
- wsk.action.create(name, file, web = Some("true"), update = true, annotations = updateAnnots)
-
- val updatedAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
- assert(updatedAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
+ JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6"))
+ )
+
+ wsk.action.create(name,
+ file,
+ web = Some("true"),
+ update = true,
+ annotations = updateAnnots)
+
+ val updatedAnnots =
+ wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ assert(
+ updatedAnnots.startsWith(
+ s"ok: got action $name, displaying field annotations\n"))
removeCLIHeader(updatedAnnots).parseJson shouldBe JsArray(
JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
JsObject("key" -> JsString(origKey), "value" -> overwrittenValue),
JsObject("key" -> JsString(updateKey), "value" -> updateValue),
JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
- JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+ JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6"))
+ )
}
- it should "ensure action update creates an action with --web flag" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "webaction"
- val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ it should "ensure action update creates an action with --web flag" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "webaction"
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, file, web = Some("true"), update = true)
- }
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, file, web = Some("true"), update = true)
+ }
- val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
- assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
- removeCLIHeader(stdout).parseJson shouldBe JsArray(
- JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
- JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
- JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
- JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+ val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ assert(
+ stdout.startsWith(
+ s"ok: got action $name, displaying field annotations\n"))
+ removeCLIHeader(stdout).parseJson shouldBe JsArray(
+ JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
+ JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
+ JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
+ JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6"))
+ )
}
- it should "reject action create and update with invalid web flag input" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "webaction"
- val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
- val invalidInput = "bogus"
- val errorMsg =
- s"Invalid argument '$invalidInput' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
- wsk.action.create(name, file, web = Some(invalidInput), expectedExitCode = MISUSE_EXIT).stderr should include(
- errorMsg)
- wsk.action
- .create(name, file, web = Some(invalidInput), update = true, expectedExitCode = MISUSE_EXIT)
- .stderr should include(errorMsg)
+ it should "reject action create and update with invalid --web flag input" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "webaction"
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ val invalidInput = "bogus"
+ val errorMsg =
+ s"Invalid argument '$invalidInput' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
+ wsk.action
+ .create(name,
+ file,
+ web = Some(invalidInput),
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include(errorMsg)
+ wsk.action
+ .create(name,
+ file,
+ web = Some(invalidInput),
+ update = true,
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include(errorMsg)
}
- it should "invoke action while not encoding &, <, > characters" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- val name = "nonescape"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val nonescape = "&<>"
- val input = Map("payload" -> nonescape.toJson)
- val output = JsObject("payload" -> JsString(s"hello, $nonescape!"))
+ it should "reject action create and update when --web-secure used on a non-web action" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = withTimestamp("nonwebaction")
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ val errorMsg =
+ s"The --web-secure option is only valid when the --web option is enabled."
+ // Create non-web action with --web-secure option -> fail
+ wsk.action
+ .create(name,
+ file,
+ websecure = Some("true"),
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include(errorMsg)
+
+ // Updating a existing non-web action should not allow the --web-secure option
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
action.create(name, file)
}
+ wsk.action
+ .create(name,
+ file,
+ websecure = Some("true"),
+ update = true,
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include(errorMsg)
- withActivation(wsk.activation, wsk.action.invoke(name, parameters = input)) { activation =>
- activation.response.success shouldBe true
- activation.response.result shouldBe Some(output)
- activation.logs.toList.flatten.filter(_.contains(nonescape)).length shouldBe 1
- }
+ // Updating an existing web action with --web false should not allow the --web-secure option
+ wsk.action.create(name, file, web = Some("true"), update = true)
+ wsk.action
+ .create(name,
+ file,
+ web = Some("false"),
+ websecure = Some("true"),
+ update = true,
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include(errorMsg)
}
- it should "get an action URL" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- val actionName = "action name@_-."
- val packageName = "package name@_-."
- val defaultPackageName = "default"
- val webActionName = "web action name@_-."
- val nonExistentActionName = "non-existence action"
- val packagedAction = s"$packageName/$actionName"
- val packagedWebAction = s"$packageName/$webActionName"
- val namespace = wsk.namespace.whois()
- val encodedActionName = URLEncoder.encode(actionName, StandardCharsets.UTF_8.name).replace("+", "%20")
- val encodedPackageName = URLEncoder.encode(packageName, StandardCharsets.UTF_8.name).replace("+", "%20")
- val encodedWebActionName = URLEncoder.encode(webActionName, StandardCharsets.UTF_8.name).replace("+", "%20")
- val encodedNamespace = URLEncoder.encode(namespace, StandardCharsets.UTF_8.name).replace("+", "%20")
- val scheme = "https"
- val actionPath = "%s://%s/api/%s/namespaces/%s/actions/%s"
- val packagedActionPath = s"$actionPath/%s"
- val webActionPath = "%s://%s/api/%s/web/%s/%s/%s"
+ it should "generate a require-whisk-annotation --web-secure used on a web action" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = withTimestamp("webaction")
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ val secretStr = "my-secret"
- assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
- action.create(actionName, defaultAction)
+ // -web true --web-secure true -> annotation "require-whisk-auth" value is an int
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, file, web = Some("true"), websecure = Some("true"))
}
+ var stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ var secretJsVar = removeCLIHeader(stdout).parseJson
+ .convertTo[JsArray]
+ .elements
+ .find({
+ _.convertTo[JsObject].getFields("key").head == JsString(
+ "require-whisk-auth")
+ })
+ var secretIsInt =
+ secretJsVar.get.convertTo[JsObject].getFields("value").head match {
+ case JsNumber(x) => true
+ case _ => false
+ }
+ secretIsInt shouldBe true
+
+ // -web true --web-secure string -> annotation "require-whisk-auth" with a value of string
+ wsk.action.create(name,
+ file,
+ web = Some("true"),
+ websecure = Some(s"$secretStr"),
+ update = true)
+ stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ val actualAnnotations =
+ removeCLIHeader(stdout).parseJson.convertTo[JsArray].elements
+ actualAnnotations.contains(JsObject(
+ "key" -> JsString("exec"),
+ "value" -> JsString("nodejs:6"))) shouldBe true
+ actualAnnotations.contains(JsObject(
+ "key" -> JsString("web-export"),
+ "value" -> JsBoolean(true))) shouldBe true
+ actualAnnotations.contains(JsObject(
+ "key" -> JsString("raw-http"),
+ "value" -> JsBoolean(false))) shouldBe true
+ actualAnnotations.contains(JsObject(
+ "key" -> JsString("final"),
+ "value" -> JsBoolean(true))) shouldBe true
+ actualAnnotations.contains(
+ JsObject("key" -> JsString("require-whisk-auth"),
+ "value" -> JsString(s"$secretStr"))) shouldBe true
+
+ // Updating web action multiple times with --web-secure true should not change the "require-whisk-auth" numeric value
+ wsk.action.create(name,
+ file,
+ web = Some("true"),
+ websecure = Some("true"),
+ update = true)
+ stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ val secretNumJsVar = removeCLIHeader(stdout).parseJson
+ .convertTo[JsArray]
+ .elements
+ .find({
+ _.convertTo[JsObject].getFields("key").head == JsString(
+ "require-whisk-auth")
+ })
+ wsk.action.create(name,
+ file,
+ web = Some("true"),
+ websecure = Some("true"),
+ update = true)
+ removeCLIHeader(stdout).parseJson
+ .convertTo[JsArray]
+ .elements
+ .find({
+ _.convertTo[JsObject].getFields("key").head == JsString(
+ "require-whisk-auth")
+ }) shouldBe secretNumJsVar
+ }
+
+ it should "remove existing require-whisk-annotation when --web-secure is false" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = withTimestamp("webaction")
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ val secretStr = "my-secret"
- assetHelper.withCleaner(wsk.action, webActionName) { (action, _) =>
- action.create(webActionName, defaultAction, web = Some("true"))
+ //
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
+ file,
+ web = Some("true"),
+ websecure = Some(s"$secretStr"))
}
+ var stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ var actualAnnotations =
+ removeCLIHeader(stdout).parseJson.convertTo[JsArray].elements
+ actualAnnotations.contains(
+ JsObject("key" -> JsString("require-whisk-auth"),
+ "value" -> JsString(s"$secretStr"))) shouldBe true
+
+ wsk.action.create(name,
+ file,
+ web = Some("true"),
+ websecure = Some("false"),
+ update = true)
+ stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ actualAnnotations =
+ removeCLIHeader(stdout).parseJson.convertTo[JsArray].elements
+ actualAnnotations.find({
+ _.convertTo[JsObject].getFields("key").head == JsString(
+ "require-whisk-auth")
+ }) shouldBe None
+ }
+
+ it should "ensure action update with --web-secure flag only copies existing annotations when new annotations are not provided" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "webaction"
+ val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
+ val createKey = "createKey"
+ val createValue = JsString("createValue")
+ val updateKey = "updateKey"
+ val updateValue = JsString("updateValue")
+ val origKey = "origKey"
+ val origValue = JsString("origValue")
+ val overwrittenValue = JsString("overwrittenValue")
+ val createAnnots = Map(createKey -> createValue, origKey -> origValue)
+ val updateAnnots =
+ Map(updateKey -> updateValue, origKey -> overwrittenValue)
+ val secretStr = "my-secret"
- assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
- pkg.create(packageName)
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, file, web = Some("true"), annotations = createAnnots)
}
- assetHelper.withCleaner(wsk.action, packagedAction) { (action, _) =>
- action.create(packagedAction, defaultAction)
- }
+ wsk.action.create(name, file, websecure = Some(secretStr), update = true)
+ var stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ var existingAnnotations =
+ removeCLIHeader(stdout).parseJson.convertTo[JsArray].elements
+ println("existingAnnotations: " + existingAnnotations)
+ existingAnnotations.contains(JsObject(
+ "key" -> JsString("exec"),
+ "value" -> JsString("nodejs:6"))) shouldBe true
+ existingAnnotations.contains(JsObject(
+ "key" -> JsString("web-export"),
+ "value" -> JsBoolean(true))) shouldBe true
+ existingAnnotations.contains(JsObject(
+ "key" -> JsString("raw-http"),
+ "value" -> JsBoolean(false))) shouldBe true
+ existingAnnotations.contains(JsObject(
+ "key" -> JsString("final"),
+ "value" -> JsBoolean(true))) shouldBe true
+ existingAnnotations.contains(
+ JsObject("key" -> JsString("require-whisk-auth"),
+ "value" -> JsString(secretStr))) shouldBe true
+ existingAnnotations.contains(JsObject("key" -> JsString(createKey),
+ "value" -> createValue)) shouldBe true
+ existingAnnotations.contains(
+ JsObject("key" -> JsString(origKey), "value" -> origValue)) shouldBe true
+
+ wsk.action.create(name,
+ file,
+ websecure = Some(secretStr),
+ update = true,
+ annotations = updateAnnots)
+ stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+ var updatedAnnotations =
+ removeCLIHeader(stdout).parseJson.convertTo[JsArray].elements
+ println("updatedAnnotations: " + updatedAnnotations)
+ updatedAnnotations.contains(JsObject(
+ "key" -> JsString("exec"),
+ "value" -> JsString("nodejs:6"))) shouldBe true
+ updatedAnnotations.contains(JsObject(
+ "key" -> JsString("web-export"),
+ "value" -> JsBoolean(true))) shouldBe true
+ updatedAnnotations.contains(JsObject(
+ "key" -> JsString("raw-http"),
+ "value" -> JsBoolean(false))) shouldBe true
+ updatedAnnotations.contains(JsObject(
+ "key" -> JsString("final"),
+ "value" -> JsBoolean(true))) shouldBe true
+ updatedAnnotations.contains(
+ JsObject("key" -> JsString("require-whisk-auth"),
+ "value" -> JsString(secretStr))) shouldBe true
+ updatedAnnotations.contains(JsObject("key" -> JsString(updateKey),
+ "value" -> updateValue)) shouldBe true
+ updatedAnnotations.contains(JsObject(
+ "key" -> JsString(origKey),
+ "value" -> overwrittenValue)) shouldBe true
+ }
+
+ it should "invoke action while not encoding &, <, > characters" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "nonescape"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+ val nonescape = "&<>"
+ val input = Map("payload" -> nonescape.toJson)
+ val output = JsObject("payload" -> JsString(s"hello, $nonescape!"))
- assetHelper.withCleaner(wsk.action, packagedWebAction) { (action, _) =>
- action.create(packagedWebAction, defaultAction, web = Some("true"))
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, file)
}
- wsk.action.get(actionName, url = Some(true)).stdout should include(
- actionPath.format(scheme, wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+ withActivation(wsk.activation, wsk.action.invoke(name, parameters = input)) {
+ activation =>
+ activation.response.success shouldBe true
+ activation.response.result shouldBe Some(output)
+ activation.logs.toList.flatten
+ .filter(_.contains(nonescape))
+ .length shouldBe 1
+ }
+ }
- // Ensure url flag works when a field filter and summary flag are specified
- wsk.action.get(actionName, url = Some(true), fieldFilter = Some("field"), summary = true).stdout should include(
- actionPath.format(scheme, wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+ it should "get an action URL" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val actionName = "action name@_-."
+ val packageName = "package name@_-."
+ val defaultPackageName = "default"
+ val webActionName = "web action name@_-."
+ val nonExistentActionName = "non-existence action"
+ val packagedAction = s"$packageName/$actionName"
+ val packagedWebAction = s"$packageName/$webActionName"
+ val namespace = wsk.namespace.whois()
+ val encodedActionName = URLEncoder
+ .encode(actionName, StandardCharsets.UTF_8.name)
+ .replace("+", "%20")
+ val encodedPackageName = URLEncoder
+ .encode(packageName, StandardCharsets.UTF_8.name)
+ .replace("+", "%20")
+ val encodedWebActionName = URLEncoder
+ .encode(webActionName, StandardCharsets.UTF_8.name)
+ .replace("+", "%20")
+ val encodedNamespace = URLEncoder
+ .encode(namespace, StandardCharsets.UTF_8.name)
+ .replace("+", "%20")
+ val scheme = "https"
+ val actionPath = "%s://%s/api/%s/namespaces/%s/actions/%s"
+ val packagedActionPath = s"$actionPath/%s"
+ val webActionPath = "%s://%s/api/%s/web/%s/%s/%s"
+
+ assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
+ action.create(actionName, defaultAction)
+ }
- wsk.action.get(webActionName, url = Some(true)).stdout should include(
- webActionPath
- .format(
- scheme,
- wskprops.apihost,
- wskprops.apiversion,
- encodedNamespace,
- defaultPackageName,
- encodedWebActionName))
+ assetHelper.withCleaner(wsk.action, webActionName) { (action, _) =>
+ action.create(webActionName, defaultAction, web = Some("true"))
+ }
- wsk.action.get(packagedAction, url = Some(true)).stdout should include(
- packagedActionPath
- .format(scheme, wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedActionName))
+ assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+ pkg.create(packageName)
+ }
- wsk.action.get(packagedWebAction, url = Some(true)).stdout should include(
- webActionPath
- .format(
- scheme,
- wskprops.apihost,
- wskprops.apiversion,
- encodedNamespace,
- encodedPackageName,
- encodedWebActionName))
+ assetHelper.withCleaner(wsk.action, packagedAction) { (action, _) =>
+ action.create(packagedAction, defaultAction)
+ }
- wsk.action.get(nonExistentActionName, url = Some(true), expectedExitCode = NOT_FOUND)
+ assetHelper.withCleaner(wsk.action, packagedWebAction) { (action, _) =>
+ action.create(packagedWebAction, defaultAction, web = Some("true"))
+ }
- val httpsProps = WskProps(apihost = "https://" + wskprops.apihost)
- wsk.action.get(actionName, url = Some(true))(httpsProps).stdout should include(
- actionPath
- .format("https", wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
- wsk.action.get(webActionName, url = Some(true))(httpsProps).stdout should include(
- webActionPath
- .format(
- "https",
- wskprops.apihost,
- wskprops.apiversion,
- encodedNamespace,
- defaultPackageName,
- encodedWebActionName))
+ wsk.action.get(actionName, url = Some(true)).stdout should include(
+ actionPath.format(scheme,
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ encodedActionName))
- }
- it should "limit length of HTTP request and response bodies for --verbose" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "limitVerbose"
- val msg = "will be truncated"
- val params = Seq("-p", "bigValue", "a" * 1000)
+ // Ensure url flag works when a field filter and summary flag are specified
+ wsk.action
+ .get(actionName,
+ url = Some(true),
+ fieldFilter = Some("field"),
+ summary = true)
+ .stdout should include(
+ actionPath.format(scheme,
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ encodedActionName))
+
+ wsk.action.get(webActionName, url = Some(true)).stdout should include(
+ webActionPath
+ .format(scheme,
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ defaultPackageName,
+ encodedWebActionName))
+
+ wsk.action.get(packagedAction, url = Some(true)).stdout should include(
+ packagedActionPath
+ .format(scheme,
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ encodedPackageName,
+ encodedActionName))
+
+ wsk.action.get(packagedWebAction, url = Some(true)).stdout should include(
+ webActionPath
+ .format(scheme,
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ encodedPackageName,
+ encodedWebActionName))
+
+ wsk.action.get(nonExistentActionName,
+ url = Some(true),
+ expectedExitCode = NOT_FOUND)
+
+ val httpsProps = WskProps(apihost = "https://" + wskprops.apihost)
+ wsk.action
+ .get(actionName, url = Some(true))(httpsProps)
+ .stdout should include(
+ actionPath
+ .format("https",
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ encodedActionName))
+ wsk.action
+ .get(webActionName, url = Some(true))(httpsProps)
+ .stdout should include(
+ webActionPath
+ .format("https",
+ wskprops.apihost,
+ wskprops.apiversion,
+ encodedNamespace,
+ defaultPackageName,
+ encodedWebActionName))
+
+ }
+ it should "limit length of HTTP request and response bodies for --verbose" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "limitVerbose"
+ val msg = "will be truncated"
+ val params = Seq("-p", "bigValue", "a" * 1000)
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
- }
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
+ }
- val truncated = wsk
- .cli(Seq("action", "invoke", name, "-b", "-v", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides)
+ val truncated =
+ wsk
+ .cli(Seq("action",
+ "invoke",
+ name,
+ "-b",
+ "-v",
+ "--auth",
+ wskprops.authKey) ++ params ++ wskprops.overrides)
.stdout
- msg.r.findAllIn(truncated).length shouldBe 2
-
- val notTruncated = wsk
- .cli(Seq("action", "invoke", name, "-b", "-d", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides)
+ msg.r.findAllIn(truncated).length shouldBe 2
+
+ val notTruncated =
+ wsk
+ .cli(Seq("action",
+ "invoke",
+ name,
+ "-b",
+ "-d",
+ "--auth",
+ wskprops.authKey) ++ params ++ wskprops.overrides)
.stdout
- msg.r.findAllIn(notTruncated).length shouldBe 0
+ msg.r.findAllIn(notTruncated).length shouldBe 0
}
- it should "denote bound and finalized action parameters for action summaries" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val nameBoundParams = "actionBoundParams"
- val nameFinalParams = "actionFinalParams"
- val paramAnnot = "paramAnnot"
- val paramOverlap = "paramOverlap"
- val paramBound = "paramBound"
- val annots = Map(
- "parameters" -> JsArray(
- JsObject("name" -> JsString(paramAnnot), "description" -> JsString("Annotated")),
- JsObject("name" -> JsString(paramOverlap), "description" -> JsString("Annotated And Bound"))))
- val annotsFinal = Map(
- "final" -> JsBoolean(true),
- "parameters" -> JsArray(
- JsObject("name" -> JsString(paramAnnot), "description" -> JsString("Annotated Parameter description")),
- JsObject("name" -> JsString(paramOverlap), "description" -> JsString("Annotated And Bound"))))
- val paramsBound = Map(paramBound -> JsString("Bound"), paramOverlap -> JsString("Bound And Annotated"))
-
- assetHelper.withCleaner(wsk.action, nameBoundParams) { (action, _) =>
- action.create(nameBoundParams, defaultAction, annotations = annots, parameters = paramsBound)
- }
- assetHelper.withCleaner(wsk.action, nameFinalParams) { (action, _) =>
- action.create(nameFinalParams, defaultAction, annotations = annotsFinal, parameters = paramsBound)
- }
+ it should "denote bound and finalized action parameters for action summaries" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val nameBoundParams = "actionBoundParams"
+ val nameFinalParams = "actionFinalParams"
+ val paramAnnot = "paramAnnot"
+ val paramOverlap = "paramOverlap"
+ val paramBound = "paramBound"
+ val annots = Map(
+ "parameters" -> JsArray(
+ JsObject("name" -> JsString(paramAnnot),
+ "description" -> JsString("Annotated")),
+ JsObject("name" -> JsString(paramOverlap),
+ "description" -> JsString("Annotated And Bound"))
+ ))
+ val annotsFinal = Map(
+ "final" -> JsBoolean(true),
+ "parameters" -> JsArray(
+ JsObject("name" -> JsString(paramAnnot),
+ "description" -> JsString("Annotated Parameter description")),
+ JsObject("name" -> JsString(paramOverlap),
+ "description" -> JsString("Annotated And Bound"))
+ )
+ )
+ val paramsBound = Map(paramBound -> JsString("Bound"),
+ paramOverlap -> JsString("Bound And Annotated"))
+
+ assetHelper.withCleaner(wsk.action, nameBoundParams) { (action, _) =>
+ action.create(nameBoundParams,
+ defaultAction,
+ annotations = annots,
+ parameters = paramsBound)
+ }
+ assetHelper.withCleaner(wsk.action, nameFinalParams) { (action, _) =>
+ action.create(nameFinalParams,
+ defaultAction,
+ annotations = annotsFinal,
+ parameters = paramsBound)
+ }
- val stdoutBound = wsk.action.get(nameBoundParams, summary = true).stdout
- val stdoutFinal = wsk.action.get(nameFinalParams, summary = true).stdout
+ val stdoutBound = wsk.action.get(nameBoundParams, summary = true).stdout
+ val stdoutFinal = wsk.action.get(nameFinalParams, summary = true).stdout
- stdoutBound should include(s"(parameters: $paramAnnot, *$paramBound, *$paramOverlap)")
- stdoutFinal should include(s"(parameters: $paramAnnot, **$paramBound, **$paramOverlap)")
+ stdoutBound should include(
+ s"(parameters: $paramAnnot, *$paramBound, *$paramOverlap)")
+ stdoutFinal should include(
+ s"(parameters: $paramAnnot, **$paramBound, **$paramOverlap)")
}
it should "create, and get an action summary without a description and/or defined parameters" in withAssetCleaner(
@@ -788,14 +1229,19 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val annotsNoParams = Map("description" -> JsString(desc))
val annotsNoDesc = Map(
"parameters" -> JsArray(
- JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
- JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+ JsObject("name" -> JsString("paramName1"),
+ "description" -> JsString("Parameter description 1")),
+ JsObject("name" -> JsString("paramName2"),
+ "description" -> JsString("Parameter description 2"))
+ ))
assetHelper.withCleaner(wsk.action, actNameNoDesc) { (action, _) =>
action.create(actNameNoDesc, defaultAction, annotations = annotsNoDesc)
}
assetHelper.withCleaner(wsk.action, actNameNoParams) { (action, _) =>
- action.create(actNameNoParams, defaultAction, annotations = annotsNoParams)
+ action.create(actNameNoParams,
+ defaultAction,
+ annotations = annotsNoParams)
}
assetHelper.withCleaner(wsk.action, actNameNoDescOrParams) { (action, _) =>
action.create(actNameNoDescOrParams, defaultAction)
@@ -803,7 +1249,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val stdoutNoDesc = wsk.action.get(actNameNoDesc, summary = true).stdout
val stdoutNoParams = wsk.action.get(actNameNoParams, summary = true).stdout
- val stdoutNoDescOrParams = wsk.action.get(actNameNoDescOrParams, summary = true).stdout
+ val stdoutNoDescOrParams =
+ wsk.action.get(actNameNoDescOrParams, summary = true).stdout
val namespace = wsk.namespace.whois()
stdoutNoDesc should include regex (s"(?i)action /${namespace}/${actNameNoDesc}: ${descFromParamsResp} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
@@ -811,79 +1258,90 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
stdoutNoDescOrParams should include regex (s"(?i)action /${namespace}/${actNameNoDescOrParams}\\s*\\(parameters: none defined\\)")
}
- it should "save action code to file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- val name = "saveAction"
- val seqName = "seqName"
- val dockerName = "dockerName"
- val containerName = s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
- val saveName = s"save-as-$name.js"
- val badSaveName = s"bad-directory${File.separator}$saveName"
+ it should "save action code to file" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val name = "saveAction"
+ val seqName = "seqName"
+ val dockerName = "dockerName"
+ val containerName =
+ s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
+ val saveName = s"save-as-$name.js"
+ val badSaveName = s"bad-directory${File.separator}$saveName"
+
+ // Test for successful --save
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, defaultAction)
+ }
- // Test for successful --save
- assetHelper.withCleaner(wsk.action, name) { (action, _) =>
- action.create(name, defaultAction)
- }
+ val saveMsg = wsk.action.get(name, save = Some(true)).stdout
- val saveMsg = wsk.action.get(name, save = Some(true)).stdout
+ saveMsg should include(s"saved action code to ")
- saveMsg should include(s"saved action code to ")
+ val savePath = saveMsg.split("ok: saved action code to ")(1).trim()
+ val saveFile = new File(savePath);
- val savePath = saveMsg.split("ok: saved action code to ")(1).trim()
- val saveFile = new File(savePath);
+ try {
+ saveFile.exists shouldBe true
- try {
- saveFile.exists shouldBe true
+ // Test for failure saving file when it already exist
+ wsk.action
+ .get(name, save = Some(true), expectedExitCode = MISUSE_EXIT)
+ .stderr should include(s"The file '$name.js' already exists")
+ } finally {
+ saveFile.delete()
+ }
- // Test for failure saving file when it already exist
- wsk.action.get(name, save = Some(true), expectedExitCode = MISUSE_EXIT).stderr should include(
- s"The file '$name.js' already exists")
- } finally {
- saveFile.delete()
- }
+ // Test for successful --save-as
+ val saveAsMsg = wsk.action.get(name, saveAs = Some(saveName)).stdout
- // Test for successful --save-as
- val saveAsMsg = wsk.action.get(name, saveAs = Some(saveName)).stdout
+ saveAsMsg should include(s"saved action code to ")
- saveAsMsg should include(s"saved action code to ")
+ val saveAsPath = saveAsMsg.split("ok: saved action code to ")(1).trim()
+ val saveAsFile = new File(saveAsPath);
- val saveAsPath = saveAsMsg.split("ok: saved action code to ")(1).trim()
- val saveAsFile = new File(saveAsPath);
+ try {
+ saveAsFile.exists shouldBe true
- try {
- saveAsFile.exists shouldBe true
-
- // Test for failure saving file when it already exist
- wsk.action.get(name, saveAs = Some(saveName), expectedExitCode = MISUSE_EXIT).stderr should include(
- s"The file '$saveName' already exists")
- } finally {
- saveAsFile.delete()
- }
+ // Test for failure saving file when it already exist
+ wsk.action
+ .get(name, saveAs = Some(saveName), expectedExitCode = MISUSE_EXIT)
+ .stderr should include(s"The file '$saveName' already exists")
+ } finally {
+ saveAsFile.delete()
+ }
- // Test for failure when using an invalid filename
- wsk.action.get(name, saveAs = Some(badSaveName), expectedExitCode = MISUSE_EXIT).stderr should include(
- s"Cannot create file '$badSaveName'")
+ // Test for failure when using an invalid filename
+ wsk.action
+ .get(name, saveAs = Some(badSaveName), expectedExitCode = MISUSE_EXIT)
+ .stderr should include(s"Cannot create file '$badSaveName'")
- // Test for failure saving Docker images
- assetHelper.withCleaner(wsk.action, dockerName) { (action, _) =>
- action.create(dockerName, None, docker = Some(containerName))
- }
+ // Test for failure saving Docker images
+ assetHelper.withCleaner(wsk.action, dockerName) { (action, _) =>
+ action.create(dockerName, None, docker = Some(containerName))
+ }
- wsk.action.get(dockerName, save = Some(true), expectedExitCode = MISUSE_EXIT).stderr should include(
- "Cannot save Docker images")
+ wsk.action
+ .get(dockerName, save = Some(true), expectedExitCode = MISUSE_EXIT)
+ .stderr should include("Cannot save Docker images")
- wsk.action.get(dockerName, saveAs = Some(dockerName), expectedExitCode = MISUSE_EXIT).stderr should include(
- "Cannot save Docker images")
+ wsk.action
+ .get(dockerName,
+ saveAs = Some(dockerName),
+ expectedExitCode = MISUSE_EXIT)
+ .stderr should include("Cannot save Docker images")
- // Tes for failure saving sequences
- assetHelper.withCleaner(wsk.action, seqName) { (action, _) =>
- action.create(seqName, Some(name), kind = Some("sequence"))
- }
+ // Tes for failure saving sequences
+ assetHelper.withCleaner(wsk.action, seqName) { (action, _) =>
+ action.create(seqName, Some(name), kind = Some("sequence"))
+ }
- wsk.action.get(seqName, save = Some(true), expectedExitCode = MISUSE_EXIT).stderr should include(
- "Cannot save action sequences")
+ wsk.action
+ .get(seqName, save = Some(true), expectedExitCode = MISUSE_EXIT)
+ .stderr should include("Cannot save action sequences")
- wsk.action.get(seqName, saveAs = Some(seqName), expectedExitCode = MISUSE_EXIT).stderr should include(
- "Cannot save action sequences")
+ wsk.action
+ .get(seqName, saveAs = Some(seqName), expectedExitCode = MISUSE_EXIT)
+ .stderr should include("Cannot save action sequences")
}
behavior of "Wsk packages"
@@ -894,232 +1352,315 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
wsk.pkg.delete(name).stdout should include(s"ok: deleted package $name")
}
- it should "create, and get a package to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "packageAnnotAndParamParsing"
-
- assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
- pkg.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
- }
-
- val stdout = wsk.pkg.get(name).stdout
- assert(stdout.startsWith(s"ok: got package $name\n"))
+ it should "create, and get a package to verify parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "packageAnnotAndParamParsing"
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+ pkg.create(name,
+ annotations = getValidJSONTestArgInput,
+ parameters = getValidJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.pkg.get(name).stdout
+ assert(stdout.startsWith(s"ok: got package $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "packageAnnotAndParamFileParsing"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
- assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
- pkg.create(name, annotationFile = argInput, parameterFile = argInput)
- }
-
- val stdout = wsk.pkg.get(name).stdout
- assert(stdout.startsWith(s"ok: got package $name\n"))
+ it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "packageAnnotAndParamFileParsing"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+ pkg.create(name, annotationFile = argInput, parameterFile = argInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.pkg.get(name).stdout
+ assert(stdout.startsWith(s"ok: got package $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create a package with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "packageEscapses"
-
- assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
- pkg.create(name, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
- }
-
- val stdout = wsk.pkg.get(name).stdout
- assert(stdout.startsWith(s"ok: got package $name\n"))
+ it should "create a package with the proper parameter and annotation escapes" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "packageEscapses"
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+ pkg.create(name,
+ parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.pkg.get(name).stdout
+ assert(stdout.startsWith(s"ok: got package $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "report conformance error accessing action as package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "report conformance error accessing action as package" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "aAsP"
val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
action.create(name, file)
}
- wsk.pkg.get(name, expectedExitCode = CONFLICT).stderr should include(Messages.conformanceMessage)
+ wsk.pkg.get(name, expectedExitCode = CONFLICT).stderr should include(
+ Messages.conformanceMessage)
- wsk.pkg.bind(name, "bogus", expectedExitCode = CONFLICT).stderr should include(Messages.requestedBindingIsNotValid)
+ wsk.pkg
+ .bind(name, "bogus", expectedExitCode = CONFLICT)
+ .stderr should include(Messages.requestedBindingIsNotValid)
- wsk.pkg.bind("bogus", "alsobogus", expectedExitCode = BAD_REQUEST).stderr should include(
- Messages.bindingDoesNotExist)
+ wsk.pkg
+ .bind("bogus", "alsobogus", expectedExitCode = BAD_REQUEST)
+ .stderr should include(Messages.bindingDoesNotExist)
}
- it should "create, and get a package summary without a description and/or parameters" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val pkgNoDesc = "pkgNoDesc"
- val pkgNoParams = "pkgNoParams"
- val pkgNoDescOrParams = "pkgNoDescOrParams"
- val pkgDesc = "Package description"
- val descFromParams = "Returns a result based on parameters"
- val namespace = wsk.namespace.whois()
- val qualpkgNoDesc = s"/${namespace}/${pkgNoDesc}"
- val qualpkgNoParams = s"/${namespace}/${pkgNoParams}"
- val qualpkgNoDescOrParams = s"/${namespace}/${pkgNoDescOrParams}"
-
- val pkgAnnotsNoParams = Map("description" -> JsString(pkgDesc))
- val pkgAnnotsNoDesc = Map(
- "parameters" -> JsArray(
- JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
- JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
-
- assetHelper.withCleaner(wsk.pkg, pkgNoDesc) { (pkg, _) =>
- pkg.create(pkgNoDesc, annotations = pkgAnnotsNoDesc)
- }
- assetHelper.withCleaner(wsk.pkg, pkgNoParams) { (pkg, _) =>
- pkg.create(pkgNoParams, annotations = pkgAnnotsNoParams)
- }
- assetHelper.withCleaner(wsk.pkg, pkgNoDescOrParams) { (pkg, _) =>
- pkg.create(pkgNoDescOrParams)
- }
+ it should "create, and get a package summary without a description and/or parameters" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val pkgNoDesc = "pkgNoDesc"
+ val pkgNoParams = "pkgNoParams"
+ val pkgNoDescOrParams = "pkgNoDescOrParams"
+ val pkgDesc = "Package description"
+ val descFromParams = "Returns a result based on parameters"
+ val namespace = wsk.namespace.whois()
+ val qualpkgNoDesc = s"/${namespace}/${pkgNoDesc}"
+ val qualpkgNoParams = s"/${namespace}/${pkgNoParams}"
+ val qualpkgNoDescOrParams = s"/${namespace}/${pkgNoDescOrParams}"
+
+ val pkgAnnotsNoParams = Map("description" -> JsString(pkgDesc))
+ val pkgAnnotsNoDesc = Map(
+ "parameters" -> JsArray(
+ JsObject("name" -> JsString("paramName1"),
+ "description" -> JsString("Parameter description 1")),
+ JsObject("name" -> JsString("paramName2"),
+ "description" -> JsString("Parameter description 2"))
+ ))
+
+ assetHelper.withCleaner(wsk.pkg, pkgNoDesc) { (pkg, _) =>
+ pkg.create(pkgNoDesc, annotations = pkgAnnotsNoDesc)
+ }
+ assetHelper.withCleaner(wsk.pkg, pkgNoParams) { (pkg, _) =>
+ pkg.create(pkgNoParams, annotations = pkgAnnotsNoParams)
+ }
+ assetHelper.withCleaner(wsk.pkg, pkgNoDescOrParams) { (pkg, _) =>
+ pkg.create(pkgNoDescOrParams)
+ }
- val stdoutNoDescPkg = wsk.pkg.get(pkgNoDesc, summary = true).stdout
- val stdoutNoParamsPkg = wsk.pkg.get(pkgNoParams, summary = true).stdout
- val stdoutNoDescOrParams = wsk.pkg.get(pkgNoDescOrParams, summary = true).stdout
+ val stdoutNoDescPkg = wsk.pkg.get(pkgNoDesc, summary = true).stdout
+ val stdoutNoParamsPkg = wsk.pkg.get(pkgNoParams, summary = true).stdout
+ val stdoutNoDescOrParams =
+ wsk.pkg.get(pkgNoDescOrParams, summary = true).stdout
- stdoutNoDescPkg should include regex (s"(?i)package ${qualpkgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
- stdoutNoParamsPkg should include regex (s"(?i)package ${qualpkgNoParams}: ${pkgDesc}\\s*\\(parameters: none defined\\)")
- stdoutNoDescOrParams should include regex (s"(?i)package ${qualpkgNoDescOrParams}\\s*\\(parameters: none defined\\)")
+ stdoutNoDescPkg should include regex (s"(?i)package ${qualpkgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
+ stdoutNoParamsPkg should include regex (s"(?i)package ${qualpkgNoParams}: ${pkgDesc}\\s*\\(parameters: none defined\\)")
+ stdoutNoDescOrParams should include regex (s"(?i)package ${qualpkgNoDescOrParams}\\s*\\(parameters: none defined\\)")
}
- it should "denote bound package parameters for package summaries" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "denote bound package parameters for package summaries" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val pkgBoundParams = "pkgBoundParams"
val pkgParamAnnot = "pkgParamAnnot"
val pkgParamOverlap = "pkgParamOverlap"
val pkgParamBound = "pkgParamBound"
val pkgAnnots = Map(
"parameters" -> JsArray(
- JsObject("name" -> JsString(pkgParamAnnot), "description" -> JsString("Annotated")),
- JsObject("name" -> JsString(pkgParamOverlap), "description" -> JsString("Annotated And Bound"))))
- val pkgParamsBound = Map(pkgParamBound -> JsString("Bound"), pkgParamOverlap -> JsString("Bound And Annotated"))
+ JsObject("name" -> JsString(pkgParamAnnot),
+ "description" -> JsString("Annotated")),
+ JsObject("name" -> JsString(pkgParamOverlap),
+ "description" -> JsString("Annotated And Bound"))
+ ))
+ val pkgParamsBound = Map(pkgParamBound -> JsString("Bound"),
+ pkgParamOverlap -> JsString("Bound And Annotated"))
assetHelper.withCleaner(wsk.pkg, pkgBoundParams) { (pkg, _) =>
- pkg.create(pkgBoundParams, annotations = pkgAnnots, parameters = pkgParamsBound)
+ pkg.create(pkgBoundParams,
+ annotations = pkgAnnots,
+ parameters = pkgParamsBound)
}
val pkgStdoutBound = wsk.pkg.get(pkgBoundParams, summary = true).stdout
- pkgStdoutBound should include(s"(parameters: $pkgParamAnnot, *$pkgParamBound, *$pkgParamOverlap)")
+ pkgStdoutBound should include(
+ s"(parameters: $pkgParamAnnot, *$pkgParamBound, *$pkgParamOverlap)")
}
behavior of "Wsk triggers"
- it should "create, and get a trigger to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "triggerAnnotAndParamParsing"
-
- assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
- trigger.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
- }
-
- val stdout = wsk.trigger.get(name).stdout
- assert(stdout.startsWith(s"ok: got trigger $name\n"))
+ it should "create, and get a trigger to verify parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "triggerAnnotAndParamParsing"
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+ trigger.create(name,
+ annotations = getValidJSONTestArgInput,
+ parameters = getValidJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.trigger.get(name).stdout
+ assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "triggerAnnotAndParamFileParsing"
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
- val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
- assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
- trigger.create(name, annotationFile = argInput, parameterFile = argInput)
- }
-
- val stdout = wsk.trigger.get(name).stdout
- assert(stdout.startsWith(s"ok: got trigger $name\n"))
+ it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "triggerAnnotAndParamFileParsing"
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+ trigger.create(name, annotationFile = argInput, parameterFile = argInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.trigger.get(name).stdout
+ assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "display a trigger summary when --summary flag is used with 'wsk trigger get'" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val triggerName = "mySummaryTrigger"
- assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) { (trigger, name) =>
+ it should "display a trigger summary when --summary flag is used with 'wsk trigger get'" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val triggerName = "mySummaryTrigger"
+ assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) {
+ (trigger, name) =>
trigger.create(name)
- }
+ }
- // Summary namespace should match one of the allowable namespaces (typically 'guest')
- val ns = wsk.namespace.whois()
- val stdout = wsk.trigger.get(triggerName, summary = true).stdout
- stdout should include regex (s"(?i)trigger\\s+/$ns/$triggerName")
+ // Summary namespace should match one of the allowable namespaces (typically 'guest')
+ val ns = wsk.namespace.whois()
+ val stdout = wsk.trigger.get(triggerName, summary = true).stdout
+ stdout should include regex (s"(?i)trigger\\s+/$ns/$triggerName")
}
- it should "create a trigger with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "triggerEscapes"
-
- assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
- trigger.create(name, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
- }
-
- val stdout = wsk.trigger.get(name).stdout
- assert(stdout.startsWith(s"ok: got trigger $name\n"))
+ it should "create a trigger with the proper parameter and annotation escapes" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "triggerEscapes"
- val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
- val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
- val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+ assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+ trigger.create(name,
+ parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
+ }
- for (expectedItem <- escapedJSONArr) {
- receivedParams should contain(expectedItem)
- receivedAnnots should contain(expectedItem)
- }
+ val stdout = wsk.trigger.get(name).stdout
+ assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+ val receivedParams = wsk
+ .parseJsonString(stdout)
+ .fields("parameters")
+ .convertTo[JsArray]
+ .elements
+ val receivedAnnots = wsk
+ .parseJsonString(stdout)
+ .fields("annotations")
+ .convertTo[JsArray]
+ .elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "not create a trigger when feed fails to initialize" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) { (trigger, name) =>
- trigger.create(name, feed = Some(s"bogus"), expectedExitCode = ANY_ERROR_EXIT).exitCode should equal(NOT_FOUND)
- trigger.get(name, expectedExitCode = NOT_FOUND)
-
- trigger.create(name, feed = Some(s"bogus/feed"), expectedExitCode = ANY_ERROR_EXIT).exitCode should equal(
- NOT_FOUND)
- trigger.get(name, expectedExitCode = NOT_FOUND)
+ it should "not create a trigger when feed fails to initialize" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) {
+ (trigger, name) =>
+ trigger
+ .create(name,
+ feed = Some(s"bogus"),
+ expectedExitCode = ANY_ERROR_EXIT)
+ .exitCode should equal(NOT_FOUND)
+ trigger.get(name, expectedExitCode = NOT_FOUND)
+
+ trigger
+ .create(name,
+ feed = Some(s"bogus/feed"),
+ expectedExitCode = ANY_ERROR_EXIT)
+ .exitCode should equal(NOT_FOUND)
+ trigger.get(name, expectedExitCode = NOT_FOUND)
}
}
@@ -1129,80 +1670,99 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val triggerName = "feedTest"
assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
- action.create(actionName, Some(TestCLIUtils.getTestActionFilename("echo.js")))
+ action.create(actionName,
+ Some(TestCLIUtils.getTestActionFilename("echo.js")))
}
try {
- wsk.trigger.create(triggerName, feed = Some(actionName)).stdout should include(""""lifecycleEvent": "CREATE"""")
+ wsk.trigger
+ .create(triggerName, feed = Some(actionName))
+ .stdout should include(""""lifecycleEvent": "CREATE"""")
- wsk.trigger.get(triggerName).stdout should include(""""lifecycleEvent": "READ"""")
+ wsk.trigger.get(triggerName).stdout should include(
+ """"lifecycleEvent": "READ"""")
- wsk.trigger.create(triggerName, update = true).stdout should include(""""lifecycleEvent": "UPDATE""")
+ wsk.trigger.create(triggerName, update = true).stdout should include(
+ """"lifecycleEvent": "UPDATE""")
} finally {
- wsk.trigger.delete(triggerName).stdout should include(""""lifecycleEvent": "DELETE"""")
+ wsk.trigger.delete(triggerName).stdout should include(
+ """"lifecycleEvent": "DELETE"""")
}
}
- it should "denote bound trigger parameters for trigger summaries" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "denote bound trigger parameters for trigger summaries" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val trgBoundParams = "trgBoundParams"
val trgParamAnnot = "trgParamAnnot"
val trgParamOverlap = "trgParamOverlap"
val trgParamBound = "trgParamBound"
val trgAnnots = Map(
"parameters" -> JsArray(
- JsObject("name" -> JsString(trgParamAnnot), "description" -> JsString("Annotated")),
- JsObject("name" -> JsString(trgParamOverlap), "description" -> JsString("Annotated And Bound"))))
- val trgParamsBound = Map(trgParamBound -> JsString("Bound"), trgParamOverlap -> JsString("Bound And Annotated"))
+ JsObject("name" -> JsString(trgParamAnnot),
+ "description" -> JsString("Annotated")),
+ JsObject("name" -> JsString(trgParamOverlap),
+ "description" -> JsString("Annotated And Bound"))
+ ))
+ val trgParamsBound = Map(trgParamBound -> JsString("Bound"),
+ trgParamOverlap -> JsString("Bound And Annotated"))
assetHelper.withCleaner(wsk.trigger, trgBoundParams) { (trigger, _) =>
- trigger.create(trgBoundParams, annotations = trgAnnots, parameters = trgParamsBound)
+ trigger.create(trgBoundParams,
+ annotations = trgAnnots,
+ parameters = trgParamsBound)
}
val trgStdoutBound = wsk.trigger.get(trgBoundParams, summary = true).stdout
- trgStdoutBound should include(s"(parameters: $trgParamAnnot, *$trgParamBound, *$trgParamOverlap)")
+ trgStdoutBound should include(
+ s"(parameters: $trgParamAnnot, *$trgParamBound, *$trgParamOverlap)")
}
- it should "create, and get a trigger summary without a description and/or parameters" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val trgNoDesc = "trgNoDesc"
- val trgNoParams = "trgNoParams"
- val trgNoDescOrParams = "trgNoDescOrParams"
- val trgDesc = "Package description"
- val descFromParams = "Returns a result based on parameters"
- val namespace = wsk.namespace.whois()
- val qualtrgNoDesc = s"/${namespace}/${trgNoDesc}"
- val qualtrgNoParams = s"/${namespace}/${trgNoParams}"
- val qualtrgNoDescOrParams = s"/${namespace}/${trgNoDescOrParams}"
-
- val trgAnnotsNoParams = Map("description" -> JsString(trgDesc))
- val trgAnnotsNoDesc = Map(
- "parameters" -> JsArray(
- JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
- JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
-
- assetHelper.withCleaner(wsk.trigger, trgNoDesc) { (trigger, _) =>
- trigger.create(trgNoDesc, annotations = trgAnnotsNoDesc)
- }
- assetHelper.withCleaner(wsk.trigger, trgNoParams) { (trigger, _) =>
- trigger.create(trgNoParams, annotations = trgAnnotsNoParams)
- }
- assetHelper.withCleaner(wsk.trigger, trgNoDescOrParams) { (trigger, _) =>
- trigger.create(trgNoDescOrParams)
- }
+ it should "create, and get a trigger summary without a description and/or parameters" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val trgNoDesc = "trgNoDesc"
+ val trgNoParams = "trgNoParams"
+ val trgNoDescOrParams = "trgNoDescOrParams"
+ val trgDesc = "Package description"
+ val descFromParams = "Returns a result based on parameters"
+ val namespace = wsk.namespace.whois()
+ val qualtrgNoDesc = s"/${namespace}/${trgNoDesc}"
+ val qualtrgNoParams = s"/${namespace}/${trgNoParams}"
+ val qualtrgNoDescOrParams = s"/${namespace}/${trgNoDescOrParams}"
+
+ val trgAnnotsNoParams = Map("description" -> JsString(trgDesc))
+ val trgAnnotsNoDesc = Map(
+ "parameters" -> JsArray(
+ JsObject("name" -> JsString("paramName1"),
+ "description" -> JsString("Parameter description 1")),
+ JsObject("name" -> JsString("paramName2"),
+ "description" -> JsString("Parameter description 2"))
+ ))
+
+ assetHelper.withCleaner(wsk.trigger, trgNoDesc) { (trigger, _) =>
+ trigger.create(trgNoDesc, annotations = trgAnnotsNoDesc)
+ }
+ assetHelper.withCleaner(wsk.trigger, trgNoParams) { (trigger, _) =>
+ trigger.create(trgNoParams, annotations = trgAnnotsNoParams)
+ }
+ assetHelper.withCleaner(wsk.trigger, trgNoDescOrParams) { (trigger, _) =>
+ trigger.create(trgNoDescOrParams)
+ }
- val stdoutNoDescPkg = wsk.trigger.get(trgNoDesc, summary = true).stdout
- val stdoutNoParamsPkg = wsk.trigger.get(trgNoParams, summary = true).stdout
- val stdoutNoDescOrParams = wsk.trigger.get(trgNoDescOrParams, summary = true).stdout
+ val stdoutNoDescPkg = wsk.trigger.get(trgNoDesc, summary = true).stdout
+ val stdoutNoParamsPkg = wsk.trigger.get(trgNoParams, summary = true).stdout
+ val stdoutNoDescOrParams =
+ wsk.trigger.get(trgNoDescOrParams, summary = true).stdout
- stdoutNoDescPkg should include regex (s"(?i)trigger ${qualtrgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
- stdoutNoParamsPkg should include regex (s"(?i)trigger ${qualtrgNoParams}: ${trgDesc}\\s*\\(parameters: none defined\\)")
- stdoutNoDescOrParams should include regex (s"(?i)trigger ${qualtrgNoDescOrParams}\\s*\\(parameters: none defined\\)")
+ stdoutNoDescPkg should include regex (s"(?i)trigger ${qualtrgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
+ stdoutNoParamsPkg should include regex (s"(?i)trigger ${qualtrgNoParams}: ${trgDesc}\\s*\\(parameters: none defined\\)")
+ stdoutNoDescOrParams should include regex (s"(?i)trigger ${qualtrgNoDescOrParams}\\s*\\(parameters: none defined\\)")
}
behavior of "Wsk entity list formatting"
- it should "create, and list a package with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "create, and list a package with a long name" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "x" * 70
assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
pkg.create(name)
@@ -1212,7 +1772,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}, 5, Some(1 second))
}
- it should "create, and list an action with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "create, and list an action with a long name" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "x" * 70
val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
assetHelper.withCleaner(wsk.action, name) { (action, _) =>
@@ -1223,7 +1784,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}, 5, Some(1 second))
}
- it should "create, and list a trigger with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "create, and list a trigger with a long name" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val name = "x" * 70
assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
trigger.create(name)
@@ -1233,7 +1795,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}, 5, Some(1 second))
}
- it should "create, and list a rule with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "create, and list a rule with a long name" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
val ruleName = "x" * 70
val triggerName = "listRulesTrigger"
val actionName = "listRulesAction";
@@ -1251,7 +1814,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
}, 5, Some(1 second))
}
- it should "return a list of alphabetized actions" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "return a list of alphabetized actions" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
// Declare 4 actions, create them out of alphabetical order
val actionName = "actionAlphaTest"
for (i <- 1 to 3) {
@@ -1260,56 +1824,64 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
action.create(name, defaultAction)
}
}
- retry({
- val original = wsk.action.list(nameSort = Some(true)).stdout
- // Create list with action names in correct order
- val scalaSorted = List(s"${actionName}1", s"${actionName}2", s"${actionName}3")
- // Filter out everything not previously created
- val regex = s"${actionName}[1-3]".r
- // Retrieve action names into list as found in original
- val list = (regex.findAllMatchIn(original)).toList
- scalaSorted.toString shouldEqual list.toString
- }, 5, Some(1 second))
+ retry(
+ {
+ val original = wsk.action.list(nameSort = Some(true)).stdout
+ // Create list with action names in correct order
+ val scalaSorted =
+ List(s"${actionName}1", s"${actionName}2", s"${actionName}3")
+ // Filter out everything not previously created
+ val regex = s"${actionName}[1-3]".r
+ // Retrieve action names into list as found in original
+ val list = (regex.findAllMatchIn(original)).toList
+ scalaSorted.toString shouldEqual list.toString
+ },
+ 5,
+ Some(1 second)
+ )
}
- it should "return an alphabetized list with default package actions on top" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- // Declare 4 actions, create them out of alphabetical order
- val actionName = "actionPackageAlphaTest"
- val packageName = "packageAlphaTest"
- assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
- action.create(actionName, defaultAction)
- }
- assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, packageName) =>
- pkg.create(packageName)
- }
- for (i <- 1 to 3) {
- val name = s"${packageName}/${actionName}$i"
- assetHelper.withCleaner(wsk.action, name) { (action, name) =>
- action.create(name, defaultAction)
- }
+ it should "return an alphabetized list with default package actions on top" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ // Declare 4 actions, create them out of alphabetical order
+ val actionName = "actionPackageAlphaTest"
+ val packageName = "packageAlphaTest"
+ assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+ action.create(actionName, defaultAction)
+ }
+ assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, packageName) =>
+ pkg.create(packageName)
+ }
+ for (i <- 1 to 3) {
+ val name = s"${packageName}/${actionName}$i"
+ assetHelper.withCleaner(wsk.action, name) { (action, name) =>
+ action.create(name, defaultAction)
}
- retry(
- {
- val original = wsk.action.list(nameSort = Some(true)).stdout
- // Create list with action names in correct order
- val scalaSorted = List(
- s"$actionName",
- s"${packageName}/${actionName}1",
- s"${packageName}/${actionName}2",
- s"${packageName}/${actionName}3")
- // Filter out everything not previously created
- val regexNoPackage = s"$actionName".r
- val regexWithPackage = s"${packageName}/${actionName}[1-3]".r
- // Retrieve action names into list as found in original
- val list = regexNoPackage.findFirstIn(original).get :: (regexWithPackage.findAllMatchIn(original)).toList
- scalaSorted.toString shouldEqual list.toString
- },
- 5,
- Some(1 second))
- }
-
- it should "return a list of alphabetized packages" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ }
+ retry(
+ {
+ val original = wsk.action.list(nameSort = Some(true)).stdout
+ // Create list with action names in correct order
+ val scalaSorted = List(s"$actionName",
+ s"${packageName}/${actionName}1",
+ s"${packageName}/${actionName}2",
+ s"${packageName}/${actionName}3")
+ // Filter out everything not previously created
+ val regexNoPackage = s"$actionName".r
+ val regexWithPackage = s"${packageName}/${actionName}[1-3]".r
+ // Retrieve action names into list as found in original
+ val list = regexNoPackage
+ .findFirstIn(original)
+ .get :: (regexWithPackage.findAllMatchIn(original)).toList
+ scalaSorted.toString shouldEqual list.toString
+ },
+ 5,
+ Some(1 second)
+ )
+ }
+
+ it should "return a list of alphabetized packages" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
// Declare 3 packages, create them out of alphabetical order
val packageName = "pkgAlphaTest"
for (i <- 1 to 3) {
@@ -1318,19 +1890,25 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
pkg.create(name)
}
}
- retry({
- val original = wsk.pkg.list(nameSort = Some(true)).stdout
- // Create list with package names in correct order
- val scalaSorted = List(s"${packageName}1", s"${packageName}2", s"${packageName}3")
- // Filter out everything not previously created
- val regex = s"${packageName}[1-3]".r
- // Retrieve package names into list as found in original
- val list = (regex.findAllMatchIn(original)).toList
- scalaSorted.toString shouldEqual list.toString
- }, 5, Some(1 second))
+ retry(
+ {
+ val original = wsk.pkg.list(nameSort = Some(true)).stdout
+ // Create list with package names in correct order
+ val scalaSorted =
+ List(s"${packageName}1", s"${packageName}2", s"${packageName}3")
+ // Filter out everything not previously created
+ val regex = s"${packageName}[1-3]".r
+ // Retrieve package names into list as found in original
+ val list = (regex.findAllMatchIn(original)).toList
+ scalaSorted.toString shouldEqual list.toString
+ },
+ 5,
+ Some(1 second)
+ )
}
- it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ it should "return a list of alphabetized triggers" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
// Declare 4 triggers, create them out of alphabetical order
val triggerName = "triggerAlphaTest"
for (i <- 1 to 3) {
@@ -1339,47 +1917,54 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
trigger.create(name)
}
}
- retry({
- val original = wsk.trigger.list(nameSort = Some(true)).stdout
- // Create list with trigger names in correct order
- val scalaSorted = List(s"${triggerName}1", s"${triggerName}2", s"${triggerName}3")
- // Filter out everything not previously created
- val regex = s"${triggerName}[1-3]".r
- // Retrieve trigger names into list as found in original
- val list = (regex.findAllMatchIn(original)).toList
- scalaSorted.toString shouldEqual list.toString
- }, 5, Some(1 second))
+ retry(
+ {
+ val original = wsk.trigger.list(nameSort = Some(true)).stdout
+ // Create list with trigger names in correct order
+ val scalaSorted =
+ List(s"${triggerName}1", s"${triggerName}2", s"${triggerName}3")
+ // Filter out everything not previously created
+ val regex = s"${triggerName}[1-3]".r
+ // Retrieve trigger names into list as found in original
+ val list = (regex.findAllMatchIn(original)).toList
+ scalaSorted.toString shouldEqual list.toString
+ },
+ 5,
+ Some(1 second)
+ )
}
- it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
- // Declare a trigger and an action for the purposes of creating rules
- val triggerName = "listRulesTrigger"
- val actionName = "listRulesAction"
+ it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ // Declare a trigger and an action for the purposes of creating rules
+ val triggerName = "listRulesTrigger"
+ val actionName = "listRulesAction"
- assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
- trigger.create(name)
- }
- assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
- action.create(name, defaultAction)
- }
- // Declare 3 rules, create them out of alphabetical order
- val ruleName = "ruleAlphaTest"
- for (i <- 1 to 3) {
- val name = s"$ruleName$i"
- assetHelper.withCleaner(wsk.rule, name) { (rule, name) =>
- rule.create(name, trigger = triggerName, action = actionName)
+ assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+ trigger.create(name)
}
- }
- retry({
- val original = wsk.rule.list(nameSort = Some(true)).stdout
- // Create list with rule names in correct order
- val scalaSorted = List(s"${ruleName}1", s"${ruleName}2", s"${ruleName}3")
- // Filter out everything not previously created
- val regex = s"${ruleName}[1-3]".r
- // Retrieve rule names into list as found in original
- val list = (regex.findAllMatchIn(original)).toList
- scalaSorted.toString shouldEqual list.toString
- })
+ assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+ action.create(name, defaultAction)
+ }
+ // Declare 3 rules, create them out of alphabetical order
+ val ruleName = "ruleAlphaTest"
+ for (i <- 1 to 3) {
+ val name = s"$ruleName$i"
+ assetHelper.withCleaner(wsk.rule, name) { (rule, name) =>
+ rule.create(name, trigger = triggerName, action = actionName)
+ }
+ }
+ retry({
+ val original = wsk.rule.list(nameSort = Some(true)).stdout
+ // Create list with rule names in correct order
+ val scalaSorted =
+ List(s"${ruleName}1", s"${ruleName}2", s"${ruleName}3")
+ // Filter out everything not previously created
+ val regex = s"${ruleName}[1-3]".r
+ // Retrieve rule names into list as found in original
+ val list = (regex.findAllMatchIn(original)).toList
+ scalaSorted.toString shouldEqual list.toString
+ })
}
behavior of "Wsk params and annotations"
@@ -1391,36 +1976,54 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
TestCLIUtils.getTestActionFilename("invalidInput1.json"),
TestCLIUtils.getTestActionFilename("invalidInput2.json"),
TestCLIUtils.getTestActionFilename("invalidInput3.json"),
- TestCLIUtils.getTestActionFilename("invalidInput4.json"))
+ TestCLIUtils.getTestActionFilename("invalidInput4.json")
+ )
val paramCmds = Seq(
- Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
- Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
+ Seq("action",
+ "create",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js")),
+ Seq("action",
+ "update",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js")),
Seq("action", "invoke", "actionName"),
Seq("package", "create", "packageName"),
Seq("package", "update", "packageName"),
Seq("package", "bind", "packageName", "boundPackageName"),
Seq("trigger", "create", "triggerName"),
Seq("trigger", "update", "triggerName"),
- Seq("trigger", "fire", "triggerName"))
+ Seq("trigger", "fire", "triggerName")
+ )
val annotCmds = Seq(
- Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
- Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
+ Seq("action",
+ "create",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js")),
+ Seq("action",
+ "update",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js")),
Seq("package", "create", "packageName"),
Seq("package", "update", "packageName"),
Seq("package", "bind", "packageName", "boundPackageName"),
Seq("trigger", "create", "triggerName"),
- Seq("trigger", "update", "triggerName"))
+ Seq("trigger", "update", "triggerName")
+ )
for (cmd <- paramCmds) {
for (invalid <- invalidJSONInputs) {
wsk
- .cli(cmd ++ Seq("-p", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
+ .cli(cmd ++ Seq("-p", "key", invalid) ++ wskprops.overrides,
+ expectedExitCode = ERROR_EXIT)
.stderr should include("Invalid parameter argument")
}
for (invalid <- invalidJSONFiles) {
- wsk.cli(cmd ++ Seq("-P", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT).stderr should include(
- "Invalid parameter argument")
+ wsk
+ .cli(cmd ++ Seq("-P", invalid) ++ wskprops.overrides,
+ expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid parameter argument")
}
}
@@ -1428,13 +2031,16 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
for (cmd <- annotCmds) {
for (invalid <- invalidJSONInputs) {
wsk
- .cli(cmd ++ Seq("-a", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
+ .cli(cmd ++ Seq("-a", "key", invalid) ++ wskprops.overrides,
+ expectedExitCode = ERROR_EXIT)
.stderr should include("Invalid annotation argument")
}
for (invalid <- invalidJSONFiles) {
- wsk.cli(cmd ++ Seq("-A", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT).stderr should include(
- "Invalid annotation argument")
+ wsk
+ .cli(cmd ++ Seq("-A", invalid) ++ wskprops.overrides,
+ expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid annotation argument")
}
}
}
@@ -1442,53 +2048,109 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
val emptyFile = TestCLIUtils.getTestActionFilename("emtpy.js")
val missingFile = "notafile"
- val emptyFileMsg = s"File '$emptyFile' is not a valid file or it does not exist"
- val missingFileMsg = s"File '$missingFile' is not a valid file or it does not exist"
+ val emptyFileMsg =
+ s"File '$emptyFile' is not a valid file or it does not exist"
+ val missingFileMsg =
+ s"File '$missingFile' is not a valid file or it does not exist"
val invalidArgs = Seq(
- (
- Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
- emptyFileMsg),
- (
- Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
- emptyFileMsg),
+ (Seq("action",
+ "create",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js"),
+ "-P",
+ emptyFile),
+ emptyFileMsg),
+ (Seq("action",
+ "update",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js"),
+ "-P",
+ emptyFile),
+ emptyFileMsg),
(Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
(Seq("action", "create", "actionName", "-P", emptyFile), emptyFileMsg),
(Seq("action", "update", "actionName", "-P", emptyFile), emptyFileMsg),
(Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
(Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
(Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package",
+ "bind",
+ "packageName",
+ "boundPackageName",
+ "-P",
+ emptyFile),
+ emptyFileMsg),
(Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
(Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package",
+ "bind",
+ "packageName",
+ "boundPackageName",
+ "-P",
+ emptyFile),
+ emptyFileMsg),
(Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
(Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
(Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
(Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
(Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
(Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
- (
- Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
- missingFileMsg),
- (
- Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
- missingFileMsg),
- (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
- (Seq("action", "create", "actionName", "-A", missingFile), missingFileMsg),
- (Seq("action", "update", "actionName", "-A", missingFile), missingFileMsg),
- (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
- (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
- (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
- (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
- (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
- (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg))
+ (Seq("action",
+ "create",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js"),
+ "-A",
+ missingFile),
+ missingFileMsg),
+ (Seq("action",
+ "update",
+ "actionName",
+ TestCLIUtils.getTestActionFilename("hello.js"),
+ "-A",
+ missingFile),
+ missingFileMsg),
+ (Seq("action", "invoke", "actionName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("action", "create", "actionName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("action", "update", "actionName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("action", "invoke", "actionName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("package", "create", "packageName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("package", "update", "packageName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("package",
+ "bind",
+ "packageName",
+ "boundPackageName",
+ "-A",
+ missingFile),
+ missingFileMsg),
+ (Seq("package", "create", "packageName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("package", "update", "packageName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("package",
+ "bind",
+ "packageName",
+ "boundPackageName",
+ "-A",
+ missingFile),
+ missingFileMsg),
+ (Seq("trigger", "create", "triggerName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("trigger", "update", "triggerName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("trigger", "create", "triggerName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("trigger", "update", "triggerName", "-A", missingFile),
+ missingFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg)
+ )
invalidArgs foreach {
case (cmd, err) =>
@@ -1528,18 +2190,24 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
(Seq("package", "update", "packageName", "-p"), invalidParamMsg),
(Seq("package", "update", "packageName", "-p", "key"), invalidParamMsg),
(Seq("package", "update", "packageName", "-P"), invalidParamFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-p"), invalidParamMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-p", "key"), invalidParamMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-P"), invalidParamFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-p"),
+ invalidParamMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-p", "key"),
+ invalidParamMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-P"),
+ invalidParamFileMsg),
(Seq("package", "create", "packageName", "-a"), invalidAnnotMsg),
(Seq("package", "create", "packageName", "-a", "key"), invalidAnnotMsg),
(Seq("package", "create", "packageName", "-A"), invalidAnnotFileMsg),
(Seq("package", "update", "packageName", "-a"), invalidAnnotMsg),
(Seq("package", "update", "packageName", "-a", "key"), invalidAnnotMsg),
(Seq("package", "update", "packageName", "-A"), invalidAnnotFileMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-a"), invalidAnnotMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-a", "key"), invalidAnnotMsg),
- (Seq("package", "bind", "packageName", "boundPackageName", "-A"), invalidAnnotFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-a"),
+ invalidAnnotMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-a", "key"),
+ invalidAnnotMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-A"),
+ invalidAnnotFileMsg),
(Seq("trigger", "create", "triggerName", "-p"), invalidParamMsg),
(Seq("trigger", "create", "triggerName", "-p", "key"), invalidParamMsg),
(Seq("trigger", "create", "triggerName", "-P"), invalidParamFileMsg),
@@ -1557,7 +2225,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
(Seq("trigger", "update", "triggerName", "-A"), invalidAnnotFileMsg),
(Seq("trigger", "fire", "triggerName", "-a"), invalidAnnotMsg),
(Seq("trigger", "fire", "triggerName", "-a", "key"), invalidAnnotMsg),
- (Seq("trigger", "fire", "triggerName", "-A"), invalidAnnotFileMsg))
+ (Seq("trigger", "fire", "triggerName", "-A"), invalidAnnotFileMsg)
+ )
invalidArgs foreach {
case (cmd, err) =>
@@ -1573,13 +2242,16 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val invalidArgsMsg = "error: Invalid argument(s)"
val tooFewArgsMsg = invalidArgsMsg + "."
val tooManyArgsMsg = invalidArgsMsg + ": "
- val actionNameActionReqMsg = "An action name and code artifact are required."
+ val actionNameActionReqMsg =
+ "An action name and code artifact are required."
val actionNameReqMsg = "An action name is required."
val actionOptMsg = "A code artifact is optional."
val packageNameReqMsg = "A package name is required."
- val packageNameBindingReqMsg = "A package name and binding name are required."
+ val packageNameBindingReqMsg =
+ "A package name and binding name are required."
val ruleNameReqMsg = "A rule name is required."
- val ruleTriggerActionReqMsg = "A rule, trigger and action name are required."
+ val ruleTriggerActionReqMsg =
+ "A rule, trigger and action name are required."
val activationIdReq = "An activation ID is required."
val triggerNameReqMsg = "A trigger name is required."
val optNamespaceMsg = "An optional namespace is the only valid argument."
@@ -1591,104 +2263,155 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
val apiGetReqMsg = "An API base path or API name is required."
val apiDeleteReqMsg =
"An API base path or API name is required. An optional API relative path and operation may also be provided."
- val apiListReqMsg = "Optional parameters are: API base path (or API name), API relative path and operation."
+ val apiListReqMsg =
+ "Optional parameters are: API base path (or API name), API relative path and operation."
val invalidShared = s"Cannot use value '$invalidArg' for shared"
val entityNameMsg =
s"An entity name, '$invalidArg', was provided instead of a namespace. Valid namespaces are of the following format: /NAMESPACE."
val invalidArgs = Seq(
(Seq("api", "create"), s"${tooFewArgsMsg} ${apiCreateReqMsg}"),
- (
- Seq("api", "create", "/basepath", "/path", "GET", "action", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${apiCreateReqMsg}"),
+ (Seq("api", "create", "/basepath", "/path", "GET", "action", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${apiCreateReqMsg}"),
(Seq("api", "get"), s"${tooFewArgsMsg} ${apiGetReqMsg}"),
- (Seq("api", "get", "/basepath", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiGetReqMsg}"),
+ (Seq("api", "get", "/basepath", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${apiGetReqMsg}"),
(Seq("api", "delete"), s"${tooFewArgsMsg} ${apiDeleteReqMsg}"),
- (
- Seq("api", "delete", "/basepath", "/path", "GET", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${apiDeleteReqMsg}"),
- (
- Seq("api", "list", "/basepath", "/path", "GET", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${apiListReqMsg}"),
+ (Seq("api", "delete", "/basepath", "/path", "GET", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${apiDeleteReqMsg}"),
+ (Seq("api", "list", "/basepath", "/path", "GET", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${apiListReqMsg}"),
(Seq("action", "create"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
- (Seq("action", "create", "someAction"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
- (Seq("action", "create", "actionName", "artifactName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("action", "update"), s"${tooFewArgsMsg} ${actionNameReqMsg} ${actionOptMsg}"),
- (
- Seq("action", "update", "actionName", "artifactName", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${actionNameReqMsg} ${actionOptMsg}"),
+ (Seq("action", "create", "someAction"),
+ s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
+ (Seq("action", "create", "actionName", "artifactName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("action", "update"),
+ s"${tooFewArgsMsg} ${actionNameReqMsg} ${actionOptMsg}"),
+ (Seq("action", "update", "actionName", "artifactName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${actionNameReqMsg} ${actionOptMsg}"),
(Seq("action", "delete"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
- (Seq("action", "delete", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("action", "delete", "actionName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("action", "get"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
- (Seq("action", "get", "actionName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("action", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("action", "get", "actionName", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("action", "list", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("action", "invoke"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
- (Seq("action", "invoke", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("activation", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("action", "invoke", "actionName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("activation", "list", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("activation", "get"), s"${tooFewArgsMsg} ${activationIdReq}"),
- (Seq("activation", "get", "activationID", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("activation", "get", "activationID", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("activation", "logs"), s"${tooFewArgsMsg} ${activationIdReq}"),
- (Seq("activation", "logs", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("activation", "logs", "activationID", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("activation", "result"), s"${tooFewArgsMsg} ${activationIdReq}"),
- (Seq("activation", "result", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("activation", "poll", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
- (Seq("namespace", "list", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
- (Seq("namespace", "get", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
+ (Seq("activation", "result", "activationID", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("activation", "poll", "activationID", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("namespace", "list", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
+ (Seq("namespace", "get", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
(Seq("package", "create"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
- (Seq("package", "create", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("package", "create", "packageName", "--shared", invalidArg), invalidShared),
+ (Seq("package", "create", "packageName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("package", "create", "packageName", "--shared", invalidArg),
+ invalidShared),
(Seq("package", "update"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
- (Seq("package", "update", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("package", "update", "packageName", "--shared", invalidArg), invalidShared),
+ (Seq("package", "update", "packageName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("package", "update", "packageName", "--shared", invalidArg),
+ invalidShared),
(Seq("package", "get"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
- (Seq("package", "get", "packageName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("package", "get", "packageName", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("package", "bind"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
- (Seq("package", "bind", "packageName"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
- (Seq("package", "bind", "packageName", "bindingName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("package", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("package", "bind", "packageName"),
+ s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
+ (Seq("package", "bind", "packageName", "bindingName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("package", "list", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("package", "list", invalidArg), entityNameMsg),
(Seq("package", "delete"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
- (Seq("package", "delete", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("package", "refresh", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("package", "delete", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("package", "refresh", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("package", "refresh", invalidArg), entityNameMsg),
(Seq("rule", "enable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
- (Seq("rule", "enable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "enable", "ruleName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "disable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
- (Seq("rule", "disable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "disable", "ruleName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "status"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
- (Seq("rule", "status", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "status", "ruleName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "create"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "create", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "create", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "create", "ruleName", "triggerName", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "create", "ruleName"),
+ s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+ (Seq("rule", "create", "ruleName", "triggerName"),
+ s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+ (Seq("rule",
+ "create",
+ "ruleName",
+ "triggerName",
+ "actionName",
+ invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "update"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "update", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "update", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
- (Seq("rule", "update", "ruleName", "triggerName", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "update", "ruleName"),
+ s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+ (Seq("rule", "update", "ruleName", "triggerName"),
+ s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+ (Seq("rule",
+ "update",
+ "ruleName",
+ "triggerName",
+ "actionName",
+ invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "get"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
- (Seq("rule", "get", "ruleName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "get", "ruleName", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("rule", "delete"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
- (Seq("rule", "delete", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("rule", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("rule", "delete", "ruleName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("rule", "list", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("rule", "list", invalidArg), entityNameMsg),
- (Seq("trigger", "fire"), s"${tooFewArgsMsg} ${triggerNameReqMsg} ${optPayloadMsg}"),
- (
- Seq("trigger", "fire", "triggerName", "triggerPayload", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg} ${optPayloadMsg}"),
+ (Seq("trigger", "fire"),
+ s"${tooFewArgsMsg} ${triggerNameReqMsg} ${optPayloadMsg}"),
+ (Seq("trigger", "fire", "triggerName", "triggerPayload", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg} ${optPayloadMsg}"),
(Seq("trigger", "create"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
- (Seq("trigger", "create", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("trigger", "create", "triggerName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("trigger", "update"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
- (Seq("trigger", "update", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("trigger", "update", "triggerName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("trigger", "get"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
- (Seq("trigger", "get", "triggerName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("trigger", "get", "triggerName", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
(Seq("trigger", "delete"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
- (Seq("trigger", "delete", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
- (Seq("trigger", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
- (Seq("trigger", "list", invalidArg), entityNameMsg))
+ (Seq("trigger", "delete", "triggerName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}."),
+ (Seq("trigger", "list", "namespace", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+ (Seq("trigger", "list", invalidArg), entityNameMsg)
+ )
invalidArgs foreach {
case (cmd, err) =>
withClue(cmd) {
- val rr = wsk.cli(cmd ++ wskprops.overrides, expectedExitCode = ANY_ERROR_EXIT)
+ val rr = wsk.cli(cmd ++ wskprops.overrides,
+ expectedExitCode = ANY_ERROR_EXIT)
rr.exitCode should (be(ERROR_EXIT) or be(MISUSE_EXIT))
rr.stderr should include(err)
rr.stderr should include("Run 'wsk --help' for usage.")
@@ -1698,56 +2421,67 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
behavior of "Wsk action parameters"
- it should "create an action with different permutations of limits" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
- def testLimit(timeout: Option[Duration] = None,
- memory: Option[ByteSize] = None,
- logs: Option[ByteSize] = 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(STD_LOGSIZE).toMB.toInt.toJson)
-
- val name = "ActionLimitTests" + Instant.now.toEpochMilli
- val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = (ec == SUCCESS_EXIT)) {
+ it should "create an action with different permutations of limits" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+
+ def testLimit(timeout: Option[Duration] = None,
+ memory: Option[ByteSize] = None,
+ logs: Option[ByteSize] = 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(STD_LOGSIZE).toMB.toInt.toJson
+ )
+
+ val name = "ActionLimitTests" + Instant.now.toEpochMilli
+ val createResult =
+ assetHelper.withCleaner(wsk.action,
+ name,
+ confirmDelete = (ec == SUCCESS_EXIT)) {
(action, _) =>
- val result = action.create(
- name,
- file,
- logsize = logs,
- memory = memory,
- timeout = timeout,
- expectedExitCode = DONTCARE_EXIT)
- withClue(s"create failed for parameters: timeout = $timeout, memory = $memory, logsize = $logs:") {
+ val result = action.create(name,
+ file,
+ logsize = logs,
+ memory = memory,
+ timeout = timeout,
+ expectedExitCode = DONTCARE_EXIT)
+ withClue(
+ s"create failed for parameters: timeout = $timeout, memory = $memory, logsize = $logs:") {
result.exitCode should be(ec)
}
result
}
- if (ec == SUCCESS_EXIT) {
- val JsObject(parsedAction) = wsk.action.get(name).stdout.split("\n").tail.mkString.parseJson.asJsObject
- parsedAction("limits") shouldBe limits
- } else {
- createResult.stderr should include("allowed threshold")
- }
+ if (ec == SUCCESS_EXIT) {
+ val JsObject(parsedAction) = wsk.action
+ .get(name)
+ .stdout
+ .split("\n")
+ .tail
+ .mkString
+ .parseJson
+ .asJsObject
+ parsedAction("limits") shouldBe limits
+ } else {
+ createResult.stderr should include("allowed threshold")
}
+ }
- // Assert for valid permutations that the values are set correctly
- for {
- time <- Seq(None, Some(MIN_DURATION), Some(MAX_DURATION))
- mem <- Seq(None, Some(minMemory), Some(maxMemory))
- log <- Seq(None, Some(MIN_LOGSIZE), Some(MAX_LOGSIZE))
- } testLimit(time, mem, log)
-
- // 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)
+ // Assert for valid permutations that the values are set correctly
+ for {
+ time <- Seq(None, Some(MIN_DURATION), Some(MAX_DURATION))
+ mem <- Seq(None, Some(minMemory), Some(maxMemory))
+ log <- Seq(None, Some(MIN_LOGSIZE), Some(MAX_LOGSIZE))
+ } testLimit(time, mem, log)
+
+ // 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)
}
}
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index ee7d434..44b8ede 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -1416,6 +1416,14 @@
"translation": "treat ACTION as a web action, a raw HTTP web action, or as a standard action; yes | true = web action, raw = raw HTTP web action, no | false = standard action"
},
{
+ "id": "secure the web action. where `SECRET` is true, false, or any string. Only valid when the ACTION is a web action",
+ "translation": "secure the web action. where `SECRET` is true, false, or any string. Only valid when the ACTION is a web action"
+ },
+ {
+ "id": "The --web-secure option is only valid when the --web option is enabled.",
+ "translation": "The --web-secure option is only valid when the --web option is enabled."
+ },
+ {
"id": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'.",
"translation": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
},
--
To stop receiving notification emails like this one, please contact
dubeejw@apache.org.