Trigger parameter issue (#479)

* allow trigger feed and trigger parameters
diff --git a/commands/commands.go b/commands/commands.go
index cbc1ce5..f6b2ab0 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -131,9 +131,11 @@
 	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 +149,14 @@
 					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 +166,14 @@
 					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,7 +183,7 @@
 					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" {
 			annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs)
@@ -191,7 +193,23 @@
 					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 +218,18 @@
 
 	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 25c9b96..b48058c 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -112,7 +112,9 @@
 
 	// trigger
 	trigger struct {
-		summary bool
+		summary      bool
+		feedParam    []string
+		triggerParam []string
 	}
 
 	//sdk
diff --git a/commands/trigger.go b/commands/trigger.go
index 86b18da..c5cec1d 100644
--- a/commands/trigger.go
+++ b/commands/trigger.go
@@ -397,11 +397,15 @@
 	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("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("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"))
 
@@ -431,52 +435,140 @@
 		return whiskErr
 	}
 
+	//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)
+		}
+
+		//if user also issued new trigger command then we stop execution
+		if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil {
+			return triggerUsageErr
+		}
+
+		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 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
+		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
+	}
+	//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)
 	}
 
-	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)
 
+	//if trigger contains no feed but user tries to update feed parameter, then we issue error.
+	if feedQualifiedName == nil && len(Flags.trigger.feedParam) > 0 {
+		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)
+	//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,17 +580,17 @@
 			}
 
 			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,
 		wski18n.T("{{.ok}} created trigger {{.name}}\n",
 			map[string]interface{}{"ok": color.GreenString("ok:"), "name": boldString(trigger.Name)}))
+
 	return nil
 }
 
@@ -547,7 +639,10 @@
 	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}}",
@@ -555,7 +650,13 @@
 		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)
+		}
 
+		if triggerUsageErr := userIssuedNewTriggerCmd(); triggerUsageErr != nil {
+			return triggerUsageErr
+		}
 		// 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")
@@ -601,3 +702,110 @@
 
 	return nil
 }
+
+//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")
+	}
+
+	_, _, 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
+}
+
+//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 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 c3a7cf7..a892bba 100644
--- a/tests/src/test/scala/system/basic/WskCliBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskCliBasicTests.scala
@@ -491,6 +491,103 @@
     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")
+  }
+
+  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()
+
+    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(
+      "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) =>
     val name = "triggerName"
     val annots = Map(
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index fbcdfb8..a887e03 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"
   }
 ]