From 9a0df2d7f687df401911ef1f64608513ab8f7e2b Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Sat, 4 Jan 2020 15:45:44 -0500 Subject: [PATCH 01/15] convert secretValue int64 to string type --- commands/action.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/commands/action.go b/commands/action.go index 35adb33dc..47daa3793 100644 --- a/commands/action.go +++ b/commands/action.go @@ -27,6 +27,7 @@ import ( "os" "path/filepath" "reflect" + "strconv" "strings" "time" @@ -873,7 +874,11 @@ func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) } else { whisk.Debug(whisk.DbgInfo, "Setting %v annotation; prior secret %v new secret %v\n", WEB_SECURE_ANNOT, reflect.TypeOf(existingSecret), reflect.TypeOf(secureSecret)) - annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: secureSecret}) + if newSecretIsInt { + annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: strconv.FormatInt(secureSecret.(int64), 10)}) + } else { + annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: secureSecret}) + } } return annotations From 7bac1c3eb835320c4635b1975741a3c9029a4832 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 20 Jan 2020 20:32:12 -0500 Subject: [PATCH 02/15] initial commit --- commands/action.go | 10 +++++++++- .../core/cli/test/WskCliBasicUsageTests.scala | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/commands/action.go b/commands/action.go index 47daa3793..85ae8760c 100644 --- a/commands/action.go +++ b/commands/action.go @@ -866,7 +866,7 @@ func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) _, existingSecretIsInt = existingSecret.(json.Number) } - if existingSecretIsInt && newSecretIsInt { + if (newSecretIsInt && existingSecretIsInt) || (newSecretIsInt && existingSecretCanConvertToInt(existingSecret)) { whisk.Debug(whisk.DbgInfo, "Retaining existing secret number\n") } else if existingSecret != nil && disableSecurity { whisk.Debug(whisk.DbgInfo, "disabling web-secure; deleting annotation: %v\n", WEB_SECURE_ANNOT) @@ -884,6 +884,14 @@ func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) return annotations } +func existingSecretCanConvertToInt(secret interface{}) bool { + if underlyingString, ok := secret.(string); ok { + _, convertErr := strconv.ParseInt(underlyingString, 10, 64) + return convertErr == nil + } + return false +} + // // Generate a secret according to the --web-secure setting // true: return a random int64 diff --git a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala index f907109d2..2656b78af 100644 --- a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala +++ b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala @@ -794,7 +794,7 @@ class WskCliBasicUsageTests extends TestHelpers with WskTestHelpers { }) var secretIsInt = secretJsVar.get.convertTo[JsObject].getFields("value").head match { - case JsNumber(x) => true + case JsString(x) => true case _ => false } secretIsInt shouldBe true From 046d6a0f7434ed5e7f8722f1723a5a0a6e364a66 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 20 Jan 2020 20:44:58 -0500 Subject: [PATCH 03/15] command.go file change to get user input feed params debug ert remove unce --- commands/action.go | 17 +- commands/commands.go | 40 +++- commands/flags.go | 4 +- commands/trigger.go | 217 +++++++++++++++--- .../core/cli/test/WskCliBasicUsageTests.scala | 2 +- 5 files changed, 219 insertions(+), 61 deletions(-) diff --git a/commands/action.go b/commands/action.go index 85ae8760c..35adb33dc 100644 --- a/commands/action.go +++ b/commands/action.go @@ -27,7 +27,6 @@ import ( "os" "path/filepath" "reflect" - "strconv" "strings" "time" @@ -866,7 +865,7 @@ func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) _, existingSecretIsInt = existingSecret.(json.Number) } - if (newSecretIsInt && existingSecretIsInt) || (newSecretIsInt && existingSecretCanConvertToInt(existingSecret)) { + if existingSecretIsInt && newSecretIsInt { whisk.Debug(whisk.DbgInfo, "Retaining existing secret number\n") } else if existingSecret != nil && disableSecurity { whisk.Debug(whisk.DbgInfo, "disabling web-secure; deleting annotation: %v\n", WEB_SECURE_ANNOT) @@ -874,24 +873,12 @@ func updateWebSecureAnnotation(websecure string, annotations whisk.KeyValueArr) } else { whisk.Debug(whisk.DbgInfo, "Setting %v annotation; prior secret %v new secret %v\n", WEB_SECURE_ANNOT, reflect.TypeOf(existingSecret), reflect.TypeOf(secureSecret)) - if newSecretIsInt { - annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: strconv.FormatInt(secureSecret.(int64), 10)}) - } else { - annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: secureSecret}) - } + annotations = annotations.AddOrReplace(&whisk.KeyValue{Key: WEB_SECURE_ANNOT, Value: secureSecret}) } return annotations } -func existingSecretCanConvertToInt(secret interface{}) bool { - if underlyingString, ok := secret.(string); ok { - _, convertErr := strconv.ParseInt(underlyingString, 10, 64) - return convertErr == nil - } - return false -} - // // Generate a secret according to the --web-secure setting // true: return a random int64 diff --git a/commands/commands.go b/commands/commands.go index cbc1ce5b6..bcaaed39e 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -19,6 +19,7 @@ package commands import ( "errors" + "fmt" "net/http" "os" "runtime" @@ -131,9 +132,11 @@ func getValueFromArgs(args []string, argIndex int, parsedArgs []string) ([]strin return parsedArgs, args, whiskErr } -func parseArgs(args []string) ([]string, []string, []string, error) { +func parseArgs(args []string) ([]string, []string, []string, []string, []string, error) { var paramArgs []string var annotArgs []string + var feedParamArgs []string + var triggerParamArgs []string var whiskErr error i := 0 @@ -147,14 +150,14 @@ func parseArgs(args []string) ([]string, []string, []string, error) { map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr } filename := paramArgs[len(paramArgs)-1] paramArgs[len(paramArgs)-1], whiskErr = ReadFile(filename) if whiskErr != nil { whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-A" || args[i] == "--annotation-file" { annotArgs, args, whiskErr = getValueFromArgs(args, i, annotArgs) @@ -164,14 +167,14 @@ func parseArgs(args []string) ([]string, []string, []string, error) { map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr } filename := annotArgs[len(annotArgs)-1] annotArgs[len(annotArgs)-1], whiskErr = ReadFile(filename) if whiskErr != nil { whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-p" || args[i] == "--param" { paramArgs, args, whiskErr = getKeyValueArgs(args, i, paramArgs) @@ -181,9 +184,10 @@ func parseArgs(args []string) ([]string, []string, []string, error) { map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-a" || args[i] == "--annotation" { + fmt.Println("4") annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) @@ -191,7 +195,23 @@ func parseArgs(args []string) ([]string, []string, []string, error) { map[string]interface{}{"err": whiskErr}) whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE) - return nil, nil, nil, whiskErr + return nil, nil, nil, nil, nil, whiskErr + } + } else if args[i] == "-F" || args[i] == "--feed-param" { + feedParamArgs, args, whiskErr = getKeyValueArgs(args, i, feedParamArgs) + if whiskErr != nil { + whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) + whiskErr = whisk.MakeWskError(whiskErr, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, + whisk.DISPLAY_USAGE) + return nil, nil, nil, nil, nil, whiskErr + } + } else if args[i] == "-T" || args[i] == "--trigger-param" { + triggerParamArgs, args, whiskErr = getKeyValueArgs(args, i, triggerParamArgs) + if whiskErr != nil { + whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) + whiskErr = whisk.MakeWskError(whiskErr, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, + whisk.DISPLAY_USAGE) + return nil, nil, nil, nil, nil, whiskErr } } else { i++ @@ -200,16 +220,18 @@ func parseArgs(args []string) ([]string, []string, []string, error) { whisk.Debug(whisk.DbgInfo, "Found param args '%s'.\n", paramArgs) whisk.Debug(whisk.DbgInfo, "Found annotations args '%s'.\n", annotArgs) + whisk.Debug(whisk.DbgInfo, "Found feed param args '%s'.\n", feedParamArgs) + whisk.Debug(whisk.DbgInfo, "Found trigger param args '%s'.\n", triggerParamArgs) whisk.Debug(whisk.DbgInfo, "Arguments with param args removed '%s'.\n", args) - return args, paramArgs, annotArgs, nil + return args, paramArgs, annotArgs, feedParamArgs, triggerParamArgs, nil } func Execute() error { var err error whisk.Debug(whisk.DbgInfo, "wsk args: %#v\n", os.Args) - os.Args, Flags.common.param, Flags.common.annotation, err = parseArgs(os.Args) + os.Args, Flags.common.param, Flags.common.annotation, Flags.trigger.feedParam, Flags.trigger.triggerParam, err = parseArgs(os.Args) if err != nil { whisk.Debug(whisk.DbgError, "parseParams(%s) failed: %s\n", os.Args, err) diff --git a/commands/flags.go b/commands/flags.go index 25c9b968f..b48058c8d 100644 --- a/commands/flags.go +++ b/commands/flags.go @@ -112,7 +112,9 @@ type FlagsStruct struct { // trigger trigger struct { - summary bool + summary bool + feedParam []string + triggerParam []string } //sdk diff --git a/commands/trigger.go b/commands/trigger.go index 86b18da46..15b6ce5e3 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -20,6 +20,7 @@ package commands import ( "errors" "fmt" + "os" "github.com/apache/openwhisk-cli/wski18n" "github.com/apache/openwhisk-client-go/whisk" @@ -397,11 +398,13 @@ func init() { triggerCreateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerCreateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format")) triggerCreateCmd.Flags().StringVarP(&Flags.common.feed, "feed", "f", "", wski18n.T("trigger feed `ACTION_NAME`")) + triggerCreateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringSliceVarP(&Flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringVarP(&Flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format")) triggerUpdateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format")) + triggerUpdateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerGetCmd.Flags().BoolVarP(&Flags.trigger.summary, "summary", "s", false, wski18n.T("summarize trigger details; parameters with prefix \"*\" are bound")) @@ -426,6 +429,7 @@ type Trigger struct { } func (t *Trigger) Create(Client *whisk.Client, args []string) error { + if whiskErr := CheckArgs(args, 1, 1, "Trigger create", wski18n.T("A trigger name is required.")); whiskErr != nil { return whiskErr @@ -436,47 +440,118 @@ func (t *Trigger) Create(Client *whisk.Client, args []string) error { return NewQualifiedNameError(args[0], err) } - paramArray := Flags.common.param annotationArray := Flags.common.annotation - feedParam := Flags.common.feed authToken := Client.Config.AuthToken // 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 parameters 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) + feedQualifiedName, additionalFeedParams := feedParameters(Flags.common.feed, FEED_CREATE, triggerName, authToken) // 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())) + if feedQualifiedName != nil { + annotationArray = append(annotationArray, getFormattedJSON("feed", feedQualifiedName.GetFullQualifiedName())) } annotations := getParameters(annotationArray, true, true) + //simplestTrigger indicates user are creating a trigger without any feed or parameters + simplestTrigger := (len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0) + + //if users are 1. creating a trigger without any feed or parameters + // 2. creating a trigger using --param flag + //then we use the old way to create the trigger. + if len(Flags.common.param) > 0 || simplestTrigger { + if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { + whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") + errMsg := fmt.Sprintf("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag\n") + fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) + return nil + } + + // the feed receives all the parameters that are specified on the command line so we merge + // the feed lifecycle parameters with the command line ones + parameters := getParameters(append(Flags.common.param, additionalFeedParams...), feedQualifiedName == nil, false) + + trigger := &whisk.Trigger{ + Name: triggerName.GetEntityName(), + Annotations: annotations.(whisk.KeyValueArr), + } + + if feedQualifiedName == 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) + } + + createOrUpdate(Client, triggerName, trigger, false) + + // Invoke the specified feed action to configure the trigger feed + if feedQualifiedName != nil { + res, err := invokeAction(*feedQualifiedName, parameters, true, false) + if err != nil { + whisk.Debug(whisk.DbgError, "Failed configuring feed '%s' failed: %s\n", feedQualifiedName.GetFullQualifiedName(), err) + + // TODO: should we do this at all? Keeping for now. + printFailedBlockingInvocationResponse(*feedQualifiedName, false, res, err) + + reason := wski18n.T(FEED_CONFIGURATION_FAILURE, map[string]interface{}{"feedname": feedQualifiedName.GetFullQualifiedName(), "err": err}) + errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.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 + 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", Flags.common.feed) + + // preserve existing behavior where output of feed activation is emitted to console + printInvocationMsg(*feedQualifiedName, true, true, res, color.Output) + } + } + + fmt.Fprintf(color.Output, + wski18n.T("{{.ok}} created trigger {{.name}}\n", + map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)})) + return nil + } + + //if users are using either --feed-param or --trigger-param flag, + //then we know the users are trying to separate trigger and feed params and + //we use the enhanced way to create trigger + + if feedQualifiedName == nil && len(Flags.trigger.feedParam) > 0 { + //trigger without feed names cannot have a feed param + errMsg := fmt.Sprintf("Incorrect usage. trigger without a feed cannot have feed parameters. \n") + fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) + return nil + } + + triggerParams := getParameters(Flags.trigger.triggerParam, true, false) + //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 + feedParams := getParameters(append(Flags.trigger.feedParam, additionalFeedParams...), feedQualifiedName == nil, false) + trigger := &whisk.Trigger{ Name: triggerName.GetEntityName(), Annotations: annotations.(whisk.KeyValueArr), - } - - 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) + Parameters: triggerParams.(whisk.KeyValueArr), } createOrUpdate(Client, triggerName, trigger, false) - // Invoke the specified feed action to configure the trigger feed - if feedName != nil { - res, err := invokeAction(*feedName, parameters, true, false) + if feedQualifiedName != nil { + res, err := invokeAction(*feedQualifiedName, feedParams, true, false) if err != nil { - whisk.Debug(whisk.DbgError, "Failed configuring feed '%s' failed: %s\n", feedName.GetFullQualifiedName(), err) + whisk.Debug(whisk.DbgError, "Failed configuring feed '%s' failed: %s\n", feedQualifiedName.GetFullQualifiedName(), err) // TODO: should we do this at all? Keeping for now. - printFailedBlockingInvocationResponse(*feedName, false, res, err) + printFailedBlockingInvocationResponse(*feedQualifiedName, false, res, err) - reason := wski18n.T(FEED_CONFIGURATION_FAILURE, map[string]interface{}{"feedname": feedName.GetFullQualifiedName(), "err": err}) + reason := wski18n.T(FEED_CONFIGURATION_FAILURE, map[string]interface{}{"feedname": feedQualifiedName.GetFullQualifiedName(), "err": err}) errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.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) @@ -488,12 +563,11 @@ func (t *Trigger) Create(Client *whisk.Client, args []string) error { } 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) } + whisk.Debug(whisk.DbgInfo, "Successfully configured trigger feed via feed action '%s'\n", Flags.common.feed) + // preserve existing behavior where output of feed activation is emitted to console + printInvocationMsg(*feedQualifiedName, true, true, res, color.Output) + } fmt.Fprintf(color.Output, @@ -524,7 +598,16 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", Flags.common.param) parameters, err := getJSONFromStrings(Flags.common.param, true) + 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 + } + whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", Flags.trigger.triggerParam) + triggerParameters, err := getJSONFromStrings(Flags.trigger.triggerParam, true) 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}}", @@ -548,17 +631,38 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { if err != nil && httpResp.StatusCode == 404 { t.Create(Client, args) + return nil } else if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}", map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return werr - } else { + } - // Get full feed name from trigger get request as it is needed to get the feed - if retTrigger != nil && retTrigger.Annotations != nil { - fullFeedName = getValueString(retTrigger.Annotations, "feed") + // Get full feed name from trigger get request as it is needed to get the feed + if retTrigger != nil && retTrigger.Annotations != nil { + fullFeedName = getValueString(retTrigger.Annotations, "feed") + } + + trigger := &whisk.Trigger{ + Name: qualifiedName.GetEntityName(), + Parameters: parameters.(whisk.KeyValueArr), + Annotations: annotations.(whisk.KeyValueArr), + } + + //simplestTrigger indicates user are updating a trigger without any feed or parameters + simplestTrigger := (len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0) + + //if users are 1. creating a trigger without any feed or parameters + // 2. creating a trigger using --param flag + //then we use the old way to create the trigger. + if len(Flags.common.param) > 0 || simplestTrigger { + if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { + whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") + errMsg := fmt.Sprintf("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag\n") + fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) + return nil } if len(fullFeedName) > 0 { @@ -578,12 +682,6 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { return werr } } else { - trigger := &whisk.Trigger{ - Name: qualifiedName.GetEntityName(), - Parameters: parameters.(whisk.KeyValueArr), - Annotations: annotations.(whisk.KeyValueArr), - } - _, _, err = Client.Triggers.Insert(trigger, true) if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) @@ -597,7 +695,56 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { fmt.Fprintf(color.Output, wski18n.T("{{.ok}} updated trigger {{.name}}\n", map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qualifiedName.GetEntityName())})) + + return nil + } + + trigger.Parameters = triggerParameters.(whisk.KeyValueArr) + _, _, err = Client.Triggers.Insert(trigger, true) + if err != nil { + whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) + errStr := wski18n.T("Unable to update 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 } + //if there is no feed attached to this trigger + if len(fullFeedName) < 1 { + //but user indicate feed parameter change, we issue error message. + if len(Flags.trigger.feedParam) > 0 { + whisk.Debug(whisk.DbgError, "trigger %+v is found but it does not contain a feed. \n", trigger) + err := errors.New("this trigger does not contain a feed") + errStr := wski18n.T(FEED_CONFIGURATION_FAILURE, map[string]interface{}{"feedname": qualifiedName.GetEntityName(), "err": err}) + werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) + return werr + } + } + + if len(fullFeedName) > 0 && feedParameterChanged(Flags.trigger.feedParam) { + //if there is feed, we invoke the action to configure the feed regardless any changes on feed parameters + fullTriggerName := fmt.Sprintf("/%s/%s", qualifiedName.GetNamespace(), qualifiedName.GetEntityName()) + Flags.trigger.feedParam = append(Flags.trigger.feedParam, getFormattedJSON(FEED_LIFECYCLE_EVENT, FEED_UPDATE)) + Flags.trigger.feedParam = append(Flags.trigger.feedParam, getFormattedJSON(FEED_TRIGGER_NAME, fullTriggerName)) + Flags.trigger.feedParam = append(Flags.trigger.feedParam, getFormattedJSON(FEED_AUTH_KEY, Client.Config.AuthToken)) + + // Invoke the specified feed action to configure the trigger feed + err = configureFeed(qualifiedName.GetEntityName(), fullFeedName, getParameters(Flags.trigger.feedParam, false, false)) + if err != nil { + whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", qualifiedName.GetEntityName(), Flags.common.feed, err) + errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.err}}", + map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) + werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) + return werr + } + } + + fmt.Fprintf(color.Output, + wski18n.T("{{.ok}} updated trigger {{.name}}\n", + map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qualifiedName.GetEntityName())})) return nil } + +func feedParameterChanged(triggerParam []string) bool { + return len(triggerParam) > 0 +} diff --git a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala index 2656b78af..f907109d2 100644 --- a/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala +++ b/tests/src/test/scala/org/apache/openwhisk/core/cli/test/WskCliBasicUsageTests.scala @@ -794,7 +794,7 @@ class WskCliBasicUsageTests extends TestHelpers with WskTestHelpers { }) var secretIsInt = secretJsVar.get.convertTo[JsObject].getFields("value").head match { - case JsString(x) => true + case JsNumber(x) => true case _ => false } secretIsInt shouldBe true From f0fab1fe5c0acc32e215f6e3f7270c581e96d434 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Sat, 1 Feb 2020 00:16:17 -0500 Subject: [PATCH 04/15] trigger travis build --- commands/trigger.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/trigger.go b/commands/trigger.go index 15b6ce5e3..01a77848b 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -454,7 +454,7 @@ func (t *Trigger) Create(Client *whisk.Client, args []string) error { annotations := getParameters(annotationArray, true, true) //simplestTrigger indicates user are creating a trigger without any feed or parameters - simplestTrigger := (len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0) + simplestTrigger := len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0 //if users are 1. creating a trigger without any feed or parameters // 2. creating a trigger using --param flag @@ -652,7 +652,7 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { } //simplestTrigger indicates user are updating a trigger without any feed or parameters - simplestTrigger := (len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0) + simplestTrigger := len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0 //if users are 1. creating a trigger without any feed or parameters // 2. creating a trigger using --param flag From 7fb2c36fe4d88400d4c971a3822b11a0d2ceda76 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Fri, 7 Feb 2020 12:41:00 -0500 Subject: [PATCH 05/15] add tests --- commands/commands.go | 2 - commands/trigger.go | 263 +++++++++++------- .../scala/system/basic/WskCliBasicTests.scala | 42 +++ 3 files changed, 206 insertions(+), 101 deletions(-) diff --git a/commands/commands.go b/commands/commands.go index bcaaed39e..f6b2ab03e 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -19,7 +19,6 @@ package commands import ( "errors" - "fmt" "net/http" "os" "runtime" @@ -187,7 +186,6 @@ func parseArgs(args []string) ([]string, []string, []string, []string, []string, return nil, nil, nil, nil, nil, whiskErr } } else if args[i] == "-a" || args[i] == "--annotation" { - fmt.Println("4") annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs) if whiskErr != nil { whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr) diff --git a/commands/trigger.go b/commands/trigger.go index 01a77848b..ea68782be 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -20,7 +20,6 @@ package commands import ( "errors" "fmt" - "os" "github.com/apache/openwhisk-cli/wski18n" "github.com/apache/openwhisk-client-go/whisk" @@ -398,13 +397,15 @@ func init() { triggerCreateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerCreateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format")) triggerCreateCmd.Flags().StringVarP(&Flags.common.feed, "feed", "f", "", wski18n.T("trigger feed `ACTION_NAME`")) - triggerCreateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) + triggerCreateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("feed parameter values in `KEY VALUE` format")) + triggerCreateCmd.Flags().StringSliceVarP(&Flags.trigger.triggerParam, "trigger-param", "T", []string{}, wski18n.T("trigger parameter values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringSliceVarP(&Flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringVarP(&Flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format")) triggerUpdateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) triggerUpdateCmd.Flags().StringVarP(&Flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format")) - triggerUpdateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("parameter values in `KEY VALUE` format")) + triggerUpdateCmd.Flags().StringSliceVarP(&Flags.trigger.feedParam, "feed-param", "F", []string{}, wski18n.T("feed parameter values in `KEY VALUE` format")) + triggerUpdateCmd.Flags().StringSliceVarP(&Flags.trigger.triggerParam, "trigger-param", "T", []string{}, wski18n.T("trigger parameter values in `KEY VALUE` format")) triggerGetCmd.Flags().BoolVarP(&Flags.trigger.summary, "summary", "s", false, wski18n.T("summarize trigger details; parameters with prefix \"*\" are bound")) @@ -429,43 +430,37 @@ type Trigger struct { } func (t *Trigger) Create(Client *whisk.Client, args []string) error { - if whiskErr := CheckArgs(args, 1, 1, "Trigger create", wski18n.T("A trigger name is required.")); whiskErr != nil { return whiskErr } - triggerName, err := NewQualifiedName(args[0]) - if err != nil { - return NewQualifiedNameError(args[0], err) - } + //1. if the command line arguments user provides contains only --param flags + //2. if the command line arguments user provides contains no --param flags at all + //we should process the trigger create command in the old way. + if userIndicatesToUseOldTriggerCommand() { + triggerName, err := NewQualifiedName(args[0]) + if err != nil { + return NewQualifiedNameError(args[0], err) + } - annotationArray := Flags.common.annotation - authToken := Client.Config.AuthToken + //if user also issued new trigger command then we stop execution + if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil { + return triggerUsageErr + } - // if a feed is specified, create additional parameters which must be passed to the feed - feedQualifiedName, additionalFeedParams := feedParameters(Flags.common.feed, FEED_CREATE, triggerName, authToken) + annotationArray := Flags.common.annotation + authToken := Client.Config.AuthToken - // 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 feedQualifiedName != nil { - annotationArray = append(annotationArray, getFormattedJSON("feed", feedQualifiedName.GetFullQualifiedName())) - } - annotations := getParameters(annotationArray, true, true) + // if a feed is specified, create additional parameters which must be passed to the feed + feedQualifiedName, additionalFeedParams := feedParameters(Flags.common.feed, FEED_CREATE, triggerName, authToken) - //simplestTrigger indicates user are creating a trigger without any feed or parameters - simplestTrigger := len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0 - - //if users are 1. creating a trigger without any feed or parameters - // 2. creating a trigger using --param flag - //then we use the old way to create the trigger. - if len(Flags.common.param) > 0 || simplestTrigger { - if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { - whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") - errMsg := fmt.Sprintf("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag\n") - fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) - return nil + // 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 feedQualifiedName != nil { + annotationArray = append(annotationArray, getFormattedJSON("feed", feedQualifiedName.GetFullQualifiedName())) } + annotations := getParameters(annotationArray, true, true) // the feed receives all the parameters that are specified on the command line so we merge // the feed lifecycle parameters with the command line ones @@ -518,16 +513,38 @@ func (t *Trigger) Create(Client *whisk.Client, args []string) error { map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)})) return nil } + //1. if user's input command line argument contains either --feed-param or --trigger-param + //2. if user's input command line argument contains both --feed-param and --trigger-param + //then we process trigger create command in a different way + return CreateExtendedVersion(Client, args) +} + +//CreateExtendedVersion only executes when users indicate to create triggers with --feed-param +//or --trigger-param flags. +func CreateExtendedVersion(Client *whisk.Client, args []string) error { + triggerName, err := NewQualifiedName(args[0]) + if err != nil { + return NewQualifiedNameError(args[0], err) + } + + annotationArray := Flags.common.annotation + authToken := Client.Config.AuthToken + + // if a feed is specified, create additional parameters which must be passed to the feed + feedQualifiedName, additionalFeedParams := feedParameters(Flags.common.feed, FEED_CREATE, triggerName, authToken) - //if users are using either --feed-param or --trigger-param flag, - //then we know the users are trying to separate trigger and feed params and - //we use the enhanced way to create trigger + // 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 feedQualifiedName != nil { + annotationArray = append(annotationArray, getFormattedJSON("feed", feedQualifiedName.GetFullQualifiedName())) + } + annotations := getParameters(annotationArray, true, true) + //if trigger contains no feed but user tries to update feed parameter, then we issue error. if feedQualifiedName == nil && len(Flags.trigger.feedParam) > 0 { - //trigger without feed names cannot have a feed param - errMsg := fmt.Sprintf("Incorrect usage. trigger without a feed cannot have feed parameters. \n") - fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) - return nil + whisk.Debug(whisk.DbgError, "Incorrect usage. trigger without a feed cannot have feed parameters.") + errStr := wski18n.T("Incorrect usage. trigger without a feed cannot have feed parameters.") + return whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) } triggerParams := getParameters(Flags.trigger.triggerParam, true, false) @@ -573,64 +590,32 @@ func (t *Trigger) Create(Client *whisk.Client, args []string) error { fmt.Fprintf(color.Output, wski18n.T("{{.ok}} created trigger {{.name}}\n", map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)})) + return nil } func (t *Trigger) Update(Client *whisk.Client, args []string) error { - var err error - var fullFeedName string - var qualifiedName = new(QualifiedName) - if whiskErr := CheckArgs(args, 1, 1, "Trigger update", wski18n.T("A trigger name is required.")); whiskErr != nil { return whiskErr } + var err error + var fullFeedName string + var qualifiedName = new(QualifiedName) + if qualifiedName, err = NewQualifiedName(args[0]); err != nil { return NewQualifiedNameError(args[0], err) } Client.Namespace = qualifiedName.GetNamespace() - // 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, true) - 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 - } - - whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", Flags.trigger.triggerParam) - triggerParameters, err := getJSONFromStrings(Flags.trigger.triggerParam, true) - 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 - } - - whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) - annotations, err := getJSONFromStrings(Flags.common.annotation, true) - - 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 - } - retTrigger, httpResp, err := Client.Triggers.Get(qualifiedName.GetEntityName()) - if err != nil && httpResp.StatusCode == 404 { - t.Create(Client, args) + triggerCreateErr := t.Create(Client, args) + if triggerCreateErr != nil { + return triggerCreateErr + } return nil } else if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) @@ -640,29 +625,47 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { return werr } - // Get full feed name from trigger get request as it is needed to get the feed - if retTrigger != nil && retTrigger.Annotations != nil { - fullFeedName = getValueString(retTrigger.Annotations, "feed") - } + //1. if the command line arguments user provides contains only --param flags + //2. if the command line arguments user provides contains no --param flags at all + //we should process the trigger update command in the old way. + if userIndicatesToUseOldTriggerCommand() { + //if user also issued new trigger command then we stop execution + if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil { + return triggerUsageErr + } - trigger := &whisk.Trigger{ - Name: qualifiedName.GetEntityName(), - Parameters: parameters.(whisk.KeyValueArr), - Annotations: annotations.(whisk.KeyValueArr), - } + // 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, true) + 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 + } - //simplestTrigger indicates user are updating a trigger without any feed or parameters - simplestTrigger := len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0 + whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) + annotations, err := getJSONFromStrings(Flags.common.annotation, true) + 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 users are 1. creating a trigger without any feed or parameters - // 2. creating a trigger using --param flag - //then we use the old way to create the trigger. - if len(Flags.common.param) > 0 || simplestTrigger { - if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { - whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") - errMsg := fmt.Sprintf("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag\n") - fmt.Fprintf(os.Stderr, "%s%s", color.RedString("error: "), errors.New(errMsg)) - return nil + trigger := &whisk.Trigger{ + Name: qualifiedName.GetEntityName(), + Parameters: parameters.(whisk.KeyValueArr), + Annotations: annotations.(whisk.KeyValueArr), + } + + // Get full feed name from trigger get request as it is needed to get the feed + if retTrigger != nil && retTrigger.Annotations != nil { + fullFeedName = getValueString(retTrigger.Annotations, "feed") } if len(fullFeedName) > 0 { @@ -698,8 +701,54 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { return nil } + //1. if user's input command line argument contains either --feed-param or --trigger-param + //2. if user's input command line argument contains both --feed-param and --trigger-param + //then we process trigger update command in a different way + return UpdateExtendedVersion(Client, args, retTrigger) +} + +//UpdateExtendedVersion only executes when users indicate to update triggers with --feed-param +//or --trigger-param flags. +func UpdateExtendedVersion(Client *whisk.Client, args []string, retTrigger *whisk.Trigger) error { + var fullFeedName string + var qualifiedName = new(QualifiedName) + var err error + + if qualifiedName, err = NewQualifiedName(args[0]); err != nil { + return NewQualifiedNameError(args[0], err) + } + + whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", Flags.trigger.triggerParam) + triggerParameters, err := getJSONFromStrings(Flags.trigger.triggerParam, true) + 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 + } + + whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) + annotations, err := getJSONFromStrings(Flags.common.annotation, true) + 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 + } + + trigger := &whisk.Trigger{ + Name: qualifiedName.GetEntityName(), + Parameters: triggerParameters.(whisk.KeyValueArr), + Annotations: annotations.(whisk.KeyValueArr), + } + + // Get full feed name from trigger get request as it is needed to get the feed + if retTrigger != nil && retTrigger.Annotations != nil { + fullFeedName = getValueString(retTrigger.Annotations, "feed") + } - trigger.Parameters = triggerParameters.(whisk.KeyValueArr) _, _, err = Client.Triggers.Insert(trigger, true) if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) @@ -748,3 +797,19 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { func feedParameterChanged(triggerParam []string) bool { return len(triggerParam) > 0 } + +//if users are 1. creating a trigger without any feed or parameters +// 2. creating a trigger using --param flag +//then we use the old way to create the trigger. +func userIndicatesToUseOldTriggerCommand() bool { + return len(Flags.common.param) > 0 || (len(Flags.trigger.feedParam) == 0 && len(Flags.common.param) == 0 && len(Flags.trigger.triggerParam) == 0) +} + +func userIssuedNewTriggerCmd() error { + if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { + whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") + errStr := wski18n.T("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag") + return whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) + } + return nil +} diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index c3a7cf77c..9f9935ecb 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -491,6 +491,48 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { wsk.trigger.list().stdout should include(triggerName) } + it should "return error message when updating feed param on trigger that contains no feed param" in withAssetCleaner( + wskprops) { (wp, assetHelper) => + val triggerName = withTimestamp("t1tor1") + val ns = wsk.namespace.whois() + val params = Map("a" -> "A".toJson) + + assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) => + trigger.create(triggerName, parameters = params) + } + wsk + .cli( + Seq("trigger", "update", triggerName, "-F", "feedParam", "feedParamVal", "--auth", wskprops.authKey) ++ wskprops.overrides, + expectedExitCode = ERROR_EXIT) + .stderr should include("this trigger does not contain a feed") + val stderr = wsk.trigger.delete(triggerName, expectedExitCode = SUCCESS_EXIT).stderr + } + + it should "return error message when creating or updating feed with both --param and --trigger-param/--feed-param flags" in withAssetCleaner( + wskprops) { (wp, assetHelper) => + val triggerName = withTimestamp("t1tor1") + val ns = wsk.namespace.whois() + + var stderr = + wsk + .cli( + Seq( + "trigger", + "create", + triggerName, + "-p", + "a", + "A", + "-F", + "feedParam", + "feedParamVal", + "--auth", + wskprops.authKey) ++ wskprops.overrides, + expectedExitCode = NOT_ALLOWED) + .stderr + stderr should include("Cannot combine --feed-param or --trigger-param flag with --param flag") + } + it should "create, and get a trigger summary" in withAssetCleaner(wskprops) { (wp, assetHelper) => val name = "triggerName" val annots = Map( From 9836d540d237cebce5889d571a1d8704f9eede3d Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 11:54:25 -0500 Subject: [PATCH 06/15] update tests --- tests/src/test/scala/system/basic/WskCliBasicTests.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index 9f9935ecb..281ef138c 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -505,7 +505,6 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { Seq("trigger", "update", triggerName, "-F", "feedParam", "feedParamVal", "--auth", wskprops.authKey) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT) .stderr should include("this trigger does not contain a feed") - val stderr = wsk.trigger.delete(triggerName, expectedExitCode = SUCCESS_EXIT).stderr } it should "return error message when creating or updating feed with both --param and --trigger-param/--feed-param flags" in withAssetCleaner( From 8854a9d94cf032ceb8b8ec001933377eb6232d62 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 14:41:44 -0500 Subject: [PATCH 07/15] trigger travis --- tests/src/test/scala/system/basic/WskCliBasicTests.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index 281ef138c..eac6d6d4c 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -500,6 +500,7 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) => trigger.create(triggerName, parameters = params) } + wsk .cli( Seq("trigger", "update", triggerName, "-F", "feedParam", "feedParamVal", "--auth", wskprops.authKey) ++ wskprops.overrides, From 008987b4ac6c8b3c7372e094338e1cdc4c91f07b Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 15:00:46 -0500 Subject: [PATCH 08/15] scala fmt --- tests/src/test/scala/system/basic/WskCliBasicTests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index eac6d6d4c..469085eac 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -500,7 +500,7 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) => trigger.create(triggerName, parameters = params) } - + wsk .cli( Seq("trigger", "update", triggerName, "-F", "feedParam", "feedParamVal", "--auth", wskprops.authKey) ++ wskprops.overrides, From 96a4b61659bf7b85472578e603336690f39fc736 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 15:51:36 -0500 Subject: [PATCH 09/15] trigger travis build --- tests/src/test/scala/system/basic/WskCliBasicTests.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index 469085eac..281ef138c 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -500,7 +500,6 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) => trigger.create(triggerName, parameters = params) } - wsk .cli( Seq("trigger", "update", triggerName, "-F", "feedParam", "feedParamVal", "--auth", wskprops.authKey) ++ wskprops.overrides, From c97bd7ad1141ec940ec23dfcf5d98120cf2fa548 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 18:15:00 -0500 Subject: [PATCH 10/15] trigger travis --- commands/trigger.go | 1 + 1 file changed, 1 insertion(+) diff --git a/commands/trigger.go b/commands/trigger.go index ea68782be..7435c9444 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -538,6 +538,7 @@ func CreateExtendedVersion(Client *whisk.Client, args []string) error { if feedQualifiedName != nil { annotationArray = append(annotationArray, getFormattedJSON("feed", feedQualifiedName.GetFullQualifiedName())) } + annotations := getParameters(annotationArray, true, true) //if trigger contains no feed but user tries to update feed parameter, then we issue error. From 051e9cb5b81881cabc3432c5ba082e36e17a425b Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 17 Feb 2020 21:08:57 -0500 Subject: [PATCH 11/15] retore old flow of control logic --- commands/trigger.go | 208 +++++++++++++++++++++++++++++++++----------- 1 file changed, 157 insertions(+), 51 deletions(-) diff --git a/commands/trigger.go b/commands/trigger.go index 7435c9444..a111b476b 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -596,74 +596,65 @@ func CreateExtendedVersion(Client *whisk.Client, args []string) error { } func (t *Trigger) Update(Client *whisk.Client, args []string) error { + var err error + var fullFeedName string + var qualifiedName = new(QualifiedName) + if whiskErr := CheckArgs(args, 1, 1, "Trigger update", wski18n.T("A trigger name is required.")); whiskErr != nil { return whiskErr } - var err error - var fullFeedName string - var qualifiedName = new(QualifiedName) - if qualifiedName, err = NewQualifiedName(args[0]); err != nil { return NewQualifiedNameError(args[0], err) } Client.Namespace = qualifiedName.GetNamespace() + // 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, true) + + 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 + } + + whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) + annotations, err := getJSONFromStrings(Flags.common.annotation, true) + + 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 + } + retTrigger, httpResp, err := Client.Triggers.Get(qualifiedName.GetEntityName()) + if err != nil && httpResp.StatusCode == 404 { - triggerCreateErr := t.Create(Client, args) - if triggerCreateErr != nil { - return triggerCreateErr - } - return nil + t.Create(Client, args) } else if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}", map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return werr - } + } else { + if !userIndicatesToUseOldTriggerCommand() { + return UpdateExtendedVersion(Client, args, retTrigger) + } - //1. if the command line arguments user provides contains only --param flags - //2. if the command line arguments user provides contains no --param flags at all - //we should process the trigger update command in the old way. - if userIndicatesToUseOldTriggerCommand() { - //if user also issued new trigger command then we stop execution if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil { return triggerUsageErr } - - // 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, true) - 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 - } - - whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) - annotations, err := getJSONFromStrings(Flags.common.annotation, true) - 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 - } - - trigger := &whisk.Trigger{ - Name: qualifiedName.GetEntityName(), - Parameters: parameters.(whisk.KeyValueArr), - Annotations: annotations.(whisk.KeyValueArr), - } - // Get full feed name from trigger get request as it is needed to get the feed if retTrigger != nil && retTrigger.Annotations != nil { fullFeedName = getValueString(retTrigger.Annotations, "feed") @@ -686,6 +677,12 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { return werr } } else { + trigger := &whisk.Trigger{ + Name: qualifiedName.GetEntityName(), + Parameters: parameters.(whisk.KeyValueArr), + Annotations: annotations.(whisk.KeyValueArr), + } + _, _, err = Client.Triggers.Insert(trigger, true) if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) @@ -699,15 +696,124 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { fmt.Fprintf(color.Output, wski18n.T("{{.ok}} updated trigger {{.name}}\n", map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qualifiedName.GetEntityName())})) - - return nil } - //1. if user's input command line argument contains either --feed-param or --trigger-param - //2. if user's input command line argument contains both --feed-param and --trigger-param - //then we process trigger update command in a different way - return UpdateExtendedVersion(Client, args, retTrigger) + + return nil } +// func (t *Trigger) Update(Client *whisk.Client, args []string) error { +// if whiskErr := CheckArgs(args, 1, 1, "Trigger update", +// wski18n.T("A trigger name is required.")); whiskErr != nil { +// return whiskErr +// } + +// var err error +// var fullFeedName string +// var qualifiedName = new(QualifiedName) + +// if qualifiedName, err = NewQualifiedName(args[0]); err != nil { +// return NewQualifiedNameError(args[0], err) +// } + +// Client.Namespace = qualifiedName.GetNamespace() + +// retTrigger, httpResp, err := Client.Triggers.Get(qualifiedName.GetEntityName()) +// if err != nil && httpResp.StatusCode == 404 { +// triggerCreateErr := t.Create(Client, args) +// if triggerCreateErr != nil { +// return triggerCreateErr +// } +// return nil +// } else if err != nil { +// whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) +// errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}", +// map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) +// werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) +// return werr +// } + +// //1. if the command line arguments user provides contains only --param flags +// //2. if the command line arguments user provides contains no --param flags at all +// //we should process the trigger update command in the old way. +// if userIndicatesToUseOldTriggerCommand() { +// //if user also issued new trigger command then we stop execution +// if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil { +// return triggerUsageErr +// } + +// // 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, true) +// 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 +// } + +// whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) +// annotations, err := getJSONFromStrings(Flags.common.annotation, true) +// 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 +// } + +// trigger := &whisk.Trigger{ +// Name: qualifiedName.GetEntityName(), +// Parameters: parameters.(whisk.KeyValueArr), +// Annotations: annotations.(whisk.KeyValueArr), +// } + +// // Get full feed name from trigger get request as it is needed to get the feed +// if retTrigger != nil && retTrigger.Annotations != nil { +// fullFeedName = getValueString(retTrigger.Annotations, "feed") +// } + +// if len(fullFeedName) > 0 { +// fullTriggerName := fmt.Sprintf("/%s/%s", qualifiedName.GetNamespace(), qualifiedName.GetEntityName()) +// Flags.common.param = append(Flags.common.param, getFormattedJSON(FEED_LIFECYCLE_EVENT, FEED_UPDATE)) +// 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)) + +// // Invoke the specified feed action to configure the trigger feed +// err = configureFeed(qualifiedName.GetEntityName(), fullFeedName, getParameters(Flags.common.param, false, false)) +// if err != nil { +// whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", qualifiedName.GetEntityName(), Flags.common.feed, +// err) +// errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.err}}", +// map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) +// werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) +// return werr +// } +// } else { +// _, _, err = Client.Triggers.Insert(trigger, true) +// if err != nil { +// whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) +// errStr := wski18n.T("Unable to update 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 +// } +// } + +// fmt.Fprintf(color.Output, +// wski18n.T("{{.ok}} updated trigger {{.name}}\n", +// map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qualifiedName.GetEntityName())})) + +// return nil +// } +// //1. if user's input command line argument contains either --feed-param or --trigger-param +// //2. if user's input command line argument contains both --feed-param and --trigger-param +// //then we process trigger update command in a different way +// return UpdateExtendedVersion(Client, args, retTrigger) +// } + //UpdateExtendedVersion only executes when users indicate to update triggers with --feed-param //or --trigger-param flags. func UpdateExtendedVersion(Client *whisk.Client, args []string, retTrigger *whisk.Trigger) error { From 32c9fd9b28a6cc926b49b709ef6d302f26e74d3c Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Tue, 18 Feb 2020 13:32:25 -0500 Subject: [PATCH 12/15] keep origin update function flow of control as much ap --- commands/trigger.go | 118 ++------------------------------------------ 1 file changed, 4 insertions(+), 114 deletions(-) diff --git a/commands/trigger.go b/commands/trigger.go index a111b476b..6f7a63bb0 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -640,7 +640,10 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { retTrigger, httpResp, err := Client.Triggers.Get(qualifiedName.GetEntityName()) if err != nil && httpResp.StatusCode == 404 { - t.Create(Client, args) + if createErr := t.Create(Client, args); createErr != nil { + return createErr + } + return nil } else if err != nil { whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}", @@ -701,119 +704,6 @@ func (t *Trigger) Update(Client *whisk.Client, args []string) error { return nil } -// func (t *Trigger) Update(Client *whisk.Client, args []string) error { -// if whiskErr := CheckArgs(args, 1, 1, "Trigger update", -// wski18n.T("A trigger name is required.")); whiskErr != nil { -// return whiskErr -// } - -// var err error -// var fullFeedName string -// var qualifiedName = new(QualifiedName) - -// if qualifiedName, err = NewQualifiedName(args[0]); err != nil { -// return NewQualifiedNameError(args[0], err) -// } - -// Client.Namespace = qualifiedName.GetNamespace() - -// retTrigger, httpResp, err := Client.Triggers.Get(qualifiedName.GetEntityName()) -// if err != nil && httpResp.StatusCode == 404 { -// triggerCreateErr := t.Create(Client, args) -// if triggerCreateErr != nil { -// return triggerCreateErr -// } -// return nil -// } else if err != nil { -// whisk.Debug(whisk.DbgError, "Client.Triggers.Get(%s) failed: %s\n", qualifiedName.GetEntityName(), err) -// errStr := wski18n.T("Unable to get trigger '{{.name}}': {{.err}}", -// map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) -// werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) -// return werr -// } - -// //1. if the command line arguments user provides contains only --param flags -// //2. if the command line arguments user provides contains no --param flags at all -// //we should process the trigger update command in the old way. -// if userIndicatesToUseOldTriggerCommand() { -// //if user also issued new trigger command then we stop execution -// if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil { -// return triggerUsageErr -// } - -// // 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, true) -// 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 -// } - -// whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", Flags.common.annotation) -// annotations, err := getJSONFromStrings(Flags.common.annotation, true) -// 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 -// } - -// trigger := &whisk.Trigger{ -// Name: qualifiedName.GetEntityName(), -// Parameters: parameters.(whisk.KeyValueArr), -// Annotations: annotations.(whisk.KeyValueArr), -// } - -// // Get full feed name from trigger get request as it is needed to get the feed -// if retTrigger != nil && retTrigger.Annotations != nil { -// fullFeedName = getValueString(retTrigger.Annotations, "feed") -// } - -// if len(fullFeedName) > 0 { -// fullTriggerName := fmt.Sprintf("/%s/%s", qualifiedName.GetNamespace(), qualifiedName.GetEntityName()) -// Flags.common.param = append(Flags.common.param, getFormattedJSON(FEED_LIFECYCLE_EVENT, FEED_UPDATE)) -// 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)) - -// // Invoke the specified feed action to configure the trigger feed -// err = configureFeed(qualifiedName.GetEntityName(), fullFeedName, getParameters(Flags.common.param, false, false)) -// if err != nil { -// whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", qualifiedName.GetEntityName(), Flags.common.feed, -// err) -// errStr := wski18n.T("Unable to create trigger '{{.name}}': {{.err}}", -// map[string]interface{}{"name": qualifiedName.GetEntityName(), "err": err}) -// werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) -// return werr -// } -// } else { -// _, _, err = Client.Triggers.Insert(trigger, true) -// if err != nil { -// whisk.Debug(whisk.DbgError, "Client.Triggers.Insert(%+v,true) failed: %s\n", trigger, err) -// errStr := wski18n.T("Unable to update 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 -// } -// } - -// fmt.Fprintf(color.Output, -// wski18n.T("{{.ok}} updated trigger {{.name}}\n", -// map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(qualifiedName.GetEntityName())})) - -// return nil -// } -// //1. if user's input command line argument contains either --feed-param or --trigger-param -// //2. if user's input command line argument contains both --feed-param and --trigger-param -// //then we process trigger update command in a different way -// return UpdateExtendedVersion(Client, args, retTrigger) -// } - //UpdateExtendedVersion only executes when users indicate to update triggers with --feed-param //or --trigger-param flags. func UpdateExtendedVersion(Client *whisk.Client, args []string, retTrigger *whisk.Trigger) error { From 8f21bc417a8d159ff72221aba749fb3e7f77ba35 Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 24 Feb 2020 17:03:25 -0500 Subject: [PATCH 13/15] improve error msg/add test --- commands/trigger.go | 8 +-- .../scala/system/basic/WskCliBasicTests.scala | 60 ++++++++++++++++++- wski18n/resources/en_US.all.json | 16 +++++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/commands/trigger.go b/commands/trigger.go index 6f7a63bb0..564e362bf 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -543,8 +543,8 @@ func CreateExtendedVersion(Client *whisk.Client, args []string) error { //if trigger contains no feed but user tries to update feed parameter, then we issue error. if feedQualifiedName == nil && len(Flags.trigger.feedParam) > 0 { - whisk.Debug(whisk.DbgError, "Incorrect usage. trigger without a feed cannot have feed parameters.") - errStr := wski18n.T("Incorrect usage. trigger without a feed cannot have feed parameters.") + whisk.Debug(whisk.DbgError, "Incorrect usage. trigger without a feed cannot have feed parameters") + errStr := wski18n.T("Incorrect usage. trigger without a feed cannot have feed parameters") return whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) } @@ -804,8 +804,8 @@ func userIndicatesToUseOldTriggerCommand() bool { func userIssuedNewTriggerCmd() error { if len(Flags.trigger.feedParam) > 0 || len(Flags.trigger.triggerParam) > 0 { - whisk.Debug(whisk.DbgError, "User tries to mix use of --param with --feed-param and --trigger-param") - errStr := wski18n.T("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with --param flag") + whisk.Debug(whisk.DbgError, "User tries to mix use of --param or --param-file flags with --feed-param or --trigger-param") + errStr := wski18n.T("Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag") return whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) } return nil diff --git a/tests/src/test/scala/system/basic/WskCliBasicTests.scala b/tests/src/test/scala/system/basic/WskCliBasicTests.scala index 281ef138c..a892bbacf 100644 --- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala @@ -507,7 +507,7 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { .stderr should include("this trigger does not contain a feed") } - it should "return error message when creating or updating feed with both --param and --trigger-param/--feed-param flags" in withAssetCleaner( + it should "return error message when creating feed with both --param and --trigger-param/--feed-param flags" in withAssetCleaner( wskprops) { (wp, assetHelper) => val triggerName = withTimestamp("t1tor1") val ns = wsk.namespace.whois() @@ -529,7 +529,63 @@ class WskCliBasicTests extends TestHelpers with WskTestHelpers { wskprops.authKey) ++ wskprops.overrides, expectedExitCode = NOT_ALLOWED) .stderr - stderr should include("Cannot combine --feed-param or --trigger-param flag with --param flag") + stderr should include( + "Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag") + } + + it should "return error message when updating feed with both --param and --trigger-param/--feed-param flags" in withAssetCleaner( + wskprops) { (wp, assetHelper) => + val triggerName = withTimestamp("t1tor1") + val ns = wsk.namespace.whois() + + var stderr = + wsk + .cli( + Seq( + "trigger", + "update", + triggerName, + "-p", + "a", + "A", + "-T", + "feedParam", + "feedParamVal", + "--auth", + wskprops.authKey) ++ wskprops.overrides, + expectedExitCode = NOT_ALLOWED) + .stderr + stderr should include( + "Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag") + } + + it should "return error message when creating feed with both --param-file and --trigger-param/--feed-param flags" in withAssetCleaner( + wskprops) { (wp, assetHelper) => + val triggerName = withTimestamp("t1tor1") + val ns = wsk.namespace.whois() + val filePathString = TestUtils.getTestActionFilename("argCheck.js") + + var stderr = + wsk + .cli( + Seq( + "trigger", + "create", + triggerName, + "--param-file", + filePathString, + "-F", + "feedParam", + "feedParamVal", + "-T", + "triggerParam", + "triggerParamVal", + "--auth", + wskprops.authKey) ++ wskprops.overrides, + expectedExitCode = NOT_ALLOWED) + .stderr + stderr should include( + "Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag") } it should "create, and get a trigger summary" in withAssetCleaner(wskprops) { (wp, assetHelper) => diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json index fbcdfb87c..e90d6a33e 100644 --- a/wski18n/resources/en_US.all.json +++ b/wski18n/resources/en_US.all.json @@ -1594,5 +1594,21 @@ { "id": "CMD_DESC_LONG_EXPORT", "translation": "Exports managed project assets from OpenWhisk to manifest and function files.\n\nThe most common way to run export:\n$ wsk project export --projectname PROJECT --manifest path/to/exported-manifest.yaml" + }, + { + "id": "Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag", + "translation": "Incorrect usage. Cannot combine --feed-param or --trigger-param flag with neither --param nor --param-file flag" + }, + { + "id": "trigger parameter values in `KEY VALUE` format", + "translation": "trigger parameter values in `KEY VALUE` format" + }, + { + "id": "feed parameter values in `KEY VALUE` format", + "translation": "feed parameter values in `KEY VALUE` format" + }, + { + "id": "Incorrect usage. trigger without a feed cannot have feed parameters", + "translation": "Incorrect usage. trigger without a feed cannot have feed parameters" } ] From a3366c86e8d369087ae122cc2afeb85f6d2b3dce Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Mon, 24 Feb 2020 21:13:58 -0500 Subject: [PATCH 14/15] capital T --- wski18n/resources/en_US.all.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json index e90d6a33e..a887e0346 100644 --- a/wski18n/resources/en_US.all.json +++ b/wski18n/resources/en_US.all.json @@ -1608,7 +1608,7 @@ "translation": "feed parameter values in `KEY VALUE` format" }, { - "id": "Incorrect usage. trigger without a feed cannot have feed parameters", - "translation": "Incorrect usage. trigger without a feed cannot have feed parameters" + "id": "Incorrect usage. Trigger without a feed cannot have feed parameters", + "translation": "Incorrect usage. Trigger without a feed cannot have feed parameters" } ] From 1bd7927dc34639c82601136fc17d3c04b4824e8f Mon Sep 17 00:00:00 2001 From: Steven DOng Date: Tue, 25 Feb 2020 11:18:42 -0500 Subject: [PATCH 15/15] Capital T again --- commands/trigger.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/commands/trigger.go b/commands/trigger.go index 564e362bf..c5cec1da5 100644 --- a/commands/trigger.go +++ b/commands/trigger.go @@ -543,8 +543,7 @@ func CreateExtendedVersion(Client *whisk.Client, args []string) error { //if trigger contains no feed but user tries to update feed parameter, then we issue error. if feedQualifiedName == nil && len(Flags.trigger.feedParam) > 0 { - whisk.Debug(whisk.DbgError, "Incorrect usage. trigger without a feed cannot have feed parameters") - errStr := wski18n.T("Incorrect usage. trigger without a feed cannot have feed parameters") + errStr := wski18n.T("Incorrect usage. Trigger without a feed cannot have feed parameters") return whisk.MakeWskError(errors.New(errStr), whisk.NOT_ALLOWED, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) }