You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2018/06/18 16:37:25 UTC

[GitHub] houshengbo closed pull request #319: Refactor action invoke functions

houshengbo closed pull request #319: Refactor action invoke functions 
URL: https://github.com/apache/incubator-openwhisk-cli/pull/319
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
index 55423b34..717c0b47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ incubator-openwhisk-cli.iml
 wski18n/i18n_resources.go
 bin/
 tests/build/
+tests/out/
diff --git a/commands/action.go b/commands/action.go
index bce0bf2a..c21d9462 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -155,9 +155,8 @@ var actionInvokeCmd = &cobra.Command{
 	PreRunE:       SetupClientConfig,
 	RunE: func(cmd *cobra.Command, args []string) error {
 		var err error
-		var parameters interface{}
 		var qualifiedName = new(QualifiedName)
-		var paramArgs []string
+		var parameters interface{}
 
 		if whiskErr := CheckArgs(
 			args,
@@ -172,65 +171,79 @@ var actionInvokeCmd = &cobra.Command{
 			return NewQualifiedNameError(args[0], err)
 		}
 
-		Client.Namespace = qualifiedName.GetNamespace()
-		paramArgs = Flags.common.param
+		parameters = getParameters(Flags.common.param, false, false)
+		blocking := Flags.common.blocking || Flags.action.result
+		resultOnly := Flags.action.result
+		header := !resultOnly
 
-		if len(paramArgs) > 0 {
-			if parameters, err = getJSONFromStrings(paramArgs, false); err != nil {
-				return getJSONFromStringsParamError(paramArgs, false, err)
-			}
-		}
-		if Flags.action.result {
-			Flags.common.blocking = true
-		}
-
-		res, _, err := Client.Actions.Invoke(
-			qualifiedName.GetEntityName(),
+		res, err := invokeAction(
+			*qualifiedName,
 			parameters,
-			Flags.common.blocking,
-			Flags.action.result)
+			blocking,
+			resultOnly)
 
-		return handleInvocationResponse(*qualifiedName, parameters, res, err)
+		return printInvocationResponse(*qualifiedName, blocking, header, res, err)
 	},
 }
 
-func handleInvocationResponse(
+func invokeAction(
 	qualifiedName QualifiedName,
 	parameters interface{},
+	blocking bool,
+	result bool) (map[string]interface{}, error) {
+	// TODO remove all global modifiers
+	Client.Namespace = qualifiedName.GetNamespace()
+	res, _, err := Client.Actions.Invoke(
+		qualifiedName.GetEntityName(),
+		parameters,
+		blocking,
+		result)
+	return res, err
+}
+
+func printInvocationResponse(
+	qualifiedName QualifiedName,
+	blocking bool,
+	header bool,
 	result map[string]interface{},
 	err error) error {
 	if err == nil {
-		printInvocationMsg(
-			qualifiedName.GetNamespace(),
-			qualifiedName.GetEntityName(),
-			getValueFromJSONResponse(ACTIVATION_ID, result),
-			result,
-			color.Output)
+		printInvocationMsg(qualifiedName, blocking, header, result, color.Output)
 	} else {
-		if !Flags.common.blocking {
-			return handleInvocationError(err, qualifiedName.GetEntityName(), parameters)
+		if !blocking {
+			return handleInvocationError(err, qualifiedName.GetEntityName())
 		} else {
-			if isBlockingTimeout(err) {
-				printBlockingTimeoutMsg(
-					qualifiedName.GetNamespace(),
-					qualifiedName.GetEntityName(),
-					getValueFromJSONResponse(ACTIVATION_ID, result))
-			} else if isApplicationError(err) {
-				printInvocationMsg(
-					qualifiedName.GetNamespace(),
-					qualifiedName.GetEntityName(),
-					getValueFromJSONResponse(ACTIVATION_ID, result),
-					result,
-					colorable.NewColorableStderr())
-			} else {
-				return handleInvocationError(err, qualifiedName.GetEntityName(), parameters)
-			}
+			return printFailedBlockingInvocationResponse(qualifiedName, header, result, err)
 		}
 	}
 
 	return err
 }
 
+func printFailedBlockingInvocationResponse(
+	qualifiedName QualifiedName,
+	header bool,
+	result map[string]interface{},
+	err error) error {
+	if isBlockingTimeout(err) {
+		printBlockingTimeoutMsg(
+			qualifiedName.GetNamespace(),
+			qualifiedName.GetEntityName(),
+			getValueFromJSONResponse(ACTIVATION_ID, result))
+		return err
+	} else if isApplicationError(err) {
+		printInvocationMsg(
+			qualifiedName,
+			true,
+			header,
+			result,
+			colorable.NewColorableStderr())
+		return err
+	} else {
+		return handleInvocationError(err, qualifiedName.GetEntityName())
+	}
+}
+
 var actionGetCmd = &cobra.Command{
 	Use:           "get ACTION_NAME [FIELD_FILTER | --summary | --url]",
 	Short:         wski18n.T("get action"),
@@ -987,12 +1000,11 @@ func actionGetError(entityName string, fetchCode bool, err error) error {
 	return nestedError(errMsg, err)
 }
 
-func handleInvocationError(err error, entityName string, parameters interface{}) error {
+func handleInvocationError(err error, entityName string) error {
 	whisk.Debug(
 		whisk.DbgError,
-		"Client.Actions.Invoke(%s, %s, %t) error: %s\n",
-		entityName, parameters,
-		Flags.common.blocking,
+		"Client.Actions.Invoke(%s, %t) error: %s\n",
+		entityName,
 		err)
 
 	errMsg := wski18n.T(
@@ -1113,25 +1125,25 @@ func printBlockingTimeoutMsg(namespace string, entityName string, activationID i
 }
 
 func printInvocationMsg(
-	namespace string,
-	entityName string,
-	activationID interface{},
+	qualifiedName QualifiedName,
+	blocking bool,
+	header bool,
 	response map[string]interface{},
 	outputStream io.Writer) {
-	if !Flags.action.result {
+	if header {
 		fmt.Fprintf(
 			outputStream,
 			wski18n.T(
 				"{{.ok}} invoked /{{.namespace}}/{{.name}} with id {{.id}}\n",
 				map[string]interface{}{
 					"ok":        color.GreenString("ok:"),
-					"namespace": boldString(namespace),
-					"name":      boldString(entityName),
-					"id":        boldString(activationID),
+					"namespace": boldString(qualifiedName.GetNamespace()),
+					"name":      boldString(qualifiedName.GetEntityName()),
+					"id":        boldString(getValueFromJSONResponse(ACTIVATION_ID, response)),
 				}))
 	}
 
-	if Flags.common.blocking {
+	if blocking {
 		printJSON(response, outputStream)
 	}
 }
diff --git a/commands/trigger.go b/commands/trigger.go
index fb501617..9aa0825b 100644
--- a/commands/trigger.go
+++ b/commands/trigger.go
@@ -193,7 +193,7 @@ var triggerCreateCmd = &cobra.Command{
 
 		// Invoke the specified feed action to configure the trigger feed
 		if feedArgPassed {
-			err := configureFeed(trigger.Name, fullFeedName)
+			err := configureFeed(trigger.Name, fullFeedName, getParameters(Flags.common.param, false, false))
 			if err != nil {
 				whisk.Debug(whisk.DbgError, "configureFeed(%s, %s) failed: %s\n", trigger.Name, Flags.common.feed,
 					err)
@@ -286,7 +286,7 @@ var triggerUpdateCmd = &cobra.Command{
 			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)
+			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)
@@ -372,7 +372,7 @@ var triggerGetCmd = &cobra.Command{
 			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))
 
-			err = configureFeed(qualifiedName.GetEntityName(), fullFeedName)
+			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(), fullFeedName, err)
 			}
@@ -441,7 +441,7 @@ var triggerDeleteCmd = &cobra.Command{
 				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))
 
-				err = configureFeed(qualifiedName.GetEntityName(), fullFeedName)
+				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(), fullFeedName, err)
 				}
@@ -515,17 +515,24 @@ var triggerListCmd = &cobra.Command{
 	},
 }
 
-func configureFeed(triggerName string, FullFeedName string) error {
-	feedArgs := []string{FullFeedName}
-	Flags.common.blocking = true
-	err := actionInvokeCmd.RunE(nil, feedArgs)
+func configureFeed(triggerName string, feedName string, parameters interface{}) error {
+	var fullFeedName *QualifiedName
+	var err error
+
+	if fullFeedName, err = NewQualifiedName(feedName); err != nil {
+		return NewQualifiedNameError(feedName, err)
+	}
+
+	res, err := invokeAction(*fullFeedName, parameters, true, false)
+	err = printInvocationResponse(*fullFeedName, true, false, res, err)
+
 	if err != nil {
-		whisk.Debug(whisk.DbgError, "Invoke of action '%s' failed: %s\n", FullFeedName, err)
+		whisk.Debug(whisk.DbgError, "Invoke of action '%s' failed: %s\n", feedName, err)
 		errStr := wski18n.T("Unable to invoke trigger '{{.trigname}}' feed action '{{.feedname}}'; feed is not configured: {{.err}}",
-			map[string]interface{}{"trigname": triggerName, "feedname": FullFeedName, "err": err})
+			map[string]interface{}{"trigname": triggerName, "feedname": feedName, "err": err})
 		err = whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
 	} else {
-		whisk.Debug(whisk.DbgInfo, "Successfully configured trigger feed via feed action '%s'\n", FullFeedName)
+		whisk.Debug(whisk.DbgInfo, "Successfully configured trigger feed via feed action '%s'\n", feedName)
 	}
 
 	return err
diff --git a/commands/util.go b/commands/util.go
index a33ad23d..775989b8 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -27,6 +27,8 @@ import (
 	"github.com/apache/incubator-openwhisk-client-go/whisk"
 
 	"github.com/fatih/color"
+	"github.com/mattn/go-colorable"
+
 	//prettyjson "github.com/hokaccha/go-prettyjson"  // See prettyjson comment below
 	"archive/tar"
 	"archive/zip"
@@ -51,6 +53,45 @@ func csvToQualifiedActions(artifacts string) []string {
 	return res
 }
 
+/**
+ * Processes command line to retrieve pairs of key-value pairs, where the value must be valid JSON.
+ *
+ * Parameters and annotations are handled the same way. The flag here is only for generating an error messages
+ * specific to one or the other.
+ *
+ * NOTE: this function will exit in case of a processing error since it indicates a problem parsing parameters.
+ *
+ * @return either an array or a JSON object (map) formatted representation of the key-value pairs.
+ */
+func getParameters(params []string, keyValueFormat bool, annotation bool) interface{} {
+	var parameters interface{}
+	var err error
+
+	if !annotation {
+		whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", params)
+	} else {
+		whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", params)
+	}
+
+	parameters, err = getJSONFromStrings(params, keyValueFormat)
+	if err != nil {
+		whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, %s) failed: %s\n", params, keyValueFormat, err)
+		var errStr string
+
+		if !annotation {
+			errStr = wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
+				map[string]interface{}{"param": fmt.Sprintf("%#v", params), "err": err})
+		} else {
+			errStr = wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
+				map[string]interface{}{"annotation": fmt.Sprintf("%#v", params), "err": err})
+		}
+		werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+		ExitOnError(werr)
+	}
+
+	return parameters
+}
+
 func getJSONFromStrings(content []string, keyValueFormat bool) (interface{}, error) {
 	var data map[string]interface{}
 	var res interface{}
@@ -68,6 +109,10 @@ func getJSONFromStrings(content []string, keyValueFormat bool) (interface{}, err
 		whisk.Debug(whisk.DbgInfo, "Created map '%v' from '%v'\n", data, content[i])
 	}
 
+	if data == nil {
+		data = make(map[string]interface{})
+	}
+
 	if keyValueFormat {
 		res = getKeyValueFormattedJSON(data)
 	} else {
@@ -1133,3 +1178,54 @@ func contains(arr []string, element string) bool {
 	}
 	return false
 }
+
+func ExitOnError(err error) {
+	if err == nil {
+		return
+	}
+
+	whisk.Debug(whisk.DbgInfo, "err object type: %s\n", reflect.TypeOf(err).String())
+
+	T := wski18n.T
+	var exitCode int = 0
+	var displayUsage bool = false
+	var displayMsg bool = false
+	var msgDisplayed bool = true
+	var displayPrefix bool = true
+
+	werr, isWskError := err.(*whisk.WskError) // Is the err a WskError?
+	if isWskError {
+		whisk.Debug(whisk.DbgError, "Got a *whisk.WskError error: %#v\n", werr)
+		displayUsage = werr.DisplayUsage
+		displayMsg = werr.DisplayMsg
+		msgDisplayed = werr.MsgDisplayed
+		displayPrefix = werr.DisplayPrefix
+		exitCode = werr.ExitCode
+	} else {
+		whisk.Debug(whisk.DbgError, "Got some other error: %s\n", err)
+		fmt.Fprintf(os.Stderr, "%s\n", err)
+
+		displayUsage = false // Cobra already displayed the usage message
+		exitCode = 1
+	}
+
+	outputStream := colorable.NewColorableStderr()
+
+	// If the err msg should be displayed to the console and it has not already been
+	// displayed, display it now.
+	if displayMsg && !msgDisplayed && displayPrefix && exitCode != 0 {
+		fmt.Fprintf(outputStream, "%s%s\n", color.RedString(T("error: ")), err)
+	} else if displayMsg && !msgDisplayed && !displayPrefix && exitCode != 0 {
+		fmt.Fprintf(outputStream, "%s\n", err)
+	} else if displayMsg && !msgDisplayed && exitCode == 0 {
+		fmt.Fprintf(outputStream, "%s\n", err)
+	}
+
+	// Displays usage
+	if displayUsage {
+		fmt.Fprintf(outputStream, T("Run '{{.Name}} --help' for usage.\n",
+			map[string]interface{}{"Name": WskCmd.CommandPath()}))
+	}
+
+	os.Exit(exitCode)
+}
diff --git a/main.go b/main.go
index 526c505f..343f6c64 100644
--- a/main.go
+++ b/main.go
@@ -19,15 +19,12 @@ package main
 
 import (
 	"fmt"
-	"github.com/fatih/color"
 	goi18n "github.com/nicksnyder/go-i18n/i18n"
 	"os"
-	"reflect"
 
 	"github.com/apache/incubator-openwhisk-cli/commands"
 	"github.com/apache/incubator-openwhisk-cli/wski18n"
 	"github.com/apache/incubator-openwhisk-client-go/whisk"
-	"github.com/mattn/go-colorable"
 )
 
 // CLI_BUILD_TIME holds the time of the CLI build.  During gradle builds,
@@ -51,12 +48,6 @@ func init() {
 }
 
 func main() {
-	var exitCode int = 0
-	var displayUsage bool = false
-	var displayMsg bool = false
-	var msgDisplayed bool = true
-	var displayPrefix bool = true
-
 	defer func() {
 		if r := recover(); r != nil {
 			fmt.Println(r)
@@ -65,42 +56,7 @@ func main() {
 	}()
 
 	if err := commands.Execute(); err != nil {
-		whisk.Debug(whisk.DbgInfo, "err object type: %s\n", reflect.TypeOf(err).String())
-
-		werr, isWskError := err.(*whisk.WskError) // Is the err a WskError?
-		if isWskError {
-			whisk.Debug(whisk.DbgError, "Got a *whisk.WskError error: %#v\n", werr)
-			displayUsage = werr.DisplayUsage
-			displayMsg = werr.DisplayMsg
-			msgDisplayed = werr.MsgDisplayed
-			displayPrefix = werr.DisplayPrefix
-			exitCode = werr.ExitCode
-		} else {
-			whisk.Debug(whisk.DbgError, "Got some other error: %s\n", err)
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-
-			displayUsage = false // Cobra already displayed the usage message
-			exitCode = 1
-		}
-
-		outputStream := colorable.NewColorableStderr()
-
-		// If the err msg should be displayed to the console and it has not already been
-		// displayed, display it now.
-		if displayMsg && !msgDisplayed && displayPrefix && exitCode != 0 {
-			fmt.Fprintf(outputStream, "%s%s\n", color.RedString(T("error: ")), err)
-		} else if displayMsg && !msgDisplayed && !displayPrefix && exitCode != 0 {
-			fmt.Fprintf(outputStream, "%s\n", err)
-		} else if displayMsg && !msgDisplayed && exitCode == 0 {
-			fmt.Fprintf(outputStream, "%s\n", err)
-		}
-
-		// Displays usage
-		if displayUsage {
-			fmt.Fprintf(outputStream, T("Run '{{.Name}} --help' for usage.\n",
-				map[string]interface{}{"Name": commands.WskCmd.CommandPath()}))
-		}
+		commands.ExitOnError(err)
 	}
-	os.Exit(exitCode)
 	return
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services