You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by mr...@apache.org on 2018/04/06 19:19:08 UTC
[incubator-openwhisk-wskdeploy] branch master updated: adding
support to create api gateway based on sequences (#858)
This is an automated email from the ASF dual-hosted git repository.
mrutkowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-wskdeploy.git
The following commit(s) were added to refs/heads/master by this push:
new 2f1996c adding support to create api gateway based on sequences (#858)
2f1996c is described below
commit 2f1996ca3fb53514fee10ed05975ada3084d16b0
Author: Priti Desai <pd...@us.ibm.com>
AuthorDate: Fri Apr 6 12:19:05 2018 -0700
adding support to create api gateway based on sequences (#858)
---
parsers/manifest_parser.go | 92 ++++++++++++++----------
parsers/manifest_parser_test.go | 6 +-
tests/dat/manifest_data_compose_api_records.yaml | 5 ++
tests/src/integration/apigateway/manifest.yml | 4 ++
utils/webaction.go | 4 ++
wski18n/i18n_ids.go | 40 ++++++-----
wski18n/i18n_resources.go | 4 +-
wski18n/resources/en_US.all.json | 8 ++-
8 files changed, 100 insertions(+), 63 deletions(-)
diff --git a/parsers/manifest_parser.go b/parsers/manifest_parser.go
index b46f73a..c63e4dd 100644
--- a/parsers/manifest_parser.go
+++ b/parsers/manifest_parser.go
@@ -1027,13 +1027,7 @@ func (dm *YAMLParser) ComposeApiRecords(client *whisk.Config, packageName string
}
for actionName, gatewayMethod := range gatewayRelPathMap {
// verify that the action is defined under actions sections
- if _, ok := pkg.Actions[actionName]; !ok {
- return nil, wskderrors.NewYAMLFileFormatError(manifestPath,
- wski18n.T(wski18n.ID_ERR_API_MISSING_ACTION_X_action_X_api_X,
- map[string]interface{}{
- wski18n.KEY_ACTION: actionName,
- wski18n.KEY_API: apiName}))
- } else {
+ if _, ok := pkg.Actions[actionName]; ok {
// verify that the action is defined as web action
// web or web-export set to any of [true, yes, raw]
a := pkg.Actions[actionName]
@@ -1049,38 +1043,62 @@ func (dm *YAMLParser) ComposeApiRecords(client *whisk.Config, packageName string
a.Annotations[utils.WEB_EXPORT_ANNOT] = true
pkg.Actions[actionName] = a
}
- request := new(whisk.ApiCreateRequest)
- request.ApiDoc = new(whisk.Api)
- request.ApiDoc.GatewayBasePath = gatewayBasePath
- // is API verb is valid, it must be one of (GET, PUT, POST, DELETE)
- request.ApiDoc.GatewayRelPath = gatewayRelPath
- if _, ok := whisk.ApiVerbs[strings.ToUpper(gatewayMethod)]; !ok {
- return nil, wskderrors.NewInvalidAPIGatewayMethodError(manifestPath,
- gatewayBasePath+gatewayRelPath,
- gatewayMethod,
- dm.getGatewayMethods())
- }
- request.ApiDoc.GatewayMethod = strings.ToUpper(gatewayMethod)
- request.ApiDoc.Namespace = client.Namespace
- request.ApiDoc.ApiName = apiName
- request.ApiDoc.Id = strings.Join([]string{API, request.ApiDoc.Namespace, request.ApiDoc.GatewayRelPath}, ":")
- // set action of an API Doc
- request.ApiDoc.Action = new(whisk.ApiAction)
- if packageName == DEFAULT_PACKAGE {
- request.ApiDoc.Action.Name = actionName
- } else {
- request.ApiDoc.Action.Name = packageName + PATH_SEPARATOR + actionName
+ // verify that the sequence is defined under sequences sections
+ } else if _, ok := pkg.Sequences[actionName]; ok {
+ // verify that the sequence is defined as web sequence
+ // web set to any of [true, yes, raw]
+ a := pkg.Sequences[actionName]
+ if !utils.IsWebSequence(a.Web) {
+ warningString := wski18n.T(wski18n.ID_WARN_API_MISSING_WEB_SEQUENCE_X_sequence_X_api_X,
+ map[string]interface{}{
+ wski18n.KEY_SEQUENCE: actionName,
+ wski18n.KEY_API: apiName})
+ wskprint.PrintOpenWhiskWarning(warningString)
+ if a.Annotations == nil {
+ a.Annotations = make(map[string]interface{}, 0)
+ }
+ a.Annotations[utils.WEB_EXPORT_ANNOT] = true
+ pkg.Sequences[actionName] = a
}
- url := []string{HTTPS + client.Host, strings.ToLower(API),
- API_VERSION, WEB, client.Namespace, packageName,
- actionName + "." + utils.HTTP_FILE_EXTENSION}
- request.ApiDoc.Action.Namespace = client.Namespace
- request.ApiDoc.Action.BackendUrl = strings.Join(url, PATH_SEPARATOR)
- request.ApiDoc.Action.BackendMethod = gatewayMethod
- request.ApiDoc.Action.Auth = client.AuthToken
- // add a newly created ApiCreateRequest object to a list of requests
- requests = append(requests, request)
+ // return failure since action or sequence are not defined in the manifest
+ } else {
+ return nil, wskderrors.NewYAMLFileFormatError(manifestPath,
+ wski18n.T(wski18n.ID_ERR_API_MISSING_ACTION_OR_SEQUENCE_X_action_or_sequence_X_api_X,
+ map[string]interface{}{
+ wski18n.KEY_ACTION: actionName,
+ wski18n.KEY_API: apiName}))
+ }
+ request := new(whisk.ApiCreateRequest)
+ request.ApiDoc = new(whisk.Api)
+ request.ApiDoc.GatewayBasePath = gatewayBasePath
+ // is API verb is valid, it must be one of (GET, PUT, POST, DELETE)
+ request.ApiDoc.GatewayRelPath = gatewayRelPath
+ if _, ok := whisk.ApiVerbs[strings.ToUpper(gatewayMethod)]; !ok {
+ return nil, wskderrors.NewInvalidAPIGatewayMethodError(manifestPath,
+ gatewayBasePath+gatewayRelPath,
+ gatewayMethod,
+ dm.getGatewayMethods())
+ }
+ request.ApiDoc.GatewayMethod = strings.ToUpper(gatewayMethod)
+ request.ApiDoc.Namespace = client.Namespace
+ request.ApiDoc.ApiName = apiName
+ request.ApiDoc.Id = strings.Join([]string{API, request.ApiDoc.Namespace, request.ApiDoc.GatewayRelPath}, ":")
+ // set action of an API Doc
+ request.ApiDoc.Action = new(whisk.ApiAction)
+ if packageName == DEFAULT_PACKAGE {
+ request.ApiDoc.Action.Name = actionName
+ } else {
+ request.ApiDoc.Action.Name = packageName + PATH_SEPARATOR + actionName
}
+ url := []string{HTTPS + client.Host, strings.ToLower(API),
+ API_VERSION, WEB, client.Namespace, packageName,
+ actionName + "." + utils.HTTP_FILE_EXTENSION}
+ request.ApiDoc.Action.Namespace = client.Namespace
+ request.ApiDoc.Action.BackendUrl = strings.Join(url, PATH_SEPARATOR)
+ request.ApiDoc.Action.BackendMethod = gatewayMethod
+ request.ApiDoc.Action.Auth = client.AuthToken
+ // add a newly created ApiCreateRequest object to a list of requests
+ requests = append(requests, request)
}
}
}
diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
index c3d62d4..113049c 100644
--- a/parsers/manifest_parser_test.go
+++ b/parsers/manifest_parser_test.go
@@ -1305,8 +1305,6 @@ func TestComposeRules(t *testing.T) {
}
}
-// TODO(752) We SHOULD automatically add "web-export" to each Action referenced in the "apis" section
-// as this is implied. The user should not have to do this manually
func TestComposeApiRecords(t *testing.T) {
p, m, _ := testLoadParseManifest(t, "../tests/dat/manifest_data_compose_api_records.yaml")
@@ -1323,7 +1321,7 @@ func TestComposeApiRecords(t *testing.T) {
if err != nil {
assert.Fail(t, "Failed to compose api records: "+err.Error())
}
- assert.Equal(t, 6, len(apiList), "Failed to get api records")
+ assert.Equal(t, 7, len(apiList), "Failed to get api records")
for _, apiRecord := range apiList {
apiDoc := apiRecord.ApiDoc
action := apiDoc.Action
@@ -1354,10 +1352,12 @@ func TestComposeApiRecords(t *testing.T) {
assert.Equal(t, "/books2", apiDoc.GatewayRelPath, "Failed to set api rel path")
assert.Equal(t, "post", action.BackendMethod, "Failed to set api backend method")
case "apiTest/listMembers2":
+ case "apiTest/listAllMembers":
assert.Equal(t, "book-club2", apiDoc.ApiName, "Failed to set api name")
assert.Equal(t, "/club2", apiDoc.GatewayBasePath, "Failed to set api base path")
assert.Equal(t, "/members2", apiDoc.GatewayRelPath, "Failed to set api rel path")
assert.Equal(t, "get", action.BackendMethod, "Failed to set api backend method")
+
default:
assert.Fail(t, "Failed to get api action name")
}
diff --git a/tests/dat/manifest_data_compose_api_records.yaml b/tests/dat/manifest_data_compose_api_records.yaml
index 385c8e9..6191a1f 100644
--- a/tests/dat/manifest_data_compose_api_records.yaml
+++ b/tests/dat/manifest_data_compose_api_records.yaml
@@ -30,6 +30,10 @@ packages:
function: ../tests/src/integration/helloworld/actions/hello.js
listMembers2:
function: ../tests/src/integration/helloworld/actions/hello.js
+ sequences:
+ listAllMembers:
+ actions: listMembers, listMembers2
+ web: true
apis:
book-club:
club:
@@ -45,3 +49,4 @@ packages:
postBooks2: post
members2:
listMembers2: get
+ listAllMembers: get
diff --git a/tests/src/integration/apigateway/manifest.yml b/tests/src/integration/apigateway/manifest.yml
index e2b26f5..5c22af2 100644
--- a/tests/src/integration/apigateway/manifest.yml
+++ b/tests/src/integration/apigateway/manifest.yml
@@ -34,6 +34,9 @@ packages:
function: src/delete-books.js
listMembers:
function: src/list-members.js
+ sequences:
+ listAllMembers:
+ actions: listMembers
# new top-level key for defining groups of named APIs
apis:
hello-world:
@@ -49,3 +52,4 @@ packages:
deleteBooks: DELETE
members:
listMembers: GET
+ listAllMembers: GET
diff --git a/utils/webaction.go b/utils/webaction.go
index 087a773..64fe346 100644
--- a/utils/webaction.go
+++ b/utils/webaction.go
@@ -121,3 +121,7 @@ func IsWebAction(webexport string) bool {
}
return false
}
+
+func IsWebSequence(webexport string) bool {
+ return IsWebAction(webexport)
+}
diff --git a/wski18n/i18n_ids.go b/wski18n/i18n_ids.go
index 1ede72a..eae4a0b 100644
--- a/wski18n/i18n_ids.go
+++ b/wski18n/i18n_ids.go
@@ -77,6 +77,7 @@ const (
KEY_BINDINGS = "bindings"
KEY_DEPENDENCY = "dependency"
KEY_LOCATION = "location"
+ KEY_SEQUENCE = "sequence"
)
// DO NOT TRANSLATE
@@ -162,25 +163,25 @@ const (
ID_MSG_MANAGED_FOUND_DELETED_X_key_X_name_X_project_X = "msg_managed_found_deleted_entity"
// Errors
- ID_ERR_DEPENDENCY_UNKNOWN_TYPE = "msg_err_dependency_unknown_type"
- ID_ERR_ENTITY_CREATE_X_key_X_err_X_code_X = "msg_err_entity_create"
- ID_ERR_ENTITY_DELETE_X_key_X_err_X_code_X = "msg_err_entity_delete"
- ID_ERR_FEED_INVOKE_X_err_X_code_X = "msg_err_feed_invoke"
- ID_ERR_KEY_MISSING_X_key_X = "msg_err_key_missing_mandatory"
- ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X = "msg_err_manifest_not_found"
- ID_ERR_NAME_MISMATCH_X_key_X_dname_X_dpath_X_mname_X_moath_X = "msg_err_name_mismatch"
- ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X = "msg_err_runtime_invalid"
- ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X = "msg_err_runtime_mismatch"
- ID_ERR_RUNTIMES_GET_X_err_X = "msg_err_runtimes_get"
- ID_ERR_RUNTIME_ACTION_SOURCE_NOT_SUPPORTED_X_ext_X_action_X = "msg_err_runtime_action_source_not_supported"
- ID_ERR_URL_INVALID_X_urltype_X_url_X_filetype_X = "msg_err_url_invalid"
- ID_ERR_URL_MALFORMED_X_urltype_X_url_X = "msg_err_url_malformed"
- ID_ERR_API_MISSING_ACTION_X_action_X_api_X = "msg_err_api_missing_action"
- ID_ERR_ACTION_INVALID_X_action_X = "msg_err_action_invalid"
- ID_ERR_ACTION_MISSING_RUNTIME_WITH_CODE_X_action_X = "msg_err_action_missing_runtime_with_code"
- ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X = "msg_err_action_function_remote_dir_not_supported"
- ID_ERR_CANT_SAVE_DOCKER_RUNTIME = "msg_err_cant_save_docker"
- ID_ERR_FILE_ALREADY_EXISTS = "msg_err_file_already_exists"
+ ID_ERR_DEPENDENCY_UNKNOWN_TYPE = "msg_err_dependency_unknown_type"
+ ID_ERR_ENTITY_CREATE_X_key_X_err_X_code_X = "msg_err_entity_create"
+ ID_ERR_ENTITY_DELETE_X_key_X_err_X_code_X = "msg_err_entity_delete"
+ ID_ERR_FEED_INVOKE_X_err_X_code_X = "msg_err_feed_invoke"
+ ID_ERR_KEY_MISSING_X_key_X = "msg_err_key_missing_mandatory"
+ ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X = "msg_err_manifest_not_found"
+ ID_ERR_NAME_MISMATCH_X_key_X_dname_X_dpath_X_mname_X_moath_X = "msg_err_name_mismatch"
+ ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X = "msg_err_runtime_invalid"
+ ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X = "msg_err_runtime_mismatch"
+ ID_ERR_RUNTIMES_GET_X_err_X = "msg_err_runtimes_get"
+ ID_ERR_RUNTIME_ACTION_SOURCE_NOT_SUPPORTED_X_ext_X_action_X = "msg_err_runtime_action_source_not_supported"
+ ID_ERR_URL_INVALID_X_urltype_X_url_X_filetype_X = "msg_err_url_invalid"
+ ID_ERR_URL_MALFORMED_X_urltype_X_url_X = "msg_err_url_malformed"
+ ID_ERR_API_MISSING_ACTION_OR_SEQUENCE_X_action_or_sequence_X_api_X = "msg_err_api_missing_action_or_sequence"
+ ID_ERR_ACTION_INVALID_X_action_X = "msg_err_action_invalid"
+ ID_ERR_ACTION_MISSING_RUNTIME_WITH_CODE_X_action_X = "msg_err_action_missing_runtime_with_code"
+ ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X = "msg_err_action_function_remote_dir_not_supported"
+ ID_ERR_CANT_SAVE_DOCKER_RUNTIME = "msg_err_cant_save_docker"
+ ID_ERR_FILE_ALREADY_EXISTS = "msg_err_file_already_exists"
// Server-side Errors (wskdeploy as an Action)
ID_ERR_JSON_MISSING_KEY_CMD = "msg_err_json_missing_cmd_key"
@@ -207,6 +208,7 @@ const (
ID_WARN_PACKAGE_IS_PUBLIC_X_package_X = "msg_warn_package_is_public"
ID_WARN_ACTION_WEB_X_action_X = "msg_warn_action_web_export_ignored"
ID_WARN_API_MISSING_WEB_ACTION_X_action_X_api_X = "msg_warn_api_missing_web_action"
+ ID_WARN_API_MISSING_WEB_SEQUENCE_X_sequence_X_api_X = "msg_warn_api_missing_web_sequence"
// Verbose (Debug/Trace) messages
ID_DEBUG_PROJECT_SEARCH_X_path_X_key_X = "msg_dbg_searching_project_directory"
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 7bc2343..e77a8f5 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -97,7 +97,7 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
return a, nil
}
-var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x6d\x8f\xdb\x36\xf2\x7f\x9f\x4f\x31\x08\xfe\x40\x5a\xc0\x51\xd2\xfe\x71\xc0\x21\xc0\xbe\xc8\x75\xd3\x76\xaf\x4d\x36\xd8\xcd\x5e\x50\xe4\x16\x0a\x2d\x8d\x6d\xd6\x12\x29\x90\x94\x1d\x77\xe1\xef\x7e\x98\x21\xf5\x60\xef\x52\xd2\x3a\xed\x5d\xdf\xd4\x09\x87\x33\xbf\x19\x0e\xe7\x89\xca\xa7\x27\x00\x77\x4f\x00\x00\x9e\xca\xfc\xe9\x2b\x78\x5a\xda\x65\x5a\x19\x5c\xc8\x2f\x29\x1a\xa3\xcd\xd3\x99\x5f\x75\x46 [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x5b\x6f\x8f\xdb\x36\xd2\x7f\x9f\x4f\x31\x08\x1e\x20\x2d\xe0\x28\x69\x1f\x3c\xc0\x83\x00\x79\x91\x6b\xd2\x76\xaf\x4d\x36\xd8\xcd\x5e\x50\xe4\x16\x0a\x2d\x8d\x6d\xd6\x12\xa9\x23\x29\x3b\xae\xe1\xef\x7e\x98\x21\xf5\xc7\xde\xa5\xa4\x75\xda\xbb\xbe\xa9\xbb\x1c\xce\xfc\x66\x38\x9c\x7f\x54\x3f\x3d\x02\xd8\x3f\x02\x00\x78\x2c\xf3\xc7\x2f\xe0\x71\x69\x97\x69\x65\x70\x21\xbf\xa4\x68\x8c\x36\x8f\x67\x7e\xd5\x19 [...]
func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
return bindataRead(
@@ -112,7 +112,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 14019, mode: os.FileMode(420), modTime: time.Unix(1522283010, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 14286, mode: os.FileMode(420), modTime: time.Unix(1523039220, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index b03692a..f765820 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -292,8 +292,8 @@
"translation": "JSON input data Missing 'cmd' key"
},
{
- "id": "msg_err_api_missing_action",
- "translation": "Action [{{.action}}] is missing from manifest file, API [{{.api}}] can only be created based on the action from manifest file. Please update manifest file to include [{{.action}}] as a web action.\n"
+ "id": "msg_err_api_missing_action_or_sequence",
+ "translation": "Action/Sequence [{{.action}}] is missing from manifest file, API [{{.api}}] can only be created based on the action/sequence from manifest file. Please update manifest file to include [{{.action}}] as a web action/sequence.\n"
},
{
"id": "msg_err_action_invalid",
@@ -404,6 +404,10 @@
"translation": "Action [{{.action}}] is not a web action, API [{{.api}}] can only be created using web action. Converting [{{.action}}] to a web action.\n"
},
{
+ "id": "msg_warn_api_missing_web_sequence",
+ "translation": "Sequence [{{.sequence}}] is not a web sequence, API [{{.api}}] can only be created using web sequence. Converting [{{.sequence}}] to a web sequence.\n"
+ },
+ {
"id": "DEBUG",
"translation": "================= DEBUG ==================="
},
--
To stop receiving notification emails like this one, please contact
mrutkowski@apache.org.