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/07 18:40:22 UTC
[incubator-openwhisk] branch master updated: wsk CLI should
tolerate APIs that do not yet have a mapped action (#2458)
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.git
The following commit(s) were added to refs/heads/master by this push:
new 9c4ff87 wsk CLI should tolerate APIs that do not yet have a mapped action (#2458)
9c4ff87 is described below
commit 9c4ff87da2658f25bcb7ea6fc920fc54d806fb0d
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Fri Jul 7 14:40:19 2017 -0400
wsk CLI should tolerate APIs that do not yet have a mapped action (#2458)
* wsk CLI should tolerate APIs that do not yet have a mapped action
- bump API GW version so that action-less APIs can be created via cli/swagger
* Add `wsk api list --full` test for action-less apis
---
ansible/group_vars/all | 2 +-
ansible/roles/apigateway/tasks/deploy.yml | 2 +-
.../apigw/endpoints.without.action.swagger.json | 76 ++++++++++++++++++++++
.../scala/whisk/core/cli/test/ApiGwTests.scala | 33 ++++++++++
tools/cli/go-whisk-cli/commands/api.go | 45 +++++++++----
.../go-whisk-cli/wski18n/resources/en_US.all.json | 4 ++
tools/cli/go-whisk/whisk/api.go | 18 ++---
7 files changed, 153 insertions(+), 27 deletions(-)
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
index 5fa8eed..91e3fa7 100644
--- a/ansible/group_vars/all
+++ b/ansible/group_vars/all
@@ -192,7 +192,7 @@ apigateway:
api: 9000
api_secure: 443
mgmt: 9001
- version: 0.7.0
+ version: 0.8.2
redis:
version: 3.2
diff --git a/ansible/roles/apigateway/tasks/deploy.yml b/ansible/roles/apigateway/tasks/deploy.yml
index a2dd2be..9d18488 100644
--- a/ansible/roles/apigateway/tasks/deploy.yml
+++ b/ansible/roles/apigateway/tasks/deploy.yml
@@ -1,7 +1,7 @@
---
# This role will install apigateway
-- name: "pull the openwhisk/apigateway image"
+- name: "pull the openwhisk/apigateway:{{ apigateway.version }} image"
shell: "docker pull openwhisk/apigateway:{{ apigateway.version }}"
when: apigateway_local_build is undefined
retries: 3
diff --git a/tests/dat/apigw/endpoints.without.action.swagger.json b/tests/dat/apigw/endpoints.without.action.swagger.json
new file mode 100644
index 0000000..2305643
--- /dev/null
+++ b/tests/dat/apigw/endpoints.without.action.swagger.json
@@ -0,0 +1,76 @@
+{
+ "swagger": "2.0",
+ "basePath": "/NoActions",
+ "info": {
+ "title": "A descriptive name",
+ "version": "1.0"
+ },
+ "paths": {
+ "/": {
+ "delete": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "get": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "head": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "options": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "patch": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "post": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ },
+ "put": {
+ "operationId": "",
+ "responses": {
+ "200": {
+ "description": "A successful invocation response"
+ }
+ }
+ }
+ }
+ },
+ "x-ibm-configuration": {
+ "assembly": {
+ "execute": []
+ },
+ "cors": {
+ "enabled": true
+ }
+ }
+}
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 5894bcd..9c8e239 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -1212,4 +1212,37 @@ class ApiGwTests
var rr = apiDelete(basepathOrApiName = nonexistentApi, expectedExitCode = ANY_ERROR_EXIT)
rr.stderr should include (s"API '${nonexistentApi}' does not exist")
}
+
+ it should "successfully list an API whose endpoints are not mapped to actions" in {
+ val testName = "CLI_APIGWTEST23"
+ var testapiname = "A descriptive name"
+ val testbasepath = "/NoActions"
+ val testrelpath = "/"
+ val testops: Seq[String] = Seq("put", "delete", "get", "head", "options", "patch", "post")
+ val swaggerPath = TestUtils.getTestApiGwFilename(s"endpoints.without.action.swagger.json")
+
+ try {
+ var rr = apiCreate(swagger = Some(swaggerPath))
+ println("api create stdout: " + rr.stdout)
+ println("api create stderror: " + rr.stderr)
+ rr.stdout should include("ok: created API")
+
+ rr = apiList(basepathOrApiName = Some(testbasepath))
+ println("api list:\n" + rr.stdout)
+ testops foreach { testurlop =>
+ rr.stdout should include regex (s"\\s+${testurlop}\\s+${testapiname}\\s+")
+ }
+ rr.stdout should include(testbasepath + testrelpath)
+
+ rr = apiList(basepathOrApiName = Some(testbasepath), full = Some(true))
+ println("api full list:\n" + rr.stdout)
+ testops foreach { testurlop =>
+ rr.stdout should include regex (s"Verb:\\s+${testurlop}")
+ }
+ rr.stdout should include(testbasepath + testrelpath)
+
+ } finally {
+ val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
}
diff --git a/tools/cli/go-whisk-cli/commands/api.go b/tools/cli/go-whisk-cli/commands/api.go
index 00167eb..d27a42e 100644
--- a/tools/cli/go-whisk-cli/commands/api.go
+++ b/tools/cli/go-whisk-cli/commands/api.go
@@ -864,21 +864,34 @@ var apiCreateCmdV2 = &cobra.Command{
for op, opv := range retApi.Swagger.Paths[path] {
whisk.Debug(whisk.DbgInfo, "Path operation: %s\n", op)
var fqActionName string
- if (len(opv.XOpenWhisk.Package) > 0) {
+ if (opv.XOpenWhisk == nil) {
+ fqActionName = ""
+ } else if (len(opv.XOpenWhisk.Package) > 0) {
fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
} else {
fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
}
whisk.Debug(whisk.DbgInfo, "baseUrl %s Path %s Path obj %+v\n", baseUrl, path, opv)
- fmt.Fprintf(color.Output,
- wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
- map[string]interface{}{
- "ok": color.GreenString("ok:"),
- "path": strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
- "verb": op,
- "name": boldString(fqActionName),
- "fullpath": managedUrl,
- }))
+ if len(fqActionName) > 0 {
+ fmt.Fprintf(color.Output,
+ wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+ map[string]interface{}{
+ "ok": color.GreenString("ok:"),
+ "path": strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
+ "verb": op,
+ "name": boldString(fqActionName),
+ "fullpath": managedUrl,
+ }))
+ } else {
+ fmt.Fprintf(color.Output,
+ wski18n.T("{{.ok}} created API {{.path}} {{.verb}}\n{{.fullpath}}\n",
+ map[string]interface{}{
+ "ok": color.GreenString("ok:"),
+ "path": strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
+ "verb": op,
+ "fullpath": managedUrl,
+ }))
+ }
}
}
}
@@ -1218,7 +1231,9 @@ func printFilteredListApiV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb s
if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) {
whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: operation matches: %#v\n", opv)
var actionName string
- if (len(opv.XOpenWhisk.Package) > 0) {
+ if (opv.XOpenWhisk == nil) {
+ actionName = ""
+ } else if (len(opv.XOpenWhisk.Package) > 0) {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
} else {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
@@ -1256,7 +1271,9 @@ func printFilteredListRowV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb s
if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) {
whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: operation matches: %#v\n", opv)
var actionName string
- if (len(opv.XOpenWhisk.Package) > 0) {
+ if (opv.XOpenWhisk == nil) {
+ actionName = ""
+ } else if (len(opv.XOpenWhisk.Package) > 0) {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
} else {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
@@ -1287,7 +1304,9 @@ func getLargestActionNameSizeV2(retApiArray *whisk.RetApiArrayV2, apiPath string
if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) {
whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
var fullActionName string
- if (len(opv.XOpenWhisk.Package) > 0) {
+ if (opv.XOpenWhisk == nil) {
+ fullActionName = ""
+ } else if (len(opv.XOpenWhisk.Package) > 0) {
fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
} else {
fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
diff --git a/tools/cli/go-whisk-cli/wski18n/resources/en_US.all.json b/tools/cli/go-whisk-cli/wski18n/resources/en_US.all.json
index 7d3a9bd..765f961 100644
--- a/tools/cli/go-whisk-cli/wski18n/resources/en_US.all.json
+++ b/tools/cli/go-whisk-cli/wski18n/resources/en_US.all.json
@@ -1188,6 +1188,10 @@
"translation": "{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n"
},
{
+ "id": "{{.ok}} created API {{.path}} {{.verb}}\n{{.fullpath}}\n",
+ "translation": "{{.ok}} created API {{.path}} {{.verb}}\n{{.fullpath}}\n"
+ },
+ {
"id": "Unable to parse api command arguments: {{.err}}",
"translation": "Unable to parse api command arguments: {{.err}}"
},
diff --git a/tools/cli/go-whisk/whisk/api.go b/tools/cli/go-whisk/whisk/api.go
index baeb0c5..6b9d4a6 100644
--- a/tools/cli/go-whisk/whisk/api.go
+++ b/tools/cli/go-whisk/whisk/api.go
@@ -545,21 +545,15 @@ func validateApiPath(path map[string]*ApiSwaggerOperationV2) error {
}
func validateApiOperation(opName string, op *ApiSwaggerOperationV2) error {
- if len(op.OperationId) == 0 {
- Debug(DbgError, "validateApiResponse: No operationId field in operation %v\n", op)
+ if (op.XOpenWhisk != nil && len(op.OperationId) == 0) {
+ Debug(DbgError, "validateApiOperation: No operationId field in operation %v\n", op)
errMsg := wski18n.T("Missing operationId field in API configuration for operation {{.op}}",
map[string]interface{}{"op": opName})
whiskErr := MakeWskError(errors.New(errMsg), EXITCODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
return whiskErr
}
- if op.XOpenWhisk == nil {
- Debug(DbgError, "validateApiResponse: No x-openwhisk stanza in operation %v\n", op)
- errMsg := wski18n.T("Missing x-openwhisk stanza in API configuration for operation {{.op}}",
- map[string]interface{}{"op": opName})
- whiskErr := MakeWskError(errors.New(errMsg), EXITCODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
- return whiskErr
- }
- if len(op.XOpenWhisk.Namespace) == 0 {
+
+ if (op.XOpenWhisk != nil && len(op.XOpenWhisk.Namespace) == 0) {
Debug(DbgError, "validateApiOperation: no x-openwhisk.namespace stanza in operation %v\n", op)
errMsg := wski18n.T("Missing x-openwhisk.namespace field in API configuration for operation {{.op}}",
map[string]interface{}{"op": opName})
@@ -569,14 +563,14 @@ func validateApiOperation(opName string, op *ApiSwaggerOperationV2) error {
// Note: The op.XOpenWhisk.Package field can have a value of "", so don't enforce a value
- if len(op.XOpenWhisk.ActionName) == 0 {
+ if (op.XOpenWhisk != nil && len(op.XOpenWhisk.ActionName) == 0) {
Debug(DbgError, "validateApiOperation: no x-openwhisk.action stanza in operation %v\n", op)
errMsg := wski18n.T("Missing x-openwhisk.action field in API configuration for operation {{.op}}",
map[string]interface{}{"op": opName})
whiskErr := MakeWskError(errors.New(errMsg), EXITCODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
return whiskErr
}
- if len(op.XOpenWhisk.ApiUrl) == 0 {
+ if (op.XOpenWhisk != nil && len(op.XOpenWhisk.ApiUrl) == 0) {
Debug(DbgError, "validateApiOperation: no x-openwhisk.url stanza in operation %v\n", op)
errMsg := wski18n.T("Missing x-openwhisk.url field in API configuration for operation {{.op}}",
map[string]interface{}{"op": opName})
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].