This is an automated email from the ASF dual-hosted git repository.
houshengbo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git
The following commit(s) were added to refs/heads/master by this push:
new 42307de Refactor trigger create using new utility methods to factor
out printing of the feed action result (#315)
42307de is described below
commit 42307de759c75b40770f9333780dbff137420777
Author: rodric rabbah <[email protected]>
AuthorDate: Mon Jun 18 21:18:55 2018 -0400
Refactor trigger create using new utility methods to factor out printing of
the feed action result (#315)
* Refactoring to remove unnecessary clone and own code.
This commit update trigger creation with a feed to use the new invoke
methods to both invoke and display the response. It will next be possible to
remove the activation result on success.
* Fix Go and Scala tests which accepted optional payload.
* Factor out an error message identifier and edit its text.
---
commands/messages.go | 27 +++
commands/trigger.go | 193 +++++++++++----------
tests/src/integration/integration_test.go | 7 +-
.../core/cli/test/WskCliBasicUsageTests.scala | 7 +-
wski18n/resources/en_US.all.json | 4 +-
5 files changed, 132 insertions(+), 106 deletions(-)
diff --git a/commands/messages.go b/commands/messages.go
new file mode 100644
index 0000000..91b4f24
--- /dev/null
+++ b/commands/messages.go
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package commands
+
+/**
+ * Mapping from identifiers to message ids in wski18n resources.
+ *
+ * NOTE: this list is not complete as message will be moved incrementally.
+ */
+const (
+ FEED_CONFIGURATION_FAILURE = "FEED_CONFIGURATION_FAILURE"
+)
diff --git a/commands/trigger.go b/commands/trigger.go
index 9aa0825..28e06f8 100644
--- a/commands/trigger.go
+++ b/commands/trigger.go
@@ -42,6 +42,58 @@ var triggerCmd = &cobra.Command{
Short: wski18n.T("work with triggers"),
}
+/**
+ * Constructs the parameters to pass to the feed, consisting of the event
type, trigger name, and subject key.
+ *
+ * NOTE: this function will exit in case of a processing error since it
indicates a problem parsing parameters.
+ *
+ * @return the feed name and parameters if a feed is specified.
+ */
+func feedParameters(feed string, lifecycle string, trigger *QualifiedName,
authKey string) (*QualifiedName, []string) {
+ if feed == "" {
+ return nil, make([]string, 0)
+ }
+
+ whisk.Debug(whisk.DbgInfo, "Trigger has a feed\n")
+
+ var params []string
+ name := fmt.Sprintf("/%s/%s", trigger.GetNamespace(),
trigger.GetEntityName())
+ params = append(params, getFormattedJSON(FEED_LIFECYCLE_EVENT,
lifecycle))
+ params = append(params, getFormattedJSON(FEED_TRIGGER_NAME, name))
+ params = append(params, getFormattedJSON(FEED_AUTH_KEY, authKey))
+
+ feedQualifiedName, err := NewQualifiedName(feed)
+ if err != nil {
+ ExitOnError(NewQualifiedNameError(feed, err))
+ }
+
+ return feedQualifiedName, params
+}
+
+/**
+ * Create or update a trigger.
+ *
+ * NOTE: this function will exit in case of a processing error since it
indicates a problem parsing parameters.
+ */
+func createOrUpdate(fqn *QualifiedName, trigger *whisk.Trigger, overwrite
bool) {
+ // TODO get rid of these global modifiers
+ Client.Namespace = fqn.GetNamespace()
+ _, _, err := Client.Triggers.Insert(trigger, overwrite)
+
+ if err != nil {
+ whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v, %s)
failed: %s\n", trigger, overwrite, err)
+ var errStr string
+ if !overwrite {
+ errStr = wski18n.T("Unable to create trigger
'{{.name}}': {{.err}}",
+ map[string]interface{}{"name": trigger.Name,
"err": err})
+ } else {
+ errStr = wski18n.T("Unable to update trigger
'{{.name}}': {{.err}}",
+ map[string]interface{}{"name": trigger.Name,
"err": err})
+ }
+ ExitOnError(whisk.MakeWskErrorFromWskError(errors.New(errStr),
err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE))
+ }
+}
+
var triggerFireCmd = &cobra.Command{
Use: "fire TRIGGER_NAME [PAYLOAD]",
Short: wski18n.T("fire trigger event"),
@@ -50,11 +102,10 @@ var triggerFireCmd = &cobra.Command{
PreRunE: SetupClientConfig,
RunE: func(cmd *cobra.Command, args []string) error {
var err error
- var parameters interface{}
var qualifiedName = new(QualifiedName)
- if whiskErr := CheckArgs(args, 1, 2, "Trigger fire",
- wski18n.T("A trigger name is required. A payload is
optional.")); whiskErr != nil {
+ if whiskErr := CheckArgs(args, 1, 1, "Trigger fire",
+ wski18n.T("A trigger name is required.")); whiskErr !=
nil {
return whiskErr
}
@@ -62,26 +113,10 @@ var triggerFireCmd = &cobra.Command{
return NewQualifiedNameError(args[0], err)
}
- Client.Namespace = qualifiedName.GetNamespace()
-
- // Add payload to parameters
- if len(args) == 2 {
- Flags.common.param = append(Flags.common.param,
getFormattedJSON("payload", args[1]))
- Flags.common.param = append(Flags.common.param,
Flags.common.param...)
- }
-
- if len(Flags.common.param) > 0 {
- parameters, err =
getJSONFromStrings(Flags.common.param, false)
- if err != nil {
- whisk.Debug(whisk.DbgError,
"getJSONFromStrings(%#v, false) failed: %s\n", Flags.common.param, err)
- errStr := wski18n.T("Invalid parameter argument
'{{.param}}': {{.err}}",
- map[string]interface{}{"param":
fmt.Sprintf("%#v", Flags.common.param), "err": err})
- werr :=
whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL,
- whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
- return werr
- }
- }
+ parameters := getParameters(Flags.common.param, false, false)
+ // TODO get rid of these global modifiers
+ Client.Namespace = qualifiedName.GetNamespace()
trigResp, _, err :=
Client.Triggers.Fire(qualifiedName.GetEntityName(), parameters)
if err != nil {
whisk.Debug(whisk.DbgError, "Client.Triggers.Fire(%s,
%#v) failed: %s\n", qualifiedName.GetEntityName(), parameters, err)
@@ -110,103 +145,73 @@ var triggerCreateCmd = &cobra.Command{
SilenceErrors: true,
PreRunE: SetupClientConfig,
RunE: func(cmd *cobra.Command, args []string) error {
- var err error
- var annotations interface{}
- var feedArgPassed bool = (Flags.common.feed != "")
- var qualifiedName = new(QualifiedName)
-
if whiskErr := CheckArgs(args, 1, 1, "Trigger create",
wski18n.T("A trigger name is required.")); whiskErr !=
nil {
return whiskErr
}
- if qualifiedName, err = NewQualifiedName(args[0]); err != nil {
- return NewQualifiedNameError(args[0], err)
- }
-
- Client.Namespace = qualifiedName.GetNamespace()
-
- var fullTriggerName string
- var fullFeedName string
- var feedQualifiedName = new(QualifiedName)
- if feedArgPassed {
- whisk.Debug(whisk.DbgInfo, "Trigger has a feed\n")
-
- if feedQualifiedName, err =
NewQualifiedName(Flags.common.feed); err != nil {
- return NewQualifiedNameError(Flags.common.feed,
err)
- }
-
- fullFeedName = fmt.Sprintf("/%s/%s",
feedQualifiedName.GetNamespace(), feedQualifiedName.GetEntityName())
- fullTriggerName = fmt.Sprintf("/%s/%s",
qualifiedName.GetNamespace(), qualifiedName.GetEntityName())
- Flags.common.param = append(Flags.common.param,
getFormattedJSON(FEED_LIFECYCLE_EVENT, FEED_CREATE))
- Flags.common.param = append(Flags.common.param,
getFormattedJSON(FEED_TRIGGER_NAME, fullTriggerName))
- Flags.common.param = append(Flags.common.param,
getFormattedJSON(FEED_AUTH_KEY, Client.Config.AuthToken))
- }
-
- // Convert the trigger's list of default parameters from a
string into []KeyValue
- // The 1 or more --param arguments have all been combined into
a single []string
- // e.g. --p arg1,arg2 --p arg3,arg4 -> [arg1, arg2, arg3,
arg4]
- whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n",
Flags.common.param)
- parameters, err := getJSONFromStrings(Flags.common.param,
!feedArgPassed)
-
+ triggerName, err := NewQualifiedName(args[0])
if err != nil {
- whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v,
true) failed: %s\n", Flags.common.param, err)
- errStr := wski18n.T("Invalid parameter argument
'{{.param}}': {{.err}}",
- map[string]interface{}{"param":
fmt.Sprintf("%#v", Flags.common.param), "err": err})
- werr :=
whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
- return werr
+ return NewQualifiedNameError(args[0], err)
}
- // Add feed to annotations
- if feedArgPassed {
- Flags.common.annotation =
append(Flags.common.annotation, getFormattedJSON("feed", Flags.common.feed))
- }
+ paramArray := Flags.common.param
+ annotationArray := Flags.common.annotation
+ feedParam := Flags.common.feed
+ authToken := Client.Config.AuthToken
- whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n",
Flags.common.annotation)
- annotations, err = getJSONFromStrings(Flags.common.annotation,
true)
+ // if a feed is specified, create additional parameters which
must be passed to the feed
+ feedName, feedParams := feedParameters(feedParam, FEED_CREATE,
triggerName, authToken)
+ // the feed receives all the paramaters that are specified on
the command line so we merge
+ // the feed lifecycle parameters with the command line ones
+ parameters := getParameters(append(paramArray, feedParams...),
feedName == nil, false)
- if err != nil {
- whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v,
true) failed: %s\n", Flags.common.annotation, err)
- errStr := wski18n.T("Invalid annotation argument
'{{.annotation}}': {{.err}}",
- map[string]interface{}{"annotation":
fmt.Sprintf("%#v", Flags.common.annotation), "err": err})
- werr :=
whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
- return werr
+ // if a feed is specified, add feed annotation the annotations
declared on the command line
+ // TODO: add test to ensure that generated annotation has
precedence
+ if feedName != nil {
+ annotationArray = append(annotationArray,
getFormattedJSON("feed", feedName.GetFullQualifiedName()))
}
+ annotations := getParameters(annotationArray, true, true)
trigger := &whisk.Trigger{
- Name: qualifiedName.GetEntityName(),
+ Name: triggerName.GetEntityName(),
Annotations: annotations.(whisk.KeyValueArr),
}
- if !feedArgPassed {
+ if feedName == nil {
+ // parameters are only attached to the trigger in there
is no feed, otherwise
+ // parameters are passed to the feed instead
trigger.Parameters = parameters.(whisk.KeyValueArr)
}
- _, _, err = Client.Triggers.Insert(trigger, false)
- if err != nil {
- whisk.Debug(whisk.DbgError,
"Client.Triggers.Insert(%+v,false) failed: %s\n", trigger, err)
- errStr := wski18n.T("Unable to create trigger
'{{.name}}': {{.err}}",
- map[string]interface{}{"name": trigger.Name,
"err": err})
- werr :=
whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
- return werr
- }
+ createOrUpdate(triggerName, trigger, false)
// Invoke the specified feed action to configure the trigger
feed
- if feedArgPassed {
- err := configureFeed(trigger.Name, fullFeedName,
getParameters(Flags.common.param, false, false))
+ if feedName != nil {
+ res, err := invokeAction(*feedName, parameters, true,
false)
if err != nil {
- whisk.Debug(whisk.DbgError, "configureFeed(%s,
%s) failed: %s\n", trigger.Name, Flags.common.feed,
- err)
+ whisk.Debug(whisk.DbgError, "Failed configuring
feed '%s' failed: %s\n", feedName.GetFullQualifiedName(), err)
+
+ // TODO: should we do this at all? Keeping for
now.
+
printFailedBlockingInvocationResponse(*feedName, false, res, err)
+
+ reason := wski18n.T(FEED_CONFIGURATION_FAILURE,
map[string]interface{}{"feedname": feedName.GetFullQualifiedName(), "err": err})
errStr := wski18n.T("Unable to create trigger
'{{.name}}': {{.err}}",
- map[string]interface{}{"name":
trigger.Name, "err": err})
+ map[string]interface{}{"name":
trigger.Name, "err": reason})
werr :=
whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
// Delete trigger that was created for this feed
- delerr := deleteTrigger(args[0])
- if delerr != nil {
- whisk.Debug(whisk.DbgWarn, "Ignoring
deleteTrigger(%s) failure: %s\n", args[0], delerr)
+ err = deleteTrigger(triggerName.GetEntityName())
+ if err != nil {
+ whisk.Debug(whisk.DbgWarn, "Ignoring
deleteTrigger(%s) failure: %s\n", triggerName.GetEntityName(), err)
}
+
return werr
+ } else {
+ whisk.Debug(whisk.DbgInfo, "Successfully
configured trigger feed via feed action '%s'\n", feedName)
+
+ // preserve existing behavior where output of
feed activation is emitted to console
+ printInvocationMsg(*feedName, true, true, res,
color.Output)
}
}
@@ -351,7 +356,6 @@ var triggerGetCmd = &cobra.Command{
}
Client.Namespace = qualifiedName.GetNamespace()
-
retTrigger, _, err :=
Client.Triggers.Get(qualifiedName.GetEntityName())
if err != nil {
whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s)
failed: %s\n", qualifiedName.GetEntityName(), err)
@@ -449,7 +453,6 @@ var triggerDeleteCmd = &cobra.Command{
Flags.common.param = origParams
Client.Namespace = qualifiedName.GetNamespace()
}
-
}
retTrigger, _, err =
Client.Triggers.Delete(qualifiedName.GetEntityName())
@@ -528,8 +531,7 @@ func configureFeed(triggerName string, feedName string,
parameters interface{})
if err != nil {
whisk.Debug(whisk.DbgError, "Invoke of action '%s' failed:
%s\n", feedName, err)
- errStr := wski18n.T("Unable to invoke trigger '{{.trigname}}'
feed action '{{.feedname}}'; feed is not configured: {{.err}}",
- map[string]interface{}{"trigname": triggerName,
"feedname": feedName, "err": err})
+ errStr := wski18n.T(FEED_CONFIGURATION_FAILURE,
map[string]interface{}{"feedname": feedName, "trigname": triggerName, "err":
err})
err = whisk.MakeWskErrorFromWskError(errors.New(errStr), err,
whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
} else {
whisk.Debug(whisk.DbgInfo, "Successfully configured trigger
feed via feed action '%s'\n", feedName)
@@ -580,5 +582,4 @@ func init() {
triggerDeleteCmd,
triggerListCmd,
)
-
}
diff --git a/tests/src/integration/integration_test.go
b/tests/src/integration/integration_test.go
index f6245c9..583f48c 100644
--- a/tests/src/integration/integration_test.go
+++ b/tests/src/integration/integration_test.go
@@ -42,7 +42,6 @@ var ruleTriggerActionReqMsg = "A rule, trigger and action
name are required."
var activationIdReq = "An activation ID is required."
var triggerNameReqMsg = "A trigger name is required."
var optNamespaceMsg = "An optional namespace is the only valid argument."
-var optPayloadMsg = "A payload is optional."
var noArgsReqMsg = "No arguments are required."
var invalidArg = "invalidArg"
var apiCreateReqMsg = "Specify a swagger file or specify an API base path with
an API path, an API verb, and an action name."
@@ -282,11 +281,11 @@ func initInvalidArgs() {
{
Cmd: []string{"trigger", "fire"},
- Err: tooFewArgsMsg + " " + triggerNameReqMsg + " " +
optPayloadMsg,
+ Err: tooFewArgsMsg + " " + triggerNameReqMsg,
},
{
- Cmd: []string{"trigger", "fire", "triggerName",
"triggerPayload", invalidArg},
- Err: tooManyArgsMsg + invalidArg + ". " +
triggerNameReqMsg + " " + optPayloadMsg,
+ Cmd: []string{"trigger", "fire", "triggerName",
invalidArg},
+ Err: tooManyArgsMsg + invalidArg + ". " +
triggerNameReqMsg,
},
{
Cmd: []string{"trigger", "create"},
diff --git
a/tests/src/test/scala/whisk/core/cli/test/WskCliBasicUsageTests.scala
b/tests/src/test/scala/whisk/core/cli/test/WskCliBasicUsageTests.scala
index 94a6ce5..8e018ad 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskCliBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskCliBasicUsageTests.scala
@@ -2257,7 +2257,6 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
val activationIdReq = "An activation ID is required."
val triggerNameReqMsg = "A trigger name is required."
val optNamespaceMsg = "An optional namespace is the only valid argument."
- val optPayloadMsg = "A payload is optional."
val noArgsReqMsg = "No arguments are required."
val invalidArg = "invalidArg"
val apiCreateReqMsg =
@@ -2389,9 +2388,9 @@ class WskCliBasicUsageTests extends TestHelpers with
WskTestHelpers {
s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
(Seq("rule", "list", invalidArg), entityNameMsg),
(Seq("trigger", "fire"),
- s"${tooFewArgsMsg} ${triggerNameReqMsg} ${optPayloadMsg}"),
- (Seq("trigger", "fire", "triggerName", "triggerPayload", invalidArg),
- s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg}
${optPayloadMsg}"),
+ s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
+ (Seq("trigger", "fire", "triggerName", invalidArg),
+ s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg}"),
(Seq("trigger", "create"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
(Seq("trigger", "create", "triggerName", invalidArg),
s"${tooManyArgsMsg}${invalidArg}."),
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 44b8ede..3e7024e 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -687,8 +687,8 @@
"translation": "Unable to obtain the list of triggers for namespace
'{{.name}}': {{.err}}"
},
{
- "id": "Unable to invoke trigger '{{.trigname}}' feed action
'{{.feedname}}'; feed is not configured: {{.err}}",
- "translation": "Unable to invoke trigger '{{.trigname}}' feed action
'{{.feedname}}'; feed is not configured: {{.err}}"
+ "id": "FEED_CONFIGURATION_FAILURE",
+ "translation": "Unable to configure feed '{{.feedname}}': {{.err}}"
},
{
"note-to-translators": "DO NOT TRANSLATE THE 'yes' AND 'no'. THOSE ARE
FIXED CLI ARGUMENT VALUES",