func genFilteredRow(resultApi *whisk.RetApi, apiPath string, apiVerb string, maxActionNameSize int, maxApiNameSize int) []whisk.ApiFilteredRow {
	var orderInfo whisk.ApiFilteredRow
	var orderInfoArr []whisk.ApiFilteredRow
	baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
	apiName := resultApi.Swagger.Info.Title
	basePath := resultApi.Swagger.BasePath
	if resultApi.Swagger != nil && resultApi.Swagger.Paths != nil {
		for path := range resultApi.Swagger.Paths {
			whisk.Debug(whisk.DbgInfo, "genFilteredRow: comparing api relpath: '%s'\n", path)
			if len(apiPath) == 0 || path == apiPath {
				whisk.Debug(whisk.DbgInfo, "genFilteredRow: relpath matches\n")
				for op, opv := range resultApi.Swagger.Paths[path].MakeOperationMap() {
					whisk.Debug(whisk.DbgInfo, "genFilteredRow: comparing operation: '%s'\n", op)
					if len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb) {
						whisk.Debug(whisk.DbgInfo, "genFilteredRow: operation matches: %#v\n", opv)
						var actionName string
						if opv.XOpenWhisk == nil {
							actionName = ""
						} else if len(opv.XOpenWhisk.Package) > 0 {
							actionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.Package + "/" + opv.XOpenWhisk.ActionName
						} else {
							actionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.ActionName
						}
						orderInfo = AssignRowInfo(actionName[0:min(len(actionName), maxActionNameSize)], op, apiName[0:min(len(apiName), maxApiNameSize)], basePath, path, baseUrl+path)
						orderInfo.FmtString = fmtString
						whisk.Debug(whisk.DbgInfo, "Appening to orderInfoArr: %s\n", orderInfo.RelPath)
						orderInfoArr = append(orderInfoArr, orderInfo)
					}
				}
			}
		}
	}
	return orderInfoArr
}
genFilteredRow(resultApi, api, maxApiNameSize, maxApiNameSize) generates an array of
ApiFilteredRows for the purpose of ordering and printing in a list form by parsing and
initializing vaules for each individual ApiFilteredRow struct.
NOTE: Large action and api name values will be truncated by their associated max size parameters.
package commands
import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"github.com/apache/openwhisk-cli/wski18n"
	"github.com/apache/openwhisk-client-go/whisk"
	"encoding/json"
	"github.com/fatih/color"
	"github.com/ghodss/yaml"
	"github.com/spf13/cobra"
	"regexp"
)
const (
	yamlFileExtension = "yaml"
	ymlFileExtension  = "yml"
	formatOptionYaml = "yaml"
	formatOptionJson = "json"
	pathParamRegex        = `\/\{([^\/]+)\}\/|\/\{([^\/]+)\}$|\{([^\/]+)}\/`
	pathSegmentParamRegex = `^\/\{([^\/]+)\}\/$`
)
var apiCmd = &cobra.Command{
	Use:   "api",
	Short: wski18n.T("work with APIs"),
}
var fmtString = "%-30s %7s %20s  %s\n"
var ContextId string
var ApiGwAccessToken string
func IsValidApiVerb(verb string) (error, bool) {
	if _, ok := whisk.ApiVerbs[strings.ToUpper(verb)]; !ok {
		whisk.Debug(whisk.DbgError, "Invalid API verb: '%s'\n", verb)
		errMsg := wski18n.T("'{{.verb}}' is not a valid API verb.  Valid values are: {{.verbs}}",
			map[string]interface{}{
				"verb":  verb,
				"verbs": reflect.ValueOf(whisk.ApiVerbs).MapKeys()})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr, false
	}
	return nil, true
}
func hasPathPrefix(path string) (error, bool) {
	if !strings.HasPrefix(path, "/") {
		whisk.Debug(whisk.DbgError, "path does not begin with '/': '%s'\n", path)
		errMsg := wski18n.T("'{{.path}}' must begin with '/'.",
			map[string]interface{}{
				"path": path,
			})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr, false
	}
	return nil, true
}
func isValidBasepath(basepath string) (error, bool) {
	if whiskerr, ok := hasPathPrefix(basepath); !ok {
		return whiskerr, false
	}
	return nil, true
}
func isValidRelpath(relpath string) (error, bool) {
	if whiskerr, ok := hasPathPrefix(relpath); !ok {
		return whiskerr, false
	}
	return nil, true
}
func getPathParameterNames(path string) ([]string, error) {
	var pathParameters []string
	regexObj, err := regexp.Compile(pathSegmentParamRegex)
	if err != nil {
		whisk.Debug(whisk.DbgError, "Failed to match path '%s' to regular expressions `%s`\n", path, pathSegmentParamRegex)
	} else {
		segments := strings.Split(path, "/")
		for _, segment := range segments {
			segment = fmt.Sprintf("/%s/", segment)
			matchedItems := regexObj.FindAllStringSubmatch(segment, -1)
			for _, matchedParam := range matchedItems {
				for idx, paramName := range matchedParam {
					whisk.Debug(whisk.DbgInfo, "Path parameter submatch '%v'; idx %v\n", paramName, idx)
					if idx > 0 && len(paramName) > 0 {
						pathParameters = append(pathParameters, paramName)
					}
				}
			}
		}
	}
	return pathParameters, err
}
func hasPathParameters(path string) (bool, error) {
	pathParams, err := getPathParameterNames(path)
	return len(pathParams) > 0, err
}
func isBasepathParameterized(basepath string) (error, bool) {
	hasParams, err := hasPathParameters(basepath)
	if hasParams || err != nil {
		errMsg := wski18n.T("The base path '{{.path}}' cannot have parameters. Only the relative path supports path parameters.",
			map[string]interface{}{"path": basepath})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr, false
	}
	return nil, true
}
func getManagedUrl(api *whisk.RetApi, relpath string, operation string) (url string) {
	baseUrl := strings.TrimSuffix(api.BaseUrl, "/")
	whisk.Debug(whisk.DbgInfo, "getManagedUrl: baseUrl = '%s', relpath = '%s', operation = '%s'\n", baseUrl, relpath, operation)
	for path := range api.Swagger.Paths {
		whisk.Debug(whisk.DbgInfo, "getManagedUrl: comparing api relpath: '%s'\n", path)
		if path == relpath {
			whisk.Debug(whisk.DbgInfo, "getManagedUrl: relpath matches '%s'\n", relpath)
			for op := range api.Swagger.Paths[path].MakeOperationMap() {
				whisk.Debug(whisk.DbgInfo, "getManagedUrl: comparing operation: '%s'\n", op)
				if strings.ToLower(op) == strings.ToLower(operation) {
					whisk.Debug(whisk.DbgInfo, "getManagedUrl: operation matches: '%s'\n", operation)
					url = baseUrl + path
				}
			}
		}
	}
	return url
}
var apiCreateCmd = &cobra.Command{
	Use:           "create ([BASE_PATH] API_PATH API_VERB ACTION] | --config-file CFG_FILE) ",
	Short:         wski18n.T("create a new API"),
	SilenceUsage:  true,
	SilenceErrors: true,
	PreRunE:       SetupClientConfig,
	RunE: func(cmd *cobra.Command, args []string) error {
		var api *whisk.Api
		var err error
		var qname = new(QualifiedName)
		var action *whisk.Action
		var webactionSecret interface{}
		if len(args) == 0 && Flags.api.configfile == "" {
			whisk.Debug(whisk.DbgError, "No swagger file and no arguments\n")
			errMsg := wski18n.T("Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
			return whiskErr
		} else if len(args) == 0 && Flags.api.configfile != "" {
			api, err = parseSwaggerApi(Flags.api.configfile, Client.Config.Namespace)
			if err != nil {
				whisk.Debug(whisk.DbgError, "parseSwaggerApi() error: %s\n", err)
				errMsg := wski18n.T("Unable to parse swagger file: {{.err}}", map[string]interface{}{"err": err})
				whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
					whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
				return whiskErr
			}
		} else {
			if whiskErr := CheckArgs(args, 3, 4, "Api create",
				wski18n.T("Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")); whiskErr != nil {
				return whiskErr
			}
			api, qname, err = parseApi(cmd, args)
			if err != nil {
				whisk.Debug(whisk.DbgError, "parseApi(%s, %s) error: %s\n", cmd.Name(), args, err)
				errMsg := wski18n.T("Unable to parse api command arguments: {{.err}}",
					map[string]interface{}{"err": err})
				whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
					whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
				return whiskErr
			}
			action, err = isWebAction(Client, *qname)
			if err != nil {
				whisk.Debug(whisk.DbgError, "isWebAction(%v) is false: %s\n", qname, err)
				whiskErr := whisk.MakeWskError(err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
				return whiskErr
			}
			if webactionSecret = action.Annotations.GetValue(WEB_SECURE_ANNOT); webactionSecret != nil {
				whisk.Debug(whisk.DbgInfo, "web action is secured\n")
			}
		}
		apiCreateReq := new(whisk.ApiCreateRequest)
		apiCreateReq.ApiDoc = api
		apiCreateReqOptions := new(whisk.ApiCreateRequestOptions)
		if apiCreateReqOptions.SpaceGuid, err = getUserContextId(); err != nil {
			return err
		}
		if apiCreateReqOptions.AccessToken, err = getAccessToken(); err != nil {
			return err
		}
		apiCreateReqOptions.ResponseType = Flags.api.resptype
		if webactionSecret != nil {
			apiCreateReq.ApiDoc.Action.SecureKey = webactionSecret
		}
		whisk.Debug(whisk.DbgInfo, "AccessToken: %s\nSpaceGuid: %s\nResponseType: %s",
			apiCreateReqOptions.AccessToken, apiCreateReqOptions.SpaceGuid, apiCreateReqOptions.ResponseType)
		retApi, _, err := Client.Apis.Insert(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
		if err != nil {
			whisk.Debug(whisk.DbgError, "Client.Apis.Insert(%#v, false) error: %s\n", api, err)
			errMsg := wski18n.T("Unable to create API: {{.err}}", map[string]interface{}{"err": err})
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return whiskErr
		}
		if api.Swagger == "" {
			baseUrl := retApi.BaseUrl
			fmt.Fprintf(color.Output,
				wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
					map[string]interface{}{
						"ok":       color.GreenString("ok:"),
						"path":     strings.TrimSuffix(api.GatewayBasePath, "/") + api.GatewayRelPath,
						"verb":     api.GatewayMethod,
						"name":     boldString("/" + api.Action.Namespace + "/" + api.Action.Name),
						"fullpath": strings.TrimSuffix(baseUrl, "/") + api.GatewayRelPath,
					}))
		} else {
			whisk.Debug(whisk.DbgInfo, "Processing swagger based create API response\n")
			baseUrl := retApi.BaseUrl
			for path := range retApi.Swagger.Paths {
				managedUrl := strings.TrimSuffix(baseUrl, "/") + path
				whisk.Debug(whisk.DbgInfo, "Managed path: '%s'\n", managedUrl)
				for op, opv := range retApi.Swagger.Paths[path].MakeOperationMap() {
					whisk.Debug(whisk.DbgInfo, "Path operation: '%s'\n", op)
					var fqActionName string
					if opv.XOpenWhisk == nil {
						fqActionName = ""
					} else if len(opv.XOpenWhisk.Package) > 0 {
						fqActionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.Package + "/" + opv.XOpenWhisk.ActionName
					} else {
						fqActionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.ActionName
					}
					whisk.Debug(whisk.DbgInfo, "baseUrl '%s'  Path '%s'  Path obj %+v\n", baseUrl, path, opv)
					if len(fqActionName) > 0 {
						fmt.Fprintf(color.Output,
							wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
								map[string]interface{}{
									"ok":       color.GreenString("ok:"),
									"path":     strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
									"verb":     op,
									"name":     boldString(fqActionName),
									"fullpath": managedUrl,
								}))
					} else {
						fmt.Fprintf(color.Output,
							wski18n.T("{{.ok}} created API {{.path}} {{.verb}}\n{{.fullpath}}\n",
								map[string]interface{}{
									"ok":       color.GreenString("ok:"),
									"path":     strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
									"verb":     op,
									"fullpath": managedUrl,
								}))
					}
				}
			}
		}
		return nil
	},
}
var apiGetCmd = &cobra.Command{
	Use:           "get BASE_PATH | API_NAME",
	Short:         wski18n.T("get API details"),
	SilenceUsage:  true,
	SilenceErrors: true,
	PreRunE:       SetupClientConfig,
	RunE: func(cmd *cobra.Command, args []string) error {
		var err error
		var isBasePathArg bool = true
		if whiskErr := CheckArgs(args, 1, 1, "Api get",
			wski18n.T("An API base path or API name is required.")); whiskErr != nil {
			return whiskErr
		}
		if cmd.LocalFlags().Changed("format") &&
			strings.ToLower(Flags.common.format) != formatOptionYaml &&
			strings.ToLower(Flags.common.format) != formatOptionJson {
			errMsg := wski18n.T("Invalid format type: {{.type}}", map[string]interface{}{"type": Flags.common.format})
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return whiskErr
		}
		apiGetReq := new(whisk.ApiGetRequest)
		apiGetReqOptions := new(whisk.ApiGetRequestOptions)
		apiGetReqOptions.ApiBasePath = args[0]
		if apiGetReqOptions.SpaceGuid, err = getUserContextId(); err != nil {
			return err
		}
		if apiGetReqOptions.AccessToken, err = getAccessToken(); err != nil {
			return err
		}
		retApi, _, err := Client.Apis.Get(apiGetReq, apiGetReqOptions)
		if err != nil {
			whisk.Debug(whisk.DbgError, "Client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
			errMsg := wski18n.T("Unable to get API '{{.name}}': {{.err}}", map[string]interface{}{"name": args[0], "err": err})
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return whiskErr
		}
		whisk.Debug(whisk.DbgInfo, "Client.Apis.Get returned: %#v\n", retApi)
		var displayResult interface{} = nil
		if Flags.common.detail {
			if retApi.Apis != nil && len(retApi.Apis) > 0 &&
				retApi.Apis[0].ApiValue != nil {
				displayResult = retApi.Apis[0].ApiValue
			} else {
				whisk.Debug(whisk.DbgError, "No result object returned\n")
			}
		} else {
			if retApi.Apis != nil && len(retApi.Apis) > 0 &&
				retApi.Apis[0].ApiValue != nil &&
				retApi.Apis[0].ApiValue.Swagger != nil {
				displayResult = retApi.Apis[0].ApiValue.Swagger
			} else {
				whisk.Debug(whisk.DbgError, "No swagger returned\n")
			}
		}
		if displayResult == nil {
			var errMsg string
			if isBasePathArg {
				errMsg = wski18n.T("API does not exist for basepath {{.basepath}}",
					map[string]interface{}{"basepath": args[0]})
			} else {
				errMsg = wski18n.T("API does not exist for API name {{.apiname}}",
					map[string]interface{}{"apiname": args[0]})
			}
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return whiskErr
		}
		if cmd.LocalFlags().Changed("format") && strings.ToLower(Flags.common.format) == formatOptionYaml {
			var jsonOutputBuffer bytes.Buffer
			var jsonOutputWriter = bufio.NewWriter(&jsonOutputBuffer)
			printJSON(displayResult, jsonOutputWriter)
			jsonOutputWriter.Flush()
			yamlbytes, err := yaml.JSONToYAML(jsonOutputBuffer.Bytes())
			if err != nil {
				whisk.Debug(whisk.DbgError, "yaml.JSONToYAML() error: %s\n", err)
				errMsg := wski18n.T("Unable to convert API into YAML: {{.err}}", map[string]interface{}{"err": err})
				whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
					whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return whiskErr
			}
			fmt.Println(string(yamlbytes))
		} else {
			printJSON(displayResult)
		}
		return nil
	},
}
var apiDeleteCmd = &cobra.Command{
	Use:           "delete BASE_PATH | API_NAME [API_PATH [API_VERB]]",
	Short:         wski18n.T("delete an API"),
	SilenceUsage:  true,
	SilenceErrors: true,
	PreRunE:       SetupClientConfig,
	RunE: func(cmd *cobra.Command, args []string) error {
		var err error
		if whiskErr := CheckArgs(args, 1, 3, "Api delete",
			wski18n.T("An API base path or API name is required.  An optional API relative path and operation may also be provided.")); whiskErr != nil {
			return whiskErr
		}
		apiDeleteReq := new(whisk.ApiDeleteRequest)
		apiDeleteReqOptions := new(whisk.ApiDeleteRequestOptions)
		if apiDeleteReqOptions.SpaceGuid, err = getUserContextId(); err != nil {
			return err
		}
		if apiDeleteReqOptions.AccessToken, err = getAccessToken(); err != nil {
			return err
		}
		if _, ok := isValidBasepath(args[0]); !ok {
			whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
			apiDeleteReqOptions.ApiBasePath = args[0]
		} else {
			apiDeleteReqOptions.ApiBasePath = args[0]
		}
		if len(args) > 1 {
			if whiskErr, ok := isValidRelpath(args[1]); !ok {
				return whiskErr
			}
			apiDeleteReqOptions.ApiRelPath = args[1]
		}
		if len(args) > 2 {
			if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
				return whiskErr
			}
			apiDeleteReqOptions.ApiVerb = strings.ToUpper(args[2])
		}
		_, err = Client.Apis.Delete(apiDeleteReq, apiDeleteReqOptions)
		if err != nil {
			whisk.Debug(whisk.DbgError, "Client.Apis.Delete(%#v, %#v) error: %s\n", apiDeleteReq, apiDeleteReqOptions, err)
			errMsg := wski18n.T("Unable to delete API: {{.err}}", map[string]interface{}{"err": err})
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
				whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return whiskErr
		}
		if len(args) == 1 {
			fmt.Fprintf(color.Output,
				wski18n.T("{{.ok}} deleted API {{.basepath}}\n",
					map[string]interface{}{
						"ok":       color.GreenString("ok:"),
						"basepath": apiDeleteReqOptions.ApiBasePath,
					}))
		} else if len(args) == 2 {
			fmt.Fprintf(color.Output,
				wski18n.T("{{.ok}} deleted {{.path}} from {{.basepath}}\n",
					map[string]interface{}{
						"ok":       color.GreenString("ok:"),
						"path":     apiDeleteReqOptions.ApiRelPath,
						"basepath": apiDeleteReqOptions.ApiBasePath,
					}))
		} else {
			fmt.Fprintf(color.Output,
				wski18n.T("{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
					map[string]interface{}{
						"ok":       color.GreenString("ok:"),
						"path":     apiDeleteReqOptions.ApiRelPath,
						"verb":     apiDeleteReqOptions.ApiVerb,
						"basepath": apiDeleteReqOptions.ApiBasePath,
					}))
		}
		return nil
	},
}
var apiListCmd = &cobra.Command{
	Use:           "list [[BASE_PATH | API_NAME] [API_PATH [API_VERB]]",
	Short:         wski18n.T("list APIs"),
	SilenceUsage:  true,
	SilenceErrors: true,
	PreRunE:       SetupClientConfig,
	RunE: func(cmd *cobra.Command, args []string) error {
		var err error
		var retApiList *whisk.ApiListResponse
		var retApi *whisk.ApiGetResponse
		var retApiArray *whisk.RetApiArray
		var apiPath string
		var apiVerb string
		var orderFilteredList []whisk.ApiFilteredList
		var orderFilteredRow []whisk.ApiFilteredRow
		if whiskErr := CheckArgs(args, 0, 3, "Api list",
			wski18n.T("Optional parameters are: API base path (or API name), API relative path and operation.")); whiskErr != nil {
			return whiskErr
		}
		if len(args) == 0 {
			apiListReqOptions := new(whisk.ApiListRequestOptions)
			apiListReqOptions.Limit = Flags.common.limit
			apiListReqOptions.Skip = Flags.common.skip
			if apiListReqOptions.SpaceGuid, err = getUserContextId(); err != nil {
				return err
			}
			if apiListReqOptions.AccessToken, err = getAccessToken(); err != nil {
				return err
			}
			retApiList, _, err = Client.Apis.List(apiListReqOptions)
			if err != nil {
				whisk.Debug(whisk.DbgError, "Client.Apis.List(%#v) error: %s\n", apiListReqOptions, err)
				errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
				whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
					whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return whiskErr
			}
			whisk.Debug(whisk.DbgInfo, "Client.Apis.List returned: %#v (%+v)\n", retApiList, retApiList)
			retApiArray = (*whisk.RetApiArray)(retApiList)
		} else {
			apiGetReq := new(whisk.ApiGetRequest)
			apiGetReq.Namespace = Client.Config.Namespace
			apiGetReqOptions := new(whisk.ApiGetRequestOptions)
			if apiGetReqOptions.SpaceGuid, err = getUserContextId(); err != nil {
				return err
			}
			if apiGetReqOptions.AccessToken, err = getAccessToken(); err != nil {
				return err
			}
			apiGetReqOptions.ApiBasePath = args[0]
			if len(args) > 1 {
				if whiskErr, ok := isValidRelpath(args[1]); !ok {
					return whiskErr
				}
				apiPath = args[1]
				apiGetReqOptions.ApiRelPath = apiPath
			}
			if len(args) > 2 {
				if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
					return whiskErr
				}
				apiVerb = strings.ToUpper(args[2])
				apiGetReqOptions.ApiVerb = apiVerb
			}
			retApi, _, err = Client.Apis.Get(apiGetReq, apiGetReqOptions)
			if err != nil {
				whisk.Debug(whisk.DbgError, "Client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
				errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
				whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
					whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return whiskErr
			}
			whisk.Debug(whisk.DbgInfo, "Client.Apis.Get returned: %#v\n", retApi)
			retApiArray = (*whisk.RetApiArray)(retApi)
		}
		sortByName := Flags.common.nameSort
		if Flags.common.full {
			fmt.Fprintf(color.Output,
				wski18n.T("{{.ok}} APIs\n",
					map[string]interface{}{
						"ok": color.GreenString("ok:"),
					}))
			for i := 0; i < len(retApiArray.Apis); i++ {
				orderFilteredList = append(orderFilteredList, genFilteredList(retApiArray.Apis[i].ApiValue, apiPath, apiVerb)...)
			}
			printList(orderFilteredList, sortByName)  
		} else {
			if len(retApiArray.Apis) > 0 {
				maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSize(retApiArray, apiPath, apiVerb)))
				maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSize(retApiArray, apiPath, apiVerb)))
				fmtString = "%-" + strconv.Itoa(maxActionNameSize) + "s %7s %" + strconv.Itoa(maxApiNameSize+1) + "s  %s\n"
				fmt.Fprintf(color.Output,
					wski18n.T("{{.ok}} APIs\n",
						map[string]interface{}{
							"ok": color.GreenString("ok:"),
						}))
				for i := 0; i < len(retApiArray.Apis); i++ {
					orderFilteredRow = append(orderFilteredRow, genFilteredRow(retApiArray.Apis[i].ApiValue, apiPath, apiVerb, maxActionNameSize, maxApiNameSize)...)
				}
				printList(orderFilteredRow, sortByName)  
			} else {
				fmt.Fprintf(color.Output,
					wski18n.T("{{.ok}} APIs\n",
						map[string]interface{}{
							"ok": color.GreenString("ok:"),
						}))
				printList(orderFilteredRow, sortByName)  
			}
		}
		return nil
	},
}
func genFilteredList(resultApi *whisk.RetApi, apiPath string, apiVerb string) []whisk.ApiFilteredList {
	var orderInfo whisk.ApiFilteredList
	var orderInfoArr []whisk.ApiFilteredList
	baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
	apiName := resultApi.Swagger.Info.Title
	basePath := resultApi.Swagger.BasePath
	if resultApi.Swagger != nil && resultApi.Swagger.Paths != nil {
		for path := range resultApi.Swagger.Paths {
			whisk.Debug(whisk.DbgInfo, "genFilteredApi: comparing api relpath: '%s'\n", path)
			if len(apiPath) == 0 || path == apiPath {
				whisk.Debug(whisk.DbgInfo, "genFilteredList: relpath matches\n")
				for op, opv := range resultApi.Swagger.Paths[path].MakeOperationMap() {
					whisk.Debug(whisk.DbgInfo, "genFilteredList: comparing operation: '%s'\n", op)
					if len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb) {
						whisk.Debug(whisk.DbgInfo, "genFilteredList: operation matches: %#v\n", opv)
						var actionName string
						if opv.XOpenWhisk == nil {
							actionName = ""
						} else if len(opv.XOpenWhisk.Package) > 0 {
							actionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.Package + "/" + opv.XOpenWhisk.ActionName
						} else {
							actionName = "/" + opv.XOpenWhisk.Namespace + "/" + opv.XOpenWhisk.ActionName
						}
						orderInfo = AssignListInfo(actionName, op, apiName, basePath, path, baseUrl+path)
						whisk.Debug(whisk.DbgInfo, "Appening to orderInfoArr: %s\n", orderInfo.RelPath)
						orderInfoArr = append(orderInfoArr, orderInfo)
					}
				}
			}
		}
	}
	return orderInfoArr
}