You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ho...@apache.org on 2017/07/17 14:10:23 UTC

[incubator-openwhisk-cli] branch master updated (93a09ce -> 7859b71)

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

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


    from 93a09ce  wsk CLI should tolerate APIs that do not yet have a mapped action (#2458)
     new 9efabe1  API GW V2 updates (#2436)
     new 5b46680  Get Action URL from CLI (#2461)
     new 435bb48  (Review) Added --last Activation Flag  (#2334)
     new a65c3cb  Externalize access to a few CLI methods to facilitate access across packages (#2483)
     new 0bd62a9  Update the i18n resource and pin to latest client go commit
     new 5b47f4f  API GW V2 updates (#2436)
     new 2339ec3  Get Action URL from CLI (#2461)
     new dd1dd2a  (Review) Added --last Activation Flag  (#2334)
     new 7859b71  Add subject with a namespace. (#2291)

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Godeps/Godeps.json                                 |   2 +-
 commands/action.go                                 |  65 ++--
 commands/activation.go                             |  68 +++-
 commands/api.go                                    |   6 +-
 commands/commands.go                               |  17 +-
 commands/flags.go                                  |   2 +
 commands/property.go                               |   6 +-
 commands/util.go                                   |  19 +-
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |   7 +-
 .../test/scala/system/basic/WskBasicTests.scala    | 402 +++++++++++----------
 .../test/scala/system/basic/WskSequenceTests.scala |   4 +-
 .../scala/whisk/core/admin/WskAdminTests.scala     |  20 +-
 .../actions/test/ApiGwRoutemgmtActionTests.scala   |   8 +-
 .../scala/whisk/core/cli/test/ApiGwTests.scala     |  50 ++-
 .../core/cli/test/WskActionSequenceTests.scala     |   6 +-
 .../whisk/core/cli/test/WskBasicUsageTests.scala   |  77 +++-
 .../whisk/core/cli/test/WskEntitlementTests.scala  |   3 +-
 .../whisk/core/cli/test/WskWebActionsTests.scala   |   3 +-
 wski18n/i18n_resources.go                          |  22 +-
 wski18n/resources/en_US.all.json                   |  36 +-
 20 files changed, 514 insertions(+), 309 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].

[incubator-openwhisk-cli] 05/09: Update the i18n resource and pin to latest client go commit

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 0bd62a9ce0fdce6af01c601cd133e64f2ecf604a
Author: Vincent Hou <sh...@us.ibm.com>
AuthorDate: Sun Jul 16 21:45:44 2017 -0400

    Update the i18n resource and pin to latest client go commit
---
 Godeps/Godeps.json        |  2 +-
 wski18n/i18n_resources.go | 22 +++++++++++-----------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 23af91a..5da8152 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -65,7 +65,7 @@
 		},
         {
             "ImportPath": "github.com/apache/incubator-openwhisk-client-go/...",
-            "Rev": "c997fa3bc91903113eeee087a13f2a0b27fe1f6a"
+            "Rev": "08e3d592828073ce3885317e2945db3678f3a6ac"
         }
 	]
 }
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 39ebbc8..aab13af 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -109,12 +109,12 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
 
-var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5d\x5f\x73\xdb\x38\x92\x7f\x9f\x4f\xd1\x95\x17\x3b\x55\xb2\xb3\xfb\x74\x75\x99\x9a\x07\x4d\xec\xd9\x78\x93\xd8\xae\xc8\x99\xdd\xa9\x9b\xab\x11\x4c\x42\x12\xc6\x14\xc0\x01\x40\x2b\x4a\xd6\xdf\xfd\x0a\x00\x49\x91\x12\xfe\x92\x72\x72\x4f\x71\xc4\xee\x5f\x37\xfe\x37\x1a\xdd\xc0\xff\xfc\x00\xf0\xf5\x07\x00\x80\x17\x24\x7f\xf1\x1a\x5e\x4c\xcb\xb2\x20\x19\x92\x84\x51\xc0\x9f\x89\xc4\x39\x54\x14\x7f\x2e\x71 [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5d\x5f\x73\xdb\x38\x92\x7f\x9f\x4f\xd1\x95\x17\x3b\x55\xb2\xb3\xfb\x74\x75\x99\x9a\x07\x4d\xec\xd9\x78\x93\xd8\xae\xc8\x99\xdd\xa9\x9b\xab\x11\x4c\x42\x12\xc6\x14\xc0\x01\x40\x2b\x4a\xd6\xdf\xfd\x0a\x00\x49\x91\x12\xfe\x92\x72\x72\x4f\x71\xc4\xee\x5f\x37\xfe\x37\x1a\xdd\xc0\xff\xfc\x00\xf0\xf5\x07\x00\x80\x17\x24\x7f\xf1\x1a\x5e\x4c\xcb\xb2\x20\x19\x92\x84\x51\xc0\x9f\x89\xc4\x39\x54\x14\x7f\x2e\x71 [...]
 
 func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
     return bindataRead(
@@ -129,7 +129,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 48413, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 49131, mode: os.FileMode(420), modTime: time.Unix(1500255849, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -149,7 +149,7 @@ func wski18nResourcesEs_esAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -169,7 +169,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -189,7 +189,7 @@ func wski18nResourcesIt_itAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -209,7 +209,7 @@ func wski18nResourcesJa_jaAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -229,7 +229,7 @@ func wski18nResourcesKo_krAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -249,7 +249,7 @@ func wski18nResourcesPt_brAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -269,7 +269,7 @@ func wski18nResourcesZh_hansAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -289,7 +289,7 @@ func wski18nResourcesZh_hantAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1499746842, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500255391, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 02/09: Get Action URL from CLI (#2461)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5b466804c18c68cae594f8126698bfe9244d8974
Author: James Dubee <jw...@us.ibm.com>
AuthorDate: Wed Jul 12 13:20:40 2017 -0400

    Get Action URL from CLI (#2461)
---
 commands/action.go               | 58 +++++++++++++++++++++++-----------------
 commands/api.go                  |  6 ++---
 commands/flags.go                |  1 +
 commands/util.go                 | 19 ++-----------
 wski18n/resources/en_US.all.json |  4 +++
 5 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/commands/action.go b/commands/action.go
index b4926d9..786e6f1 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -33,13 +33,13 @@ import (
     "github.com/mattn/go-colorable"
 )
 
-const MEMORY_LIMIT = 256
-const TIMEOUT_LIMIT = 60000
-const LOGSIZE_LIMIT = 10
-const ACTIVATION_ID = "activationId"
-const WEB_EXPORT_ANNOT = "web-export"
-const RAW_HTTP_ANNOT = "raw-http"
-const FINAL_ANNOT = "final"
+const MEMORY_LIMIT      = 256
+const TIMEOUT_LIMIT     = 60000
+const LOGSIZE_LIMIT     = 10
+const ACTIVATION_ID     = "activationId"
+const WEB_EXPORT_ANNOT  = "web-export"
+const RAW_HTTP_ANNOT    = "raw-http"
+const FINAL_ANNOT       = "final"
 
 var actionCmd = &cobra.Command{
     Use:   "action",
@@ -196,7 +196,7 @@ func handleInvocationResponse(
 }
 
 var actionGetCmd = &cobra.Command{
-    Use:           "get ACTION_NAME [FIELD_FILTER]",
+    Use:           "get ACTION_NAME [FIELD_FILTER | --summary | --url]",
     Short:         wski18n.T("get action"),
     SilenceUsage:  true,
     SilenceErrors: true,
@@ -211,7 +211,7 @@ var actionGetCmd = &cobra.Command{
             return whiskErr
         }
 
-        if len(args) > 1 {
+        if !Flags.action.url && !Flags.common.summary && len(args) > 1 {
             field = args[1]
 
             if !fieldExists(&whisk.Action{}, field) {
@@ -229,7 +229,13 @@ var actionGetCmd = &cobra.Command{
             return actionGetError(qualifiedName.entityName, err)
         }
 
-        if Flags.common.summary {
+        if Flags.action.url {
+            actionURL := action.ActionURL(Properties.APIHost,
+                DefaultOpenWhiskApiPath,
+                Properties.APIVersion,
+                qualifiedName.packageName)
+            printActionGetWithURL(qualifiedName.entity, actionURL)
+        } else if Flags.common.summary {
             printSummary(action)
         } else {
             if len(field) > 0 {
@@ -823,6 +829,17 @@ func printActionGetWithField(entityName string, field string, action *whisk.Acti
     printField(action, field)
 }
 
+func printActionGetWithURL(entityName string, actionURL string) {
+    fmt.Fprintf(
+        color.Output,
+        wski18n.T("{{.ok}} got action {{.name}}\n",
+            map[string]interface{}{
+                "ok": color.GreenString("ok:"),
+                "name": boldString(entityName),
+            }))
+    fmt.Println(actionURL)
+}
+
 func printActionGet(entityName string, action *whisk.Action) {
     fmt.Fprintf(
         color.Output,
@@ -847,7 +864,7 @@ func printActionDeleted(entityName string) {
 }
 
 // Check if the specified action is a web-action
-func isWebAction(client *whisk.Client, qname QualifiedName) error {
+func isWebAction(client *whisk.Client, qname QualifiedName) (error) {
     var err error = nil
 
     savedNs := client.Namespace
@@ -855,6 +872,7 @@ func isWebAction(client *whisk.Client, qname QualifiedName) error {
     fullActionName := "/" + qname.namespace + "/" + qname.entityName
 
     action, _, err := client.Actions.Get(qname.entityName)
+
     if err != nil {
         whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", fullActionName, err)
         whisk.Debug(whisk.DbgError, "Unable to obtain action '%s' for web action validation\n", fullActionName)
@@ -865,23 +883,14 @@ func isWebAction(client *whisk.Client, qname QualifiedName) error {
     } else {
         err = errors.New(wski18n.T("Action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
             map[string]interface{}{"name": fullActionName}))
-        weVal := getValue(action.Annotations, "web-export")
-        if (weVal == nil) {
-            whisk.Debug(whisk.DbgError, "getValue(annotations, web-export) for action %s found no value\n", fullActionName)
-        } else {
-            var webExport bool
-            var ok bool
-            if webExport, ok = weVal.(bool); !ok {
-                whisk.Debug(whisk.DbgError, "web-export annotation value (%v) is not a boolean\n", weVal)
-            } else if !webExport {
-                whisk.Debug(whisk.DbgError, "web-export annotation value is false\n", weVal)
-            } else {
-                err = nil
-            }
+
+        if action.WebAction() {
+            err = nil
         }
     }
 
     client.Namespace = savedNs
+
     return err
 }
 
@@ -922,6 +931,7 @@ func init() {
     actionInvokeCmd.Flags().BoolVarP(&Flags.action.result, "result", "r", false, wski18n.T("blocking invoke; show only activation result (unless there is a failure)"))
 
     actionGetCmd.Flags().BoolVarP(&Flags.common.summary, "summary", "s", false, wski18n.T("summarize action details"))
+    actionGetCmd.Flags().BoolVarP(&Flags.action.url, "url", "r", false, wski18n.T("get action url"))
 
     actionListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
     actionListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
diff --git a/commands/api.go b/commands/api.go
index 968c8b7..b58b4ed 100644
--- a/commands/api.go
+++ b/commands/api.go
@@ -1567,9 +1567,9 @@ func getUserContextId() (string, error) {
 func init() {
     apiCreateCmd.Flags().StringVarP(&Flags.api.apiname, "apiname", "n", "", wski18n.T("Friendly name of the API; ignored when CFG_FILE is specified (default BASE_PATH)"))
     apiCreateCmd.Flags().StringVarP(&Flags.api.configfile, "config-file", "c", "", wski18n.T("`CFG_FILE` containing API configuration in swagger JSON format"))
-    //apiUpdateCmd.Flags().StringVarP(&flags.api.action, "action", "a", "", wski18n.T("`ACTION` to invoke when API is called"))
-    //apiUpdateCmd.Flags().StringVarP(&flags.api.path, "path", "p", "", wski18n.T("relative `PATH` of API"))
-    //apiUpdateCmd.Flags().StringVarP(&flags.api.verb, "method", "m", "", wski18n.T("API `VERB`"))
+    //apiUpdateCmd.Flags().StringVarP(&Flags.api.action, "action", "a", "", wski18n.T("`ACTION` to invoke when API is called"))
+    //apiUpdateCmd.Flags().StringVarP(&Flags.api.path, "path", "p", "", wski18n.T("relative `PATH` of API"))
+    //apiUpdateCmd.Flags().StringVarP(&Flags.api.verb, "method", "m", "", wski18n.T("API `VERB`"))
     apiGetCmd.Flags().BoolVarP(&Flags.common.detail, "full", "f", false, wski18n.T("display full API configuration details"))
     apiListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
     apiListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
diff --git a/commands/flags.go b/commands/flags.go
index 5695be8..4dbf12a 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -126,6 +126,7 @@ type ActionFlags struct {
     result      bool
     kind        string
     main        string
+    url         bool
 }
 
 func IsVerbose() bool {
diff --git a/commands/util.go b/commands/util.go
index 96e205a..e010914 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -488,26 +488,11 @@ func getKeys(keyValueArr whisk.KeyValueArr) ([]string) {
     return res
 }
 
-func getValue(keyValueArr whisk.KeyValueArr, key string) (interface{}) {
-    var res interface{}
-
-    for i := 0; i < len(keyValueArr); i++ {
-        if keyValueArr[i].Key == key {
-            res = keyValueArr[i].Value
-            break;
-        }
-    }
-
-    whisk.Debug(whisk.DbgInfo, "Got value '%v' from '%v' for key '%s'\n", res, keyValueArr, key)
-
-    return res
-}
-
 func getValueString(keyValueArr whisk.KeyValueArr, key string) (string) {
     var value interface{}
     var res string
 
-    value = getValue(keyValueArr, key)
+    value = keyValueArr.GetValue(key)
     castedValue, canCast := value.(string)
 
     if (canCast) {
@@ -523,7 +508,7 @@ func getChildValues(keyValueArr whisk.KeyValueArr, key string, childKey string)
     var value interface{}
     var res []interface{}
 
-    value = getValue(keyValueArr, key)
+    value = keyValueArr.GetValue(key)
 
     castedValue, canCast := value.([]interface{})
     if canCast {
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index ec409ad..bcc776d 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -1466,5 +1466,9 @@
   {
     "id": "An entity name, '{{.name}}', was provided instead of a namespace. Valid namespaces are of the following format: /NAMESPACE.",
     "translation": "An entity name, '{{.name}}', was provided instead of a namespace. Valid namespaces are of the following format: /NAMESPACE."
+  },
+  {
+    "id": "get action url",
+    "translation": "get action url"
   }
 ]

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 07/09: Get Action URL from CLI (#2461)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2339ec3f0e267b04a2562d53acd4f95f72957f96
Author: James Dubee <jw...@us.ibm.com>
AuthorDate: Wed Jul 12 13:20:40 2017 -0400

    Get Action URL from CLI (#2461)
---
 .../whisk/core/cli/test/WskBasicUsageTests.scala   | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)

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 faef3dd..ea2c8d4 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -21,6 +21,7 @@ import java.io.File
 import java.io.BufferedWriter
 import java.io.FileWriter
 import java.time.Instant
+import java.net.URLEncoder
 
 import scala.language.postfixOps
 import scala.concurrent.duration.Duration
@@ -696,6 +697,63 @@ class WskBasicUsageTests
             }
     }
 
+    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 (user, namespace) = WskAdmin.getUser(wskprops.authKey)
+            val encodedActionName = URLEncoder.encode(actionName, "UTF-8").replace("+", "%20")
+            val encodedPackageName = URLEncoder.encode(packageName, "UTF-8").replace("+", "%20")
+            val encodedWebActionName = URLEncoder.encode(webActionName, "UTF-8").replace("+", "%20")
+            val encodedNamespace = URLEncoder.encode(namespace, "UTF-8").replace("+", "%20")
+            val actionPath = "https://%s/api/%s/namespaces/%s/actions/%s"
+            val packagedActionPath = s"$actionPath/%s"
+            val webActionPath = "https://%s/api/%s/web/%s/%s/%s"
+
+            assetHelper.withCleaner(wsk.action, actionName) {
+                (action, _) => action.create(actionName, defaultAction)
+            }
+
+            assetHelper.withCleaner(wsk.action, webActionName) {
+                (action, _) => action.create(webActionName, defaultAction, web = Some("true"))
+            }
+
+            assetHelper.withCleaner(wsk.pkg, packageName) {
+                (pkg, _) => pkg.create(packageName)
+            }
+
+            assetHelper.withCleaner(wsk.action, packagedAction) {
+                (action, _) => action.create(packagedAction, defaultAction)
+            }
+
+            assetHelper.withCleaner(wsk.action, packagedWebAction) {
+                (action, _) => action.create(packagedWebAction, defaultAction, web = Some("true"))
+            }
+
+            wsk.action.get(actionName, url = Some(true)).
+                stdout should include(actionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+
+            // 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(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+
+            wsk.action.get(webActionName, url = Some(true)).
+                stdout should include(webActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, defaultPackageName, encodedWebActionName))
+
+            wsk.action.get(packagedAction, url = Some(true)).
+                stdout should include(packagedActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedActionName))
+
+            wsk.action.get(packagedWebAction, url = Some(true)).
+                stdout should include(webActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedWebActionName))
+
+            wsk.action.get(nonExistentActionName, url = Some(true), expectedExitCode = NOT_FOUND)
+    }
+
     behavior of "Wsk packages"
 
     it should "create, and delete a package" in {

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 09/09: Add subject with a namespace. (#2291)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7859b711a4a73345f4d60657c040f6089182298b
Author: rodric rabbah <ro...@gmail.com>
AuthorDate: Fri Jul 14 19:02:24 2017 -0400

    Add subject with a namespace. (#2291)
    
    - Add a test that should catch future regressions where a key is installed incorrectly.
    - Add a helper to retrieve namespace for a key.
    - Eliminate use of wskadmin in tests to lookup a namespace from a key.
    - Delete deprecated WhiskAuth
    - Rename WhiskAuthV2 to WhiskAuth.
    - Fix all tests for WhiskAuth removal.
---
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |   7 +-
 .../test/scala/system/basic/WskBasicTests.scala    | 340 ++++++++++-----------
 .../scala/whisk/core/admin/WskAdminTests.scala     |  20 +-
 .../scala/whisk/core/cli/test/ApiGwTests.scala     |  17 +-
 .../core/cli/test/WskActionSequenceTests.scala     |   6 +-
 .../whisk/core/cli/test/WskBasicUsageTests.scala   |  29 +-
 .../whisk/core/cli/test/WskEntitlementTests.scala  |   3 +-
 .../whisk/core/cli/test/WskWebActionsTests.scala   |   3 +-
 8 files changed, 202 insertions(+), 223 deletions(-)

diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
index d1bc472..49cfbf7 100644
--- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
@@ -35,7 +35,6 @@ import common.TestHelpers
 import common.TestCLIUtils
 import common.TestUtils._
 import common.Wsk
-import common.WskAdmin
 import common.WskProps
 import common.WskPropsV2
 import common.WskTestHelpers
@@ -57,7 +56,7 @@ class ApiGwEndToEndTests
 
     implicit val wskprops = WskProps()
     val wsk = new Wsk
-    val (cliuser, clinamespace) = WskAdmin.getUser(wskprops.authKey)
+    val clinamespace = wsk.namespace.whois()
 
     // Custom CLI properties file
     val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
@@ -85,7 +84,7 @@ class ApiGwEndToEndTests
         val urlqueryvalue = "test"
 
         try {
-            println("cli user: " + cliuser + "; cli namespace: " + clinamespace)
+            println("cli namespace: " + clinamespace)
 
             // Create the action for the API
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -155,7 +154,7 @@ class ApiGwEndToEndTests
         val urlqueryvalue = "test"
 
         try {
-            println("cli user: " + cliuser + "; cli namespace: " + clinamespace)
+            println("cli namespace: " + clinamespace)
 
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo-web-http.js")
diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala
index 65ebc04..ef86c1b 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -20,6 +20,9 @@ package system.basic
 import java.io.File
 import java.time.Instant
 
+import scala.concurrent.duration.DurationInt
+import scala.language.postfixOps
+
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
 
@@ -29,12 +32,9 @@ import common.TestUtils._
 import common.Wsk
 import common.WskProps
 import common.WskTestHelpers
-
 import spray.json._
 import spray.json.DefaultJsonProtocol._
 import spray.json.pimpAny
-import scala.concurrent.duration.DurationInt
-import scala.language.postfixOps
 
 @RunWith(classOf[JUnitRunner])
 class WskBasicTests
@@ -138,17 +138,16 @@ class WskBasicTests
                         "description" -> JsString("Parameter description 2"))))
 
             assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) =>
-                    pkg.create(packageName, annotations = packageAnnots)
+                (pkg, _) => pkg.create(packageName, annotations = packageAnnots)
             }
 
             wsk.action.create(packageName + "/" + actionName, defaultAction, annotations = actionAnnots)
             val stdout = wsk.pkg.get(packageName, summary = true).stdout
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val ns = wsk.namespace.whois()
             wsk.action.delete(packageName + "/" + actionName)
 
-            stdout should include regex (s"(?i)package /${ns_regex_list}/${packageName}: Package description\\s*\\(parameters: paramName1, paramName2\\)")
-            stdout should include regex (s"(?i)action /${ns_regex_list}/${packageName}/${actionName}: Action description\\s*\\(parameters: paramName1, paramName2\\)")
+            stdout should include regex (s"(?i)package /$ns/$packageName: Package description\\s*\\(parameters: paramName1, paramName2\\)")
+            stdout should include regex (s"(?i)action /$ns/$packageName/$actionName: Action description\\s*\\(parameters: paramName1, paramName2\\)")
     }
 
     it should "create a package with a name that contains spaces" in withAssetCleaner(wskprops) {
@@ -156,8 +155,7 @@ class WskBasicTests
             val name = "package with spaces"
 
             val res = assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name)
+                (pkg, _) => pkg.create(name)
             }
 
             res.stdout should include(s"ok: created package $name")
@@ -173,12 +171,10 @@ class WskBasicTests
                 (pkg, _) => pkg.create(name, parameters = paramInput)
             }
 
-            val expectedParam = JsObject(
-                "payload" -> JsString("test"))
-
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val expectedParam = JsObject("payload" -> JsString("test"))
+            val ns = wsk.namespace.whois()
 
-            wsk.pkg.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
+            wsk.pkg.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
             wsk.pkg.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
             wsk.pkg.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
             wsk.pkg.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
@@ -189,10 +185,9 @@ class WskBasicTests
     it should "reject creation of duplication packages" in withAssetCleaner(wskprops) {
         val name = "dupePackage"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) => pkg.create(name)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.pkg, name) {
+            (pkg, _) => pkg.create(name)
+        }
 
         val stderr = wsk.pkg.create(name, expectedExitCode = CONFLICT).stderr
         stderr should include regex (s"""Unable to create package '$name': resource already exists \\(code \\d+\\)""")
@@ -228,6 +223,7 @@ class WskBasicTests
                     action.create(name, file, parameters = params)
                     action.create(name, None, parameters = Map("b" -> "B".toJson), update = true)
             }
+
             val stdout = wsk.action.get(name).stdout
             stdout should not include regex(""""key": "a"""")
             stdout should not include regex(""""value": "A"""")
@@ -242,13 +238,12 @@ class WskBasicTests
         val name = "dupeAction"
         val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            (action, _) => action.create(name, file)
+        }
 
-            val stderr = wsk.action.create(name, file, expectedExitCode = CONFLICT).stderr
-            stderr should include regex (s"""Unable to create action '$name': resource already exists \\(code \\d+\\)""")
+        val stderr = wsk.action.create(name, file, expectedExitCode = CONFLICT).stderr
+        stderr should include regex (s"""Unable to create action '$name': resource already exists \\(code \\d+\\)""")
     }
 
     it should "reject delete of action that does not exist" in {
@@ -271,40 +266,38 @@ class WskBasicTests
 
     it should "create, and invoke an action that utilizes a docker container" in withAssetCleaner(wskprops) {
         val name = "dockerContainer"
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                // this docker image will be need to be pulled from dockerhub and hence has to be published there first
-                (action, _) => action.create(name, None, docker = Some("openwhisk/example"))
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            // this docker image will be need to be pulled from dockerhub and hence has to be published there first
+            (action, _) => action.create(name, None, docker = Some("openwhisk/example"))
+        }
 
-            val args = Map("payload" -> "test".toJson)
-            val run = wsk.action.invoke(name, args)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(JsObject(
-                        "args" -> args.toJson,
-                        "msg" -> "Hello from arbitrary C program!".toJson))
-            }
+        val args = Map("payload" -> "test".toJson)
+        val run = wsk.action.invoke(name, args)
+        withActivation(wsk.activation, run) {
+            activation =>
+                activation.response.result shouldBe Some(JsObject(
+                    "args" -> args.toJson,
+                    "msg" -> "Hello from arbitrary C program!".toJson))
+        }
     }
 
     it should "create, and invoke an action that utilizes dockerskeleton with native zip" in withAssetCleaner(wskprops) {
         val name = "dockerContainerWithZip"
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                // this docker image will be need to be pulled from dockerhub and hence has to be published there first
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            // this docker image will be need to be pulled from dockerhub and hence has to be published there first
+            (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
+        }
 
-            val run = wsk.action.invoke(name, Map())
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(JsObject(
-                        "msg" -> "hello zip".toJson))
-                    activation.logs shouldBe defined
-                    val logs = activation.logs.get.toString
-                    logs should include("This is an example zip used with the docker skeleton action.")
-                    logs should not include ("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX")
-            }
+        val run = wsk.action.invoke(name, Map())
+        withActivation(wsk.activation, run) {
+            activation =>
+                activation.response.result shouldBe Some(JsObject(
+                    "msg" -> "hello zip".toJson))
+                activation.logs shouldBe defined
+                val logs = activation.logs.get.toString
+                logs should include("This is an example zip used with the docker skeleton action.")
+                logs should not include ("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX")
+        }
     }
 
     it should "create, and invoke an action using a parameter file" in withAssetCleaner(wskprops) {
@@ -312,18 +305,15 @@ class WskBasicTests
         val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
         val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            (action, _) => action.create(name, file)
+        }
 
-            val expectedOutput = JsObject(
-                "payload" -> JsString("test"))
-            val run = wsk.action.invoke(name, parameterFile = argInput)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(expectedOutput)
-            }
+        val expectedOutput = JsObject("payload" -> JsString("test"))
+        val run = wsk.action.invoke(name, parameterFile = argInput)
+        withActivation(wsk.activation, run) {
+            activation => activation.response.result shouldBe Some(expectedOutput)
+        }
     }
 
     it should "create an action, and get its individual fields" in withAssetCleaner(wskprops) {
@@ -331,26 +321,23 @@ class WskBasicTests
         val paramInput = Map("payload" -> "test".toJson)
         val successMsg = s"ok: got action $name, displaying field"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, defaultAction, parameters = paramInput)
-            }
-
-            val expectedParam = JsObject(
-                "payload" -> JsString("test"))
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            (action, _) => action.create(name, defaultAction, parameters = paramInput)
+        }
 
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+        val expectedParam = JsObject("payload" -> JsString("test"))
+        val ns = wsk.namespace.whois()
 
-            wsk.action.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-            wsk.action.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-            wsk.action.get(name, fieldFilter = Some("exec")).stdout should include(s"""$successMsg""")
-            wsk.action.get(name, fieldFilter = Some("exec")).stdout should include regex (s"""$successMsg exec\n\\{\\s+"kind":\\s+"nodejs:6",\\s+"code":\\s+"\\/\\*\\*[\\\\r]*\\\\n \\* Hello, world.[\\\\r]*\\\\n \\*\\/[\\\\r]*\\\\nfunction main\\(params\\) \\{[\\\\r]*\\\\n    greeting \\= 'hello, ' \\+ params.payload \\+ '!'[\\\\r]*\\\\n    console.log\\(greeting\\);[\\\\r]*\\\\n    return \\{payload: greeting\\}[\\\\r]*\\\\n\\}""")
-            wsk.action.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
-            wsk.action.get(name, fieldFilter = Some("annotations")).stdout should include regex (s"""$successMsg annotations\n\\[\\s+\\{\\s+"key":\\s+"exec",\\s+"value":\\s+"nodejs:6"\\s+\\}\\s+\\]""")
-            wsk.action.get(name, fieldFilter = Some("limits")).stdout should include regex (s"""$successMsg limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10\\s+\\}""")
-            wsk.action.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
-            wsk.action.get(name, fieldFilter = Some("invalid"), expectedExitCode = MISUSE_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
-            wsk.action.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+        wsk.action.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+        wsk.action.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+        wsk.action.get(name, fieldFilter = Some("exec")).stdout should include(s"""$successMsg""")
+        wsk.action.get(name, fieldFilter = Some("exec")).stdout should include regex (s"""$successMsg exec\n\\{\\s+"kind":\\s+"nodejs:6",\\s+"code":\\s+"\\/\\*\\*[\\\\r]*\\\\n \\* Hello, world.[\\\\r]*\\\\n \\*\\/[\\\\r]*\\\\nfunction main\\(params\\) \\{[\\\\r]*\\\\n    greeting \\= 'hello, ' \\+ params.payload \\+ '!'[\\\\r]*\\\\n    console.log\\(greeting\\);[\\\\r]*\\\\n    return \\{payload: greeting\\}[\\\\r]*\\\\n\\}""")
+        wsk.action.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
+        wsk.action.get(name, fieldFilter = Some("annotations")).stdout should include regex (s"""$successMsg annotations\n\\[\\s+\\{\\s+"key":\\s+"exec",\\s+"value":\\s+"nodejs:6"\\s+\\}\\s+\\]""")
+        wsk.action.get(name, fieldFilter = Some("limits")).stdout should include regex (s"""$successMsg limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10\\s+\\}""")
+        wsk.action.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+        wsk.action.get(name, fieldFilter = Some("invalid"), expectedExitCode = MISUSE_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
+        wsk.action.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
     }
 
     /**
@@ -414,6 +401,7 @@ class WskBasicTests
             assetHelper.withCleaner(wsk.action, name) {
                 (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("wc.js")))
             }
+
             wsk.action.invoke(name, Map("payload" -> "one two three".toJson), result = true)
                 .stdout should include regex (""""count": 3""")
     }
@@ -437,9 +425,9 @@ class WskBasicTests
             }
 
             val stdout = wsk.action.get(name, summary = true).stdout
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val ns = wsk.namespace.whois()
 
-            stdout should include regex (s"(?i)action /${ns_regex_list}/${name}: Action description\\s*\\(parameters: paramName1, paramName2\\)")
+            stdout should include regex (s"(?i)action /$ns/$name: Action description\\s*\\(parameters: paramName1, paramName2\\)")
     }
 
     it should "create an action with a name that contains spaces" in withAssetCleaner(wskprops) {
@@ -484,12 +472,11 @@ class WskBasicTests
 
     it should "create, and get docker action get ensure exec code is omitted" in withAssetCleaner(wskprops) {
         val name = "dockerContainer"
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, None, docker = Some("fake-container"))
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
+            (action, _) => action.create(name, None, docker = Some("fake-container"))
+        }
 
-            wsk.action.get(name).stdout should not include (""""code"""")
+        wsk.action.get(name).stdout should not include (""""code"""")
     }
 
     behavior of "Wsk Trigger CLI"
@@ -548,9 +535,9 @@ class WskBasicTests
             }
 
             val stdout = wsk.trigger.get(name, summary = true).stdout
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val ns = wsk.namespace.whois()
 
-            stdout should include regex (s"trigger /${ns_regex_list}/${name}: Trigger description\\s*\\(parameters: paramName1, paramName2\\)")
+            stdout should include regex (s"trigger /$ns/$name: Trigger description\\s*\\(parameters: paramName1, paramName2\\)")
     }
 
     it should "create a trigger with a name that contains spaces" in withAssetCleaner(wskprops) {
@@ -558,8 +545,7 @@ class WskBasicTests
             val name = "trigger with spaces"
 
             val res = assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name)
+                (trigger, _) => trigger.create(name)
             }
 
             res.stdout should include regex (s"ok: created trigger $name")
@@ -570,19 +556,15 @@ class WskBasicTests
         val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
         val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
+            (trigger, _) => trigger.create(name)
+        }
 
-            val expectedOutput = JsObject(
-                "payload" -> JsString("test"))
-            val run = wsk.trigger.fire(name, parameterFile = argInput)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(expectedOutput)
-            }
+        val expectedOutput = JsObject("payload" -> JsString("test"))
+        val run = wsk.trigger.fire(name, parameterFile = argInput)
+        withActivation(wsk.activation, run) {
+            activation => activation.response.result shouldBe Some(expectedOutput)
+        }
     }
 
     it should "create a trigger, and get its individual fields" in withAssetCleaner(wskprops) {
@@ -590,53 +572,47 @@ class WskBasicTests
         val paramInput = Map("payload" -> "test".toJson)
         val successMsg = s"ok: got trigger $name, displaying field"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, parameters = paramInput)
-            }
-
-            val expectedParam = JsObject(
-                "payload" -> JsString("test"))
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
+            (trigger, _) => trigger.create(name, parameters = paramInput)
+        }
 
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+        val expectedParam = JsObject("payload" -> JsString("test"))
+        val ns = wsk.namespace.whois()
 
-            wsk.trigger.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
-            wsk.trigger.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-            wsk.trigger.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-            wsk.trigger.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-            wsk.trigger.get(name, fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
-            wsk.trigger.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
-            wsk.trigger.get(name, fieldFilter = Some("limits")).stdout should include(s"""$successMsg limits\n{}""")
-            wsk.trigger.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
+        wsk.trigger.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+        wsk.trigger.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+        wsk.trigger.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+        wsk.trigger.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+        wsk.trigger.get(name, fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
+        wsk.trigger.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
+        wsk.trigger.get(name, fieldFilter = Some("limits")).stdout should include(s"""$successMsg limits\n{}""")
+        wsk.trigger.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
     }
 
     it should "create, and fire a trigger to ensure result is empty" in withAssetCleaner(wskprops) {
         (wp, assetHelper) =>
             val name = "emptyResultTrigger"
             assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name)
+                (trigger, _) => trigger.create(name)
             }
 
             val run = wsk.trigger.fire(name)
             withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(JsObject())
+                activation => activation.response.result shouldBe Some(JsObject())
             }
     }
 
     it should "reject creation of duplicate triggers" in withAssetCleaner(wskprops) {
         val name = "dupeTrigger"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) => trigger.create(name)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
+            (trigger, _) => trigger.create(name)
+        }
 
         val stderr = wsk.trigger.create(name, expectedExitCode = CONFLICT).stderr
         stderr should include regex (s"""Unable to create trigger '$name': resource already exists \\(code \\d+\\)""")
     }
+
     it should "reject delete of trigger that does not exist" in {
         val name = "nonexistentTrigger"
         val stderr = wsk.trigger.delete(name, expectedExitCode = NOT_FOUND).stderr
@@ -698,8 +674,7 @@ class WskBasicTests
                 (action, name) => action.create(name, defaultAction)
             }
             assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) =>
-                    rule.create(name, trigger = triggerName, action = actionName)
+                (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
             }
 
             val stdout = wsk.rule.get(ruleName).stdout
@@ -721,11 +696,12 @@ class WskBasicTests
             assetHelper.withCleaner(wsk.rule, ruleName, confirmDelete = false) {
                 (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
             }
+
             // Summary namespace should match one of the allowable namespaces (typically 'guest')
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val ns = wsk.namespace.whois()
             val stdout = wsk.rule.get(ruleName, summary = true).stdout
 
-            stdout should include regex (s"(?i)rule /${ns_regex_list}/${ruleName}\\s*\\(status: active\\)")
+            stdout should include regex (s"(?i)rule /$ns/$ruleName\\s*\\(status: active\\)")
     }
 
     it should "create a rule, and get its individual fields" in withAssetCleaner(wskprops) {
@@ -735,32 +711,29 @@ class WskBasicTests
         val paramInput = Map("payload" -> "test".toJson)
         val successMsg = s"ok: got rule $ruleName, displaying field"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) =>
-                    rule.create(name, trigger = triggerName, action = actionName)
-            }
-
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, triggerName) {
+            (trigger, name) => trigger.create(name)
+        }
+        assetHelper.withCleaner(wsk.action, actionName) {
+            (action, name) => action.create(name, defaultAction)
+        }
+        assetHelper.withCleaner(wsk.rule, ruleName) {
+            (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
+        }
 
-            wsk.rule.get(ruleName, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
-            wsk.rule.get(ruleName, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$ruleName"""")
-            wsk.rule.get(ruleName, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"\n""")
-            wsk.rule.get(ruleName, fieldFilter = Some("status")).stdout should include(s"""$successMsg status\n"active"""")
-            val trigger = wsk.rule.get(ruleName, fieldFilter = Some("trigger")).stdout
-            trigger should include regex (s"""$successMsg trigger\n""")
-            trigger should include(triggerName)
-            trigger should not include (actionName)
-            val action = wsk.rule.get(ruleName, fieldFilter = Some("action")).stdout
-            action should include regex (s"""$successMsg action\n""")
-            action should include(actionName)
-            action should not include (triggerName)
+        val ns = wsk.namespace.whois()
+        wsk.rule.get(ruleName, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+        wsk.rule.get(ruleName, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$ruleName"""")
+        wsk.rule.get(ruleName, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"\n""")
+        wsk.rule.get(ruleName, fieldFilter = Some("status")).stdout should include(s"""$successMsg status\n"active"""")
+        val trigger = wsk.rule.get(ruleName, fieldFilter = Some("trigger")).stdout
+        trigger should include regex (s"""$successMsg trigger\n""")
+        trigger should include(triggerName)
+        trigger should not include (actionName)
+        val action = wsk.rule.get(ruleName, fieldFilter = Some("action")).stdout
+        action should include regex (s"""$successMsg action\n""")
+        action should include(actionName)
+        action should not include (triggerName)
     }
 
     it should "reject creation of duplicate rules" in withAssetCleaner(wskprops) {
@@ -768,17 +741,15 @@ class WskBasicTests
         val triggerName = "triggerName"
         val actionName = "actionName"
 
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) =>
-                    rule.create(name, trigger = triggerName, action = actionName)
-            }
+        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, triggerName) {
+            (trigger, name) => trigger.create(name)
+        }
+        assetHelper.withCleaner(wsk.action, actionName) {
+            (action, name) => action.create(name, defaultAction)
+        }
+        assetHelper.withCleaner(wsk.rule, ruleName) {
+            (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
+        }
 
         val stderr = wsk.rule.create(ruleName, trigger = triggerName, action = actionName, expectedExitCode = CONFLICT).stderr
         stderr should include regex (s"""Unable to create rule '$ruleName': resource already exists \\(code \\d+\\)""")
@@ -817,8 +788,10 @@ class WskBasicTests
     behavior of "Wsk Namespace CLI"
 
     it should "return a list of exactly one namespace" in {
-        wsk.namespace.list().
-            stdout.lines should have size 2 // headline + namespace
+        val lines = wsk.namespace.list().stdout.lines.toSeq
+        lines should have size 2
+        lines.head shouldBe "namespaces"
+        lines(1).trim should not be empty
     }
 
     it should "list entities in default namespace" in {
@@ -846,13 +819,12 @@ class WskBasicTests
                     trigger.create(name)
             }
 
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
-
+            val ns = s""""${wsk.namespace.whois()}""""
             val run = wsk.trigger.fire(name)
             withActivation(wsk.activation, run) {
                 activation =>
                     val successMsg = s"ok: got activation ${activation.activationId}, displaying field"
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns""")
                     wsk.activation.get(Some(activation.activationId), fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
                     wsk.activation.get(Some(activation.activationId), fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
                     wsk.activation.get(Some(activation.activationId), fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
@@ -866,19 +838,19 @@ class WskBasicTests
     }
 
     it should "reject get of activation that does not exist" in {
-        val name = "0"*32
+        val name = "0" * 32
         val stderr = wsk.activation.get(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
 
     it should "reject logs of activation that does not exist" in {
-        val name = "0"*32
+        val name = "0" * 32
         val stderr = wsk.activation.logs(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get logs for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
 
     it should "reject result of activation that does not exist" in {
-        val name = "0"*32
+        val name = "0" * 32
         val stderr = wsk.activation.result(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get result for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
@@ -895,7 +867,7 @@ class WskBasicTests
             val includeID = wsk.activation.extractActivationId(lastInvoke).get
             Thread.sleep(1000)
 
-            var  lastFlag = Seq (
+            val lastFlag = Seq(
                 (Seq("activation", "get", "publish", "--last"), includeID),
                 (Seq("activation", "get", "--last"), includeID),
                 (Seq("activation", "logs", "--last"), includeStr),
@@ -912,15 +884,15 @@ class WskBasicTests
         (wp, assetHelper) =>
             val auth: Seq[String] = Seq("--auth", wskprops.authKey)
 
-             assetHelper.withCleaner(wsk.action, "lastName") {
-                 (action, _) => wsk.action.create("lastName", defaultAction)
-             }
+            assetHelper.withCleaner(wsk.action, "lastName") {
+                (action, _) => wsk.action.create("lastName", defaultAction)
+            }
             val lastId = wsk.activation.extractActivationId(wsk.action.invoke("lastName")).get
             val tooManyArgsMsg = s"${lastId}. An activation ID is required."
             val invalidField = s"Invalid field filter '${lastId}'."
             Thread.sleep(1000)
 
-            var  invalidCmd = Seq (
+            val invalidCmd = Seq(
                 (Seq("activation", "get", s"$lastId", "publish", "--last"), tooManyArgsMsg),
                 (Seq("activation", "get", s"$lastId", "--last"), invalidField),
                 (Seq("activation", "logs", s"$lastId", "--last"), tooManyArgsMsg),
@@ -931,5 +903,5 @@ class WskBasicTests
                     val stderr = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = ERROR_EXIT).stderr
                     stderr should include(err)
             }
-     }
+    }
 }
diff --git a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
index e5ab26c..ec4cf59 100644
--- a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
+++ b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
@@ -25,10 +25,11 @@ import org.scalatest.junit.JUnitRunner
 
 import common.RunWskAdminCmd
 import common.TestHelpers
+import common.Wsk
 import common.WskAdmin
+import common.WskProps
 import whisk.core.entity.AuthKey
 import whisk.core.entity.Subject
-import whisk.core.entity.WhiskAuth
 
 @RunWith(classOf[JUnitRunner])
 class WskAdminTests
@@ -43,8 +44,8 @@ class WskAdminTests
 
     it should "CRD a subject" in {
         val wskadmin = new RunWskAdminCmd {}
-        val auth = WhiskAuth(Subject(), AuthKey())
-        val subject = auth.subject.asString
+        val auth = AuthKey()
+        val subject = Subject().asString
         try {
             println(s"CRD subject: $subject")
             val create = wskadmin.cli(Seq("user", "create", subject))
@@ -67,14 +68,14 @@ class WskAdminTests
 
             // recreate with explicit
             val newspace = s"${subject}.myspace"
-            wskadmin.cli(Seq("user", "create", subject, "-ns", newspace, "-u", auth.authkey.compact))
+            wskadmin.cli(Seq("user", "create", subject, "-ns", newspace, "-u", auth.compact))
 
             whisk.utils.retry({
                 // reverse lookup by namespace
-                wskadmin.cli(Seq("user", "list", "-k", newspace)).stdout.trim should be(auth.authkey.compact)
+                wskadmin.cli(Seq("user", "list", "-k", newspace)).stdout.trim should be(auth.compact)
             }, 10, Some(1.second))
 
-            wskadmin.cli(Seq("user", "get", subject, "-ns", newspace)).stdout.trim should be(auth.authkey.compact)
+            wskadmin.cli(Seq("user", "get", subject, "-ns", newspace)).stdout.trim should be(auth.compact)
 
             // delete namespace
             wskadmin.cli(Seq("user", "delete", subject, "-ns", newspace)).stdout should include("Namespace deleted")
@@ -83,4 +84,11 @@ class WskAdminTests
         }
     }
 
+    it should "verify guest account installed correctly" in {
+        val wskadmin = new RunWskAdminCmd {}
+        implicit val wskprops = WskProps()
+        val wsk = new Wsk
+        val ns = wsk.namespace.whois()
+        wskadmin.cli(Seq("user", "get", ns)).stdout.trim should be(wskprops.authKey)
+    }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index aadb929..aa3fd84 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -29,7 +29,6 @@ import common.TestUtils._
 import common.TestCLIUtils
 import common.WhiskProperties
 import common.Wsk
-import common.WskAdmin
 import common.WskProps
 import common.WskPropsV2
 import common.WskTestHelpers
@@ -45,7 +44,7 @@ class ApiGwTests
 
     implicit var wskprops = WskProps()
     val wsk = new Wsk
-    val (cliuser, clinamespace) = WskAdmin.getUser(wskprops.authKey)
+    val clinamespace = wsk.namespace.whois()
 
     // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk
     // throttling restriction.  To avoid CLI failures due to being throttled, track the
@@ -229,7 +228,7 @@ class ApiGwTests
         val testapiname = testName + " API Name"
         val actionName = testName + "_action"
         try {
-            println("cli user: " + cliuser + "; cli namespace: " + clinamespace)
+            println("cli namespace: " + clinamespace)
 
             var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
             println("api create: " + rr.stdout)
@@ -259,7 +258,7 @@ class ApiGwTests
         val testapiname = testName+" API Name"
         val actionName = testName+"_action"
         try {
-            println("cli user: "+cliuser+"; cli namespace: "+clinamespace)
+            println("cli namespace: "+clinamespace)
 
             var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
             rr.stdout should include("ok: created API")
@@ -434,7 +433,7 @@ class ApiGwTests
         val testapiname = testName+" API Name"
         val actionName = testName+"a-c@t ion"
         try {
-            println("cli user: "+cliuser+"; cli namespace: "+clinamespace)
+            println("cli namespace: "+clinamespace)
 
             var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
             rr.stdout should include("ok: created API")
@@ -612,7 +611,7 @@ class ApiGwTests
         val testapiname = testName + " API Name"
         val actionName = testName + "_action"
         try {
-            println("cli user: " + cliuser + "; cli namespace: " + clinamespace)
+            println("cli namespace: " + clinamespace)
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
@@ -646,7 +645,7 @@ class ApiGwTests
         val testapiname = testName+" API Name"
         val actionName = testName+"_action"
         try {
-            println("cli user: "+cliuser+"; cli namespace: "+clinamespace)
+            println("cli namespace: "+clinamespace)
 
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -856,7 +855,7 @@ class ApiGwTests
         val testapiname = testName+" API Name"
         val actionName = testName+"a-c@t ion"
         try {
-            println("cli user: "+cliuser+"; cli namespace: "+clinamespace)
+            println("cli namespace: "+clinamespace)
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
@@ -1256,7 +1255,7 @@ class ApiGwTests
         val wskpropsBackup = wskprops
         try {
             // Create the action for the API.
-            val file = TestUtils.getTestActionFilename(s"echo.js")
+            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
             // Set an invalid auth key
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
index d6a2fab..84d4a82 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
@@ -23,10 +23,10 @@ import org.scalatest.junit.JUnitRunner
 import common.TestHelpers
 import common.TestCLIUtils
 import common.Wsk
-import common.WskAdmin
 import common.WskProps
 import common.WskTestHelpers
 import spray.json._
+import whisk.core.entity.EntityPath
 
 /**
  * Tests creation and retrieval of a sequence action
@@ -38,8 +38,8 @@ class WskActionSequenceTests
 
     implicit val wskprops = WskProps()
     val wsk = new Wsk
-    val defaultNamespace = wskprops.namespace
-    val (user, namespace) = WskAdmin.getUser(wskprops.authKey)
+    val defaultNamespace = EntityPath.DEFAULT.asString
+    val namespace = wsk.namespace.whois()
 
     behavior of "Wsk Action Sequence"
 
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 ea2c8d4..987d0ae 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -22,6 +22,8 @@ import java.io.BufferedWriter
 import java.io.FileWriter
 import java.time.Instant
 import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
+import java.time.Clock
 
 import scala.language.postfixOps
 import scala.concurrent.duration.Duration
@@ -50,8 +52,6 @@ import whisk.core.entity.size.SizeInt
 import whisk.utils.retry
 import JsonArgsForTests._
 import whisk.http.Messages
-import common.WskAdmin
-import java.time.Clock
 
 /**
  * Tests for basic CLI usage. Some of these tests require a deployed backend.
@@ -98,10 +98,13 @@ class WskBasicUsageTests
     it should "set apihost, auth, and namespace" in {
         val tmpwskprops = File.createTempFile("wskprops", ".tmp")
         try {
-            val namespace = wsk.namespace.list().stdout.trim.split("\n").last
+            val namespace = wsk.namespace.whois()
             val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            val stdout = wsk.cli(Seq("property", "set", "-i", "--apihost", wskprops.apihost, "--auth", wskprops.authKey,
-                "--namespace", namespace), env = env).stdout
+            val stdout = wsk.cli(Seq("property", "set", "-i",
+                "--apihost", wskprops.apihost,
+                "--auth", wskprops.authKey,
+                "--namespace", namespace),
+                env = env).stdout
             stdout should include(s"ok: whisk auth set")
             stdout should include(s"ok: whisk API host set to ${wskprops.apihost}")
             stdout should include(s"ok: whisk namespace set to ${namespace}")
@@ -521,7 +524,7 @@ class WskBasicUsageTests
 
     it should "invoke an action receiving context properties" in withAssetCleaner(wskprops) {
         (wp, assetHelper) =>
-            val (user, namespace) = WskAdmin.getUser(wskprops.authKey)
+            val namespace = wsk.namespace.whois()
             val name = "context"
             assetHelper.withCleaner(wsk.action, name) {
                 (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloContext.js")))
@@ -706,11 +709,11 @@ class WskBasicUsageTests
             val nonExistentActionName = "non-existence action"
             val packagedAction = s"$packageName/$actionName"
             val packagedWebAction = s"$packageName/$webActionName"
-            val (user, namespace) = WskAdmin.getUser(wskprops.authKey)
-            val encodedActionName = URLEncoder.encode(actionName, "UTF-8").replace("+", "%20")
-            val encodedPackageName = URLEncoder.encode(packageName, "UTF-8").replace("+", "%20")
-            val encodedWebActionName = URLEncoder.encode(webActionName, "UTF-8").replace("+", "%20")
-            val encodedNamespace = URLEncoder.encode(namespace, "UTF-8").replace("+", "%20")
+            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 actionPath = "https://%s/api/%s/namespaces/%s/actions/%s"
             val packagedActionPath = s"$actionPath/%s"
             val webActionPath = "https://%s/api/%s/web/%s/%s/%s"
@@ -906,9 +909,9 @@ class WskBasicUsageTests
             }
 
             // Summary namespace should match one of the allowable namespaces (typically 'guest')
-            val ns_regex_list = wsk.namespace.list().stdout.trim.replace('\n', '|')
+            val ns = wsk.namespace.whois()
             val stdout = wsk.trigger.get(triggerName, summary = true).stdout
-            stdout should include regex (s"(?i)trigger\\s+/${ns_regex_list}/${triggerName}")
+            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) {
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
index 70de2f8..7f83762 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
@@ -27,7 +27,6 @@ import common.TestUtils.FORBIDDEN
 import common.TestUtils.NOT_FOUND
 import common.TestUtils.TIMEOUT
 import common.Wsk
-import common.WskAdmin
 import common.WskProps
 import common.WskTestHelpers
 import spray.json._
@@ -328,7 +327,7 @@ class WskEntitlementTests
             val run = wsk.action.invoke(fullyQualifiedActionName)(defaultWskProps)
 
             withActivation(wsk.activation, run)({ activation =>
-                val (_, namespace) = WskAdmin.getUser(defaultWskProps.authKey)
+                val namespace = wsk.namespace.whois()(defaultWskProps)
                 activation.response.success shouldBe true
                 activation.response.result.get.toString should include regex (s""""namespace":\\s*"$namespace"""")
             })(defaultWskProps)
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index 1f38acd..be6ae04 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -32,7 +32,6 @@ import common.TestHelpers
 import common.TestCLIUtils
 import common.WhiskProperties
 import common.Wsk
-import common.WskAdmin
 import common.WskProps
 import common.WskTestHelpers
 import spray.json._
@@ -132,7 +131,7 @@ trait WskWebActionsTests
 
     val wsk = new Wsk
     private implicit val wskprops = WskProps()
-    val namespace = WskAdmin.getUser(wskprops.authKey)._2
+    val namespace = wsk.namespace.whois()
 
     protected val testRoutePath: String
 

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 08/09: (Review) Added --last Activation Flag (#2334)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit dd1dd2a65e860e40e7ba560a53ea068e80291031
Author: Benjamin Poole <Be...@ibm.com>
AuthorDate: Thu Jul 13 10:00:39 2017 -0400

    (Review) Added --last Activation Flag  (#2334)
    
    * Added lastFlag to activation logs, result and get along with docs/testing
---
 .../test/scala/system/basic/WskBasicTests.scala    | 76 ++++++++++++++++++----
 .../test/scala/system/basic/WskSequenceTests.scala |  4 +-
 2 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala
index 6de37d8..65ebc04 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -852,34 +852,84 @@ class WskBasicTests
             withActivation(wsk.activation, run) {
                 activation =>
                     val successMsg = s"ok: got activation ${activation.activationId}, displaying field"
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("subject")).stdout should include regex (s"""(?i)$successMsg subject\n""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("activationid")).stdout should include(s"""$successMsg activationid\n"${activation.activationId}""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("start")).stdout should include regex (s"""$successMsg start\n\\d""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("end")).stdout should include regex (s"""$successMsg end\n\\d""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("duration")).stdout should include regex (s"""$successMsg duration\n\\d""")
-                    wsk.activation.get(activation.activationId, fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns_regex_list""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("subject")).stdout should include regex (s"""(?i)$successMsg subject\n""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("activationid")).stdout should include(s"""$successMsg activationid\n"${activation.activationId}""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("start")).stdout should include regex (s"""$successMsg start\n\\d""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("end")).stdout should include regex (s"""$successMsg end\n\\d""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("duration")).stdout should include regex (s"""$successMsg duration\n\\d""")
+                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
             }
     }
 
     it should "reject get of activation that does not exist" in {
         val name = "0"*32
-        val stderr = wsk.activation.get(name, expectedExitCode = NOT_FOUND).stderr
+        val stderr = wsk.activation.get(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
 
     it should "reject logs of activation that does not exist" in {
         val name = "0"*32
-        val stderr = wsk.activation.logs(name, expectedExitCode = NOT_FOUND).stderr
+        val stderr = wsk.activation.logs(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get logs for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
 
     it should "reject result of activation that does not exist" in {
         val name = "0"*32
-        val stderr = wsk.activation.result(name, expectedExitCode = NOT_FOUND).stderr
+        val stderr = wsk.activation.result(Some(name), expectedExitCode = NOT_FOUND).stderr
         stderr should include regex (s"""Unable to get result for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
     }
+
+    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!"
+
+            assetHelper.withCleaner(wsk.action, "lastName") {
+                (action, _) => wsk.action.create("lastName", defaultAction)
+            }
+            val lastInvoke = wsk.action.invoke("lastName")
+            val includeID = wsk.activation.extractActivationId(lastInvoke).get
+            Thread.sleep(1000)
+
+            var  lastFlag = Seq (
+                (Seq("activation", "get", "publish", "--last"), includeID),
+                (Seq("activation", "get", "--last"), includeID),
+                (Seq("activation", "logs", "--last"), includeStr),
+                (Seq("activation", "result", "--last"), includeStr))
+
+            lastFlag foreach {
+                case (cmd, output) =>
+                    val stdout = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT).stdout
+                    stdout should include(output)
+            }
+    }
+
+    it should "reject activation request when using activation ID with --last Flag" in withAssetCleaner(wskprops) {
+        (wp, assetHelper) =>
+            val auth: Seq[String] = Seq("--auth", wskprops.authKey)
+
+             assetHelper.withCleaner(wsk.action, "lastName") {
+                 (action, _) => wsk.action.create("lastName", defaultAction)
+             }
+            val lastId = wsk.activation.extractActivationId(wsk.action.invoke("lastName")).get
+            val tooManyArgsMsg = s"${lastId}. An activation ID is required."
+            val invalidField = s"Invalid field filter '${lastId}'."
+            Thread.sleep(1000)
+
+            var  invalidCmd = Seq (
+                (Seq("activation", "get", s"$lastId", "publish", "--last"), tooManyArgsMsg),
+                (Seq("activation", "get", s"$lastId", "--last"), invalidField),
+                (Seq("activation", "logs", s"$lastId", "--last"), tooManyArgsMsg),
+                (Seq("activation", "result", s"$lastId", "--last"), tooManyArgsMsg))
+
+            invalidCmd foreach {
+                case (cmd, err) =>
+                    val stderr = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = ERROR_EXIT).stderr
+                    stderr should include(err)
+            }
+     }
 }
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index a5c483b..0c023c9 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -213,7 +213,7 @@ class WskSequenceTests
                     result.fields.get("error") shouldBe Some(JsString(sequenceIsTooLong))
                     // check that inner sequence had only (limit - 1) activations
                     val innerSeq = activation.logs.get(1) // the id of the inner sequence activation
-                    val getInnerSeq = wsk.activation.get(innerSeq)
+                    val getInnerSeq = wsk.activation.get(Some(innerSeq))
                     withActivation(wsk.activation, getInnerSeq, totalWait = allowedActionDuration) {
                         innerSeqActivation =>
                             innerSeqActivation.logs.get.size shouldBe (limit - 1)
@@ -507,7 +507,7 @@ class WskSequenceTests
         withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
             checkSequenceLogsAndAnnotations(activation, 1)
             val componentId = activation.logs.get(atomicActionIdx)
-            val getComponentActivation = wsk.activation.get(componentId)
+            val getComponentActivation = wsk.activation.get(Some(componentId))
             withActivation(wsk.activation, getComponentActivation, totalWait = allowedActionDuration) { componentActivation =>
                 println(componentActivation)
                 componentActivation.logs shouldBe defined

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 01/09: API GW V2 updates (#2436)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9efabe18be87b8f196c8a951d8164fb4e1b8c39b
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Wed Jul 12 12:46:04 2017 -0400

    API GW V2 updates (#2436)
    
    - Do not enforce need for gwUrl parameter in api gw actions
    - Enable http redirect forwarding
    - Add automated test to validate rejection of api creation with invalid auth key
---
 commands/action.go               | 7 +++++--
 wski18n/resources/en_US.all.json | 8 ++------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/commands/action.go b/commands/action.go
index 6b57621..b4926d9 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -858,9 +858,12 @@ func isWebAction(client *whisk.Client, qname QualifiedName) error {
     if err != nil {
         whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", fullActionName, err)
         whisk.Debug(whisk.DbgError, "Unable to obtain action '%s' for web action validation\n", fullActionName)
-        err = errors.New(wski18n.T("API action '{{.name}}' does not exist", map[string]interface{}{"name": fullActionName}))
+        errMsg := wski18n.T("Unable to get action '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": fullActionName, "err": err})
+        err = whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_NETWORK, whisk.DISPLAY_MSG,
+            whisk.NO_DISPLAY_USAGE)
     } else {
-        err = errors.New(wski18n.T("API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+        err = errors.New(wski18n.T("Action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
             map[string]interface{}{"name": fullActionName}))
         weVal := getValue(action.Annotations, "web-export")
         if (weVal == nil) {
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 765f961..ec409ad 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -1384,12 +1384,8 @@
     "translation": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
   },
   {
-    "id": "API action '{{.name}}' does not exist",
-    "translation": "API action '{{.name}}' does not exist"
-  },
-  {
-    "id": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
-    "translation": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action."
+    "id": "Action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+    "translation": "Action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action."
   },
   {
     "id": "Invalid configuration. The x-openwhisk stanza is missing.",

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 03/09: (Review) Added --last Activation Flag (#2334)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 435bb48d5af97ed83d13897f5bdec0fe096b6a1c
Author: Benjamin Poole <Be...@ibm.com>
AuthorDate: Thu Jul 13 10:00:39 2017 -0400

    (Review) Added --last Activation Flag  (#2334)
    
    * Added lastFlag to activation logs, result and get along with docs/testing
---
 commands/activation.go           | 68 ++++++++++++++++++++++++++++++++++++++--
 commands/flags.go                |  1 +
 wski18n/resources/en_US.all.json | 20 ++++++++++++
 3 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/commands/activation.go b/commands/activation.go
index d7f59b2..c9317cd 100644
--- a/commands/activation.go
+++ b/commands/activation.go
@@ -101,14 +101,22 @@ var activationListCmd = &cobra.Command{
 }
 
 var activationGetCmd = &cobra.Command{
-    Use:   "get ACTIVATION_ID [FIELD_FILTER]",
+    Use:   "get (ACTIVATION_ID | --last) [FIELD_FILTER]",
     Short: wski18n.T("get activation"),
     SilenceUsage:   true,
     SilenceErrors:  true,
     PreRunE: setupClientConfig,
     RunE: func(cmd *cobra.Command, args []string) error {
         var field string
+        var err error
 
+        if args, err = lastFlag(args); err != nil {  // Checks if any errors occured in lastFlag(args)
+          whisk.Debug(whisk.DbgError, "lastFlag(%#v) failed: %s\n", args, err)
+          errStr := wski18n.T("Unable to get activation: {{.err}}",
+            map[string]interface{}{"err": err})
+          werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+          return werr
+        }
         if whiskErr := checkArgs(args, 1, 2, "Activation get",
                 wski18n.T("An activation ID is required.")); whiskErr != nil {
             return whiskErr
@@ -164,13 +172,21 @@ var activationGetCmd = &cobra.Command{
 }
 
 var activationLogsCmd = &cobra.Command{
-    Use:   "logs ACTIVATION_ID",
+    Use:   "logs (ACTIVATION_ID | --last)",
     Short: wski18n.T("get the logs of an activation"),
     SilenceUsage:   true,
     SilenceErrors:  true,
     PreRunE: setupClientConfig,
     RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
+        if args, err = lastFlag(args); err != nil {  // Checks if any errors occured in lastFlag(args)
+          whisk.Debug(whisk.DbgError, "lastFlag(%#v) failed: %s\n", args, err)
+          errStr := wski18n.T("Unable to get logs for activation: {{.err}}",
+            map[string]interface{}{"err": err})
+          werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+          return werr
+        }
         if whiskErr := checkArgs(args, 1, 1, "Activation logs",
                 wski18n.T("An activation ID is required.")); whiskErr != nil {
             return whiskErr
@@ -192,13 +208,21 @@ var activationLogsCmd = &cobra.Command{
 }
 
 var activationResultCmd = &cobra.Command{
-    Use:   "result ACTIVATION_ID",
+    Use:   "result (ACTIVATION_ID | --last)",
     Short: "get the result of an activation",
     SilenceUsage:   true,
     SilenceErrors:  true,
     PreRunE: setupClientConfig,
     RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
 
+        if args, err = lastFlag(args); err != nil {  // Checks if any errors occured in lastFlag(args)
+          whisk.Debug(whisk.DbgError, "lastFlag(%#v) failed: %s\n", args, err)
+          errStr := wski18n.T("Unable to get result for activation: {{.err}}",
+            map[string]interface{}{"err": err})
+          werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+          return werr
+        }
         if whiskErr := checkArgs(args, 1, 1, "Activation result",
                 wski18n.T("An activation ID is required.")); whiskErr != nil {
             return whiskErr
@@ -219,6 +243,39 @@ var activationResultCmd = &cobra.Command{
     },
 }
 
+// lastFlag(args) retrieves the last activation with flag -l or --last
+// Param: Brings in []strings from args
+// Return: Returns a []string with the latest ID or the original args and any errors
+func lastFlag(args []string) ([]string, error) {
+    if Flags.activation.last {
+        options := &whisk.ActivationListOptions {
+            Limit: 1,
+            Skip: 0,
+        }
+        activations,_, err := client.Activations.List(options)
+        if err != nil {    // Checks Activations.List for errors when retrieving latest activaiton
+            whisk.Debug(whisk.DbgError, "client.Activations.List(%#v) error during lastFlag: %s\n", options, err)
+            return args, err
+        }
+        if len(activations) == 0 {    // Checks to to see if there are activations available
+            whisk.Debug(whisk.DbgError, "No activations found in activation list\n")
+            errStr := wski18n.T("Activation list does not contain any activations.")
+            whiskErr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return args, whiskErr
+        }
+        if len(args) == 0 {
+            whisk.Debug(whisk.DbgInfo, "Appending most recent activation ID(%s) into args\n", activations[0].ActivationID)
+            args = append(args, activations[0].ActivationID)
+        } else {
+                whisk.Debug(whisk.DbgInfo, "Appending most recent activation ID(%s) into args\n", activations[0].ActivationID)
+                args = append(args, activations[0].ActivationID)
+                whisk.Debug(whisk.DbgInfo, "Allocating appended ID to correct position in args\n")
+                args[0], args[len(args) - 1] = args[len(args) - 1], args[0]    // IDs should be located at args[0], if 1 or more arguments are given ID has to be moved to args[0]
+        }
+    }
+    return args, nil
+}
+
 var activationPollCmd = &cobra.Command{
     Use:   "poll [ NAMESPACE | ACTION_NAME ]",
     Short: wski18n.T("poll continuously for log messages from currently running actions"),
@@ -341,6 +398,11 @@ func init() {
     activationListCmd.Flags().Int64Var(&Flags.activation.since, "since", 0, wski18n.T("return activations with timestamps later than `SINCE`; measured in milliseconds since Th, 01, Jan 1970"))
 
     activationGetCmd.Flags().BoolVarP(&Flags.common.summary, "summary", "s", false, wski18n.T("summarize activation details"))
+    activationGetCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
+
+    activationLogsCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
+
+    activationResultCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
 
     activationPollCmd.Flags().IntVarP(&Flags.activation.exit, "exit", "e", 0, wski18n.T("stop polling after `SECONDS` seconds"))
     activationPollCmd.Flags().IntVar(&Flags.activation.sinceSeconds, "since-seconds", 0, wski18n.T("start polling for activations `SECONDS` seconds ago"))
diff --git a/commands/flags.go b/commands/flags.go
index 4dbf12a..7357426 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -88,6 +88,7 @@ type FlagsStruct struct {
         sinceHours      int
         sinceDays       int
         exit            int
+        last            bool
     }
 
     // rule
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index bcc776d..535f958 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -948,6 +948,10 @@
     "translation": "get activation"
   },
   {
+    "id": "Unable to get activation: {{.err}}",
+    "translation": "Unable to get activation: {{.err}}"
+  },
+  {
     "id": "Unable to get activation '{{.id}}': {{.err}}",
     "translation": "Unable to get activation '{{.id}}': {{.err}}"
   },
@@ -964,10 +968,18 @@
     "translation": "get the logs of an activation"
   },
   {
+    "id": "Unable to get logs for activation: {{.err}}",
+    "translation": "Unable to get logs for activation: {{.err}}"
+  },
+  {
     "id": "Unable to get logs for activation '{{.id}}': {{.err}}",
     "translation": "Unable to get logs for activation '{{.id}}': {{.err}}"
   },
   {
+    "id": "Unable to get result for activation: {{.err}}",
+    "translation": "Unable to get result for activation: {{.err}}"
+  },
+  {
     "id": "Unable to get result for activation '{{.id}}': {{.err}}",
     "translation": "Unable to get result for activation '{{.id}}': {{.err}}"
   },
@@ -992,6 +1004,10 @@
     "translation": "\nActivation: {{.name}} ({{.id}})\n"
   },
   {
+    "id": "Activation list does not contain any activations.",
+    "translation": "Activation list does not contain any activations."
+  },
+  {
     "id": "exclude the first `SKIP` number of activations from the result",
     "translation": "exclude the first `SKIP` number of activations from the result"
   },
@@ -1016,6 +1032,10 @@
     "translation": "summarize activation details"
   },
   {
+    "id": "retrieves the last activation",
+    "translation": "retrieves the last activation"
+  },
+  {
     "id": "stop polling after `SECONDS` seconds",
     "translation": "stop polling after `SECONDS` seconds"
   },

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 04/09: Externalize access to a few CLI methods to facilitate access across packages (#2483)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a65c3cb8592c99de2e7060d1415225f9deffd39f
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Fri Jul 14 14:40:18 2017 -0400

    Externalize access to a few CLI methods to facilitate access across packages (#2483)
    
    - Also move properties file reading/loading to when the command is executed, not at binary load time
---
 commands/commands.go             | 17 +++++++++--------
 commands/property.go             |  6 +++---
 wski18n/resources/en_US.all.json |  4 ++++
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/commands/commands.go b/commands/commands.go
index 5020ea2..d943f6a 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -19,7 +19,6 @@ package commands
 
 import (
     "errors"
-    "fmt"
     "net/http"
     "os"
 
@@ -75,14 +74,7 @@ func setupClientConfig(cmd *cobra.Command, args []string) (error){
 }
 
 func init() {
-    var err error
 
-    err = loadProperties()
-    if err != nil {
-        whisk.Debug(whisk.DbgError, "loadProperties() error: %s\n", err)
-        fmt.Println(err)
-        os.Exit(whisk.EXITCODE_ERR_GENERAL)
-    }
 }
 
 func getKeyValueArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) {
@@ -211,5 +203,14 @@ func Execute() error {
         return whiskErr
     }
 
+    err = loadProperties()
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "loadProperties() error: %s\n", err)
+        errMsg := wski18n.T("Unable to access configuration properties: {{.err}}", map[string]interface{}{"err":err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return whiskErr
+    }
+
     return WskCmd.Execute()
 }
diff --git a/commands/property.go b/commands/property.go
index 4a2a7e7..a29ab14 100644
--- a/commands/property.go
+++ b/commands/property.go
@@ -349,7 +349,7 @@ func setDefaultProperties() {
     // Properties.CLIVersion value is set from main's init()
 }
 
-func getPropertiesFilePath() (propsFilePath string, werr error) {
+func GetPropertiesFilePath() (propsFilePath string, werr error) {
     var envExists bool
 
     // Environment variable overrides the default properties file path
@@ -381,10 +381,10 @@ func loadProperties() error {
 
     setDefaultProperties()
 
-    Properties.PropsFile, err = getPropertiesFilePath()
+    Properties.PropsFile, err = GetPropertiesFilePath()
     if err != nil {
         return nil
-        //whisk.Debug(whisk.DbgError, "getPropertiesFilePath() failed: %s\n", err)
+        //whisk.Debug(whisk.DbgError, "GetPropertiesFilePath() failed: %s\n", err)
         //errStr := fmt.Sprintf("Unable to load the properties file: %s", err)
         //werr := whisk.MakeWskError(errors.New(errStr), whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
         //return werr
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 535f958..7d3929e 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -381,6 +381,10 @@
     "translation": "Unable to read the properties file '{{.filename}}': {{.err}}"
   },
   {
+    "id": "Unable to access configuration properties: {{.err}}",
+    "translation": "Unable to access configuration properties: {{.err}}"
+  },
+  {
     "id": "Invalid host address '{{.host}}': {{.err}}",
     "translation": "Invalid host address '{{.host}}': {{.err}}"
   },

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 06/09: API GW V2 updates (#2436)

Posted by ho...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5b47f4f5c3d844e331c658985b65227e952c9060
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Wed Jul 12 12:46:04 2017 -0400

    API GW V2 updates (#2436)
    
    - Do not enforce need for gwUrl parameter in api gw actions
    - Enable http redirect forwarding
    - Add automated test to validate rejection of api creation with invalid auth key
---
 .../actions/test/ApiGwRoutemgmtActionTests.scala   |  8 ++---
 .../scala/whisk/core/cli/test/ApiGwTests.scala     | 35 ++++++++++++++++++++--
 2 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
index 5e8b5dd..5a0f97c 100644
--- a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
+++ b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
@@ -427,10 +427,10 @@ class ApiGwRoutemgmtActionTests
     it should "reject routemgmt actions that are invoked with not enough parameters" in {
         val invalidArgs = Seq(
             //getApi
-            ("/whisk.system/routemgmt/getApi", ANY_ERROR_EXIT, "__ow_user is required", Seq()),
+            ("/whisk.system/routemgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
 
             //deleteApi
-            ("/whisk.system/routemgmt/deleteApi", ANY_ERROR_EXIT, "__ow_user is required", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
+            ("/whisk.system/routemgmt/deleteApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
             ("/whisk.system/routemgmt/deleteApi", ANY_ERROR_EXIT, "basepath is required", Seq("-p", "__ow_user", "_")),
             ("/whisk.system/routemgmt/deleteApi", ANY_ERROR_EXIT, "When specifying an operation, the path is required",
                 Seq("-p", "__ow_user", "_", "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp", "-p", "operation", "get")),
@@ -560,10 +560,10 @@ class ApiGwRoutemgmtActionTests
     it should "reject apimgmt actions that are invoked with not enough parameters" in {
         val invalidArgs = Seq(
             //getApi
-            ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "__ow_user is required", Seq()),
+            ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
 
             //deleteApi
-            ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "__ow_user is required", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
+            ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
             ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "basepath is required", Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
             ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "When specifying an operation, the path is required",
               Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp", "-p", "operation", "get")),
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index 2a0a1d5..aadb929 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -43,7 +43,7 @@ class ApiGwTests
     with WskTestHelpers
     with BeforeAndAfterAll {
 
-    implicit val wskprops = WskProps()
+    implicit var wskprops = WskProps()
     val wsk = new Wsk
     val (cliuser, clinamespace) = WskAdmin.getUser(wskprops.authKey)
 
@@ -1194,7 +1194,7 @@ class ApiGwTests
 
     it should "reject creation of an API from invalid YAML formatted API configuration file" in {
         val testName = "CLI_APIGWTEST22"
-        val testbasepath = "/bp"
+        val testbasepath = "/"+testName+"_bp"
         val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.bad.yaml")
         try {
             var rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
@@ -1245,4 +1245,35 @@ class ApiGwTests
             val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
+
+    it should "reject creation of an API with invalid auth key" in {
+        val testName = "CLI_APIGWTEST24"
+        val testbasepath = "/" + testName + "_bp"
+        val testrelpath = "/path"
+        val testurlop = "get"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
+        val wskpropsBackup = wskprops
+        try {
+            // Create the action for the API.
+            val file = TestUtils.getTestActionFilename(s"echo.js")
+            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+            // Set an invalid auth key
+            wskprops = WskProps(authKey = "bad-auth-key")
+
+            var rr = apiCreate(
+                basepath = Some(testbasepath),
+                relpath = Some(testrelpath),
+                operation = Some(testurlop),
+                action = Some(actionName),
+                apiname = Some(testapiname),
+                expectedExitCode = ANY_ERROR_EXIT)
+            rr.stderr should include("The supplied authentication is invalid")
+        } finally {
+            wskprops = wskpropsBackup
+            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        }
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.