You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/08/17 17:17:44 UTC
[incubator-openwhisk-cli] 03/10: Allow CLI to sort entities by name
(#2326)
This is an automated email from the ASF dual-hosted git repository.
csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git
commit 6aae54c1beb3b77cbfadb6783d5e67b11ce07b91
Author: Brandon Lee Underwood <Br...@ibm.com>
AuthorDate: Thu Aug 10 21:47:07 2017 -0400
Allow CLI to sort entities by name (#2326)
- Created interfaces `Printables` and `Sortables`
- Made Actions, Triggers, Packages, Rules, APIs into Printables and Sortables
- Made Activations into Printables and Sortables, Sort currently undefined
- Made alphabetic sorting default, sort by last update time with --time flag
- Changed sorting default back to last update time, --sort flag for alphabetical sorting
- Updated flag name to "--name-sort"/"-n"
- Updated Docs
- Fixed rule status printing for `wsk list` and `wsk namespace get`
---
commands/action.go | 4 +-
commands/activation.go | 2 +-
commands/api.go | 120 ++++++++++++++++++-----------
commands/flags.go | 1 +
commands/namespace.go | 25 ++++--
commands/package.go | 5 +-
commands/rule.go | 5 +-
commands/trigger.go | 4 +-
commands/util.go | 162 ++++++++++++++++++++++-----------------
commands/wsk.go | 2 +
wski18n/i18n_resources.go | 22 +++---
wski18n/resources/en_US.all.json | 19 +++--
12 files changed, 230 insertions(+), 141 deletions(-)
diff --git a/commands/action.go b/commands/action.go
index 83e89fa..f14cc9a 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -321,7 +321,8 @@ var actionListCmd = &cobra.Command{
return actionListError(qualifiedName.GetEntityName(), options, err)
}
- printList(actions)
+ sortByName := flags.common.nameSort
+ printList(actions, sortByName)
return nil
},
@@ -942,6 +943,7 @@ func init() {
actionListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
actionListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
+ actionListCmd.Flags().BoolVarP(&Flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
actionCmd.AddCommand(
actionCreateCmd,
diff --git a/commands/activation.go b/commands/activation.go
index 8273351..29f8f48 100644
--- a/commands/activation.go
+++ b/commands/activation.go
@@ -93,7 +93,7 @@ var activationListCmd = &cobra.Command{
if options.Docs == true {
printFullActivationList(activations)
} else {
- printList(activations)
+ printList(activations, false) // Default sorting for Activations are by creation time, hence sortByName is always false
}
return nil
diff --git a/commands/api.go b/commands/api.go
index cec47eb..0f7f01c 100644
--- a/commands/api.go
+++ b/commands/api.go
@@ -93,7 +93,6 @@ func isValidRelpath(relpath string) (error, bool) {
return nil, true
}
-
/*
* Pull the managedUrl (external API URL) from the API configuration
*/
@@ -445,6 +444,8 @@ var apiListCmd = &cobra.Command{
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 {
@@ -518,7 +519,8 @@ var apiListCmd = &cobra.Command{
// Cast to a common type to allow for code to print out apilist response or apiget response
retApiArray = (*whisk.RetApiArray)(retApi)
}
-
+ //Checks for any order flags being passed
+ sortByName := flags.common.nameSort
// Display the APIs - applying any specified filtering
if (Flags.common.full) {
fmt.Fprintf(color.Output,
@@ -526,10 +528,10 @@ var apiListCmd = &cobra.Command{
map[string]interface{}{
"ok": color.GreenString("ok:"),
}))
-
- for i:=0; i<len(retApiArray.Apis); i++ {
- printFilteredListApi(retApiArray.Apis[i].ApiValue, apiPath, apiVerb)
+ for i := 0; i < len(retApiArray.Apis); i++ {
+ orderFilteredList = append(orderFilteredList, genFilteredList(retApiArray.Apis[i].ApiValue, apiPath, apiVerb)...)
}
+ printList(orderFilteredList, sortByName) // Sends an array of structs that contains specifed variables that are not truncated
} else {
if (len(retApiArray.Apis) > 0) {
// Dynamically create the output format string based on the maximum size of the
@@ -542,17 +544,17 @@ var apiListCmd = &cobra.Command{
map[string]interface{}{
"ok": color.GreenString("ok:"),
}))
- fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
- for i:=0; i<len(retApiArray.Apis); i++ {
- printFilteredListRow(retApiArray.Apis[i].ApiValue, apiPath, apiVerb, maxActionNameSize, maxApiNameSize)
+ for i := 0; i < len(retApiArray.Apis); i++ {
+ orderFilteredRow = append(orderFilteredRow, genFilteredRow(retApiArray.Apis[i].ApiValue, apiPath, apiVerb, maxActionNameSize, maxApiNameSize)...)
}
+ printList(orderFilteredRow, sortByName) // Sends an array of structs that contains specifed variables that are truncated
} else {
fmt.Fprintf(color.Output,
wski18n.T("{{.ok}} APIs\n",
map[string]interface{}{
"ok": color.GreenString("ok:"),
}))
- fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+ printList(orderFilteredRow, sortByName) // Sends empty orderFilteredRow so that defaultHeader can be printed
}
}
@@ -560,24 +562,25 @@ var apiListCmd = &cobra.Command{
},
}
-/*
- * Takes an API object (containing one more more single basepath/relpath/operation triplets)
- * and some filtering configuration. For each API endpoint matching the filtering criteria, display
- * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url)
- */
-func printFilteredListApi(resultApi *whisk.RetApi, apiPath string, apiVerb string) {
+// genFilteredList(resultApi, api) generates an array of
+// ApiFilteredLists for the purpose of ordering and printing in a list form.
+// NOTE: genFilteredRow() generates entries with one line per configuration
+// property (action name, verb, api name, api gw url)
+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, "printFilteredListApi: comparing api relpath: %s\n", path)
+ whisk.Debug(whisk.DbgInfo, "genFilteredList: comparing api relpath: %s\n", path)
if ( len(apiPath) == 0 || path == apiPath) {
- whisk.Debug(whisk.DbgInfo, "printFilteredListApi: relpath matches\n")
+ whisk.Debug(whisk.DbgInfo, "genFilteredList: relpath matches\n")
for op, opv := range resultApi.Swagger.Paths[path] {
- whisk.Debug(whisk.DbgInfo, "printFilteredListApi: comparing operation: '%s'\n", op)
+ whisk.Debug(whisk.DbgInfo, "genFilteredList: comparing operation: '%s'\n", op)
if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) {
- whisk.Debug(whisk.DbgInfo, "printFilteredListApi: operation matches: %#v\n", opv)
+ whisk.Debug(whisk.DbgInfo, "genFilteredList: operation matches: %#v\n", opv)
var actionName string
if (opv.XOpenWhisk == nil) {
actionName = ""
@@ -586,38 +589,36 @@ func printFilteredListApi(resultApi *whisk.RetApi, apiPath string, apiVerb strin
} else {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
}
- fmt.Printf("%s: %s\n", wski18n.T("Action"), actionName)
- fmt.Printf(" %s: %s\n", wski18n.T("API Name"), apiName)
- fmt.Printf(" %s: %s\n", wski18n.T("Base path"), basePath)
- fmt.Printf(" %s: %s\n", wski18n.T("Path"), path)
- fmt.Printf(" %s: %s\n", wski18n.T("Verb"), op)
- fmt.Printf(" %s: %s\n", wski18n.T("URL"), baseUrl+path)
+ orderInfo = AssignListInfo(actionName, op, apiName, basePath, path, baseUrl+path)
+ whisk.Debug(whisk.DbgInfo, "Appening to orderInfoArr: %s %s\n", orderInfo.RelPath)
+ orderInfoArr = append(orderInfoArr, orderInfo)
}
}
}
}
}
+ return orderInfoArr
}
-/*
- * Takes an API object (containing one more more single basepath/relpath/operation triplets)
- * and some filtering configuration. For each API matching the filtering criteria, display the API
- * on a single line (action name, verb, api name, api gw url).
- *
- * NOTE: Large action name and api name value will be truncated by their associated max size parameters.
- */
-func printFilteredListRow(resultApi *whisk.RetApi, apiPath string, apiVerb string, maxActionNameSize int, maxApiNameSize int) {
+// 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.
+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, "printFilteredListRow: comparing api relpath: %s\n", path)
+ whisk.Debug(whisk.DbgInfo, "genFilteredRow: comparing api relpath: %s\n", path)
if ( len(apiPath) == 0 || path == apiPath) {
- whisk.Debug(whisk.DbgInfo, "printFilteredListRow: relpath matches\n")
+ whisk.Debug(whisk.DbgInfo, "genFilteredRow: relpath matches\n")
for op, opv := range resultApi.Swagger.Paths[path] {
- whisk.Debug(whisk.DbgInfo, "printFilteredListRow: comparing operation: '%s'\n", op)
+ whisk.Debug(whisk.DbgInfo, "genFilteredRow: comparing operation: '%s'\n", op)
if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) {
- whisk.Debug(whisk.DbgInfo, "printFilteredListRow: operation matches: %#v\n", opv)
+ whisk.Debug(whisk.DbgInfo, "genFilteredRow: operation matches: %#v\n", opv)
var actionName string
if (opv.XOpenWhisk == nil) {
actionName = ""
@@ -626,21 +627,51 @@ func printFilteredListRow(resultApi *whisk.RetApi, apiPath string, apiVerb strin
} else {
actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
}
- fmt.Printf(fmtString,
- actionName[0 : min(len(actionName), maxActionNameSize)],
- op,
- apiName[0 : min(len(apiName), maxApiNameSize)],
- baseUrl+path)
+ 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 %s\n", orderInfo.RelPath)
+ orderInfoArr = append(orderInfoArr, orderInfo)
}
}
}
}
}
+ return orderInfoArr
+}
+
+// AssignRowInfo(actionName, verb, apiName, basePath, relPath, url) assigns
+// the given vaules to and initializes an ApiFilteredRow struct, then returns it.
+func AssignRowInfo(actionName string, verb string, apiName string, basePath string, relPath string, url string) whisk.ApiFilteredRow {
+ var orderInfo whisk.ApiFilteredRow
+
+ orderInfo.ActionName = actionName
+ orderInfo.Verb = verb
+ orderInfo.ApiName = apiName
+ orderInfo.BasePath = basePath
+ orderInfo.RelPath = relPath
+ orderInfo.Url = url
+
+ return orderInfo
+}
+
+// AssignListInfo(actionName, verb, apiName, basePath, relPath, url) assigns
+// the given vaules to and initializes an ApiFilteredList struct, then returns it.
+func AssignListInfo(actionName string, verb string, apiName string, basePath string, relPath string, url string) whisk.ApiFilteredList {
+ var orderInfo whisk.ApiFilteredList
+
+ orderInfo.ActionName = actionName
+ orderInfo.Verb = verb
+ orderInfo.ApiName = apiName
+ orderInfo.BasePath = basePath
+ orderInfo.RelPath = relPath
+ orderInfo.Url = url
+
+ return orderInfo
}
func getLargestActionNameSize(retApiArray *whisk.RetApiArray, apiPath string, apiVerb string) int {
var maxNameSize = 0
- for i:=0; i<len(retApiArray.Apis); i++ {
+ for i := 0; i < len(retApiArray.Apis); i++ {
var resultApi = retApiArray.Apis[i].ApiValue
if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
for path, _ := range resultApi.Swagger.Paths {
@@ -673,7 +704,7 @@ func getLargestActionNameSize(retApiArray *whisk.RetApiArray, apiPath string, ap
func getLargestApiNameSize(retApiArray *whisk.RetApiArray, apiPath string, apiVerb string) int {
var maxNameSize = 0
- for i:=0; i<len(retApiArray.Apis); i++ {
+ for i := 0; i < len(retApiArray.Apis); i++ {
var resultApi = retApiArray.Apis[i].ApiValue
apiName := resultApi.Swagger.Info.Title
if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
@@ -920,6 +951,7 @@ func init() {
apiGetCmd.Flags().StringVarP(&Flags.common.format, "format", "", formatOptionJson, wski18n.T("Specify the API output `TYPE`, either json or yaml"))
apiListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
apiListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
+ apiListCmd.Flags().BoolVarP(&Flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by order of [BASE_PATH | API_NAME], API_PATH, then API_VERB; only applicable within the limit/skip returned entity block"))
apiListCmd.Flags().BoolVarP(&Flags.common.full, "full", "f", false, wski18n.T("display full description of each API"))
apiCmd.AddCommand(
apiCreateCmd,
diff --git a/commands/flags.go b/commands/flags.go
index 7ef23d6..9a3454f 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -61,6 +61,7 @@ type FlagsStruct struct {
feed string // name of feed
detail bool
format string
+ nameSort bool // sorts list alphabetically by entity name
}
property struct {
diff --git a/commands/namespace.go b/commands/namespace.go
index a9f7bef..f7af0fc 100644
--- a/commands/namespace.go
+++ b/commands/namespace.go
@@ -55,7 +55,7 @@ var namespaceListCmd = &cobra.Command{
werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_NETWORK, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
return werr
}
- printList(namespaces)
+ printList(namespaces, false) // `-n` flag applies to `namespace get`, not list, so must pass value false for printList here
return nil
},
}
@@ -99,16 +99,31 @@ var namespaceGetCmd = &cobra.Command{
fmt.Fprintf(color.Output, wski18n.T("Entities in namespace: {{.namespace}}\n",
map[string]interface{}{"namespace": boldString(getClientNamespace())}))
- printList(namespace.Contents.Packages)
- printList(namespace.Contents.Actions)
- printList(namespace.Contents.Triggers)
- printList(namespace.Contents.Rules)
+ sortByName := flags.common.nameSort
+ printList(namespace.Contents.Packages, sortByName)
+ printList(namespace.Contents.Actions, sortByName)
+ printList(namespace.Contents.Triggers, sortByName)
+ //No errors, lets attempt to retrieve the status of each rule #312
+ for index, rule := range namespace.Contents.Rules {
+ ruleStatus, _, err := client.Rules.Get(rule.Name)
+ if err != nil {
+ errStr := wski18n.T("Unable to get status of rule '{{.name}}': {{.err}}",
+ map[string]interface{}{"name": rule.Name, "err": err})
+ fmt.Println(errStr)
+ werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+ return werr
+ }
+ namespace.Contents.Rules[index].Status = ruleStatus.Status
+ }
+ printList(namespace.Contents.Rules, sortByName)
return nil
},
}
func init() {
+ namespaceGetCmd.Flags().BoolVarP(&flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
+
namespaceCmd.AddCommand(
namespaceListCmd,
namespaceGetCmd,
diff --git a/commands/package.go b/commands/package.go
index fcf6652..9dff500 100644
--- a/commands/package.go
+++ b/commands/package.go
@@ -412,7 +412,8 @@ var packageListCmd = &cobra.Command{
return werr
}
- printList(packages)
+ sortByName := flags.common.nameSort
+ printList(packages, sortByName)
return nil
},
@@ -503,6 +504,7 @@ var packageRefreshCmd = &cobra.Command{
}
func init() {
+<<<<<<< HEAD
packageCreateCmd.Flags().StringSliceVarP(&Flags.common.annotation, "annotation", "a", []string{}, wski18n.T("annotation values in `KEY VALUE` format"))
packageCreateCmd.Flags().StringVarP(&Flags.common.annotFile, "annotation-file", "A", "", wski18n.T("`FILE` containing annotation values in JSON format"))
packageCreateCmd.Flags().StringSliceVarP(&Flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
@@ -524,6 +526,7 @@ func init() {
packageListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of packages from the result"))
packageListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of packages from the collection"))
+ packageListCmd.Flags().BoolVarP(&Flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
packageCmd.AddCommand(
packageBindCmd,
diff --git a/commands/rule.go b/commands/rule.go
index 4d34af6..67cddf0 100644
--- a/commands/rule.go
+++ b/commands/rule.go
@@ -402,7 +402,9 @@ var ruleListCmd = &cobra.Command{
rules[index].Status = ruleStatus.Status
}
}
- printList(rules)
+
+ sortByName := flags.common.nameSort
+ printList(rules, sortByName)
return nil
},
}
@@ -414,6 +416,7 @@ func init() {
ruleListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of rules from the result"))
ruleListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of rules from the collection"))
+ ruleListCmd.Flags().BoolVarP(&Flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
ruleCmd.AddCommand(
ruleCreateCmd,
diff --git a/commands/trigger.go b/commands/trigger.go
index 4b1c2e9..0d85af7 100644
--- a/commands/trigger.go
+++ b/commands/trigger.go
@@ -457,7 +457,8 @@ var triggerListCmd = &cobra.Command{
werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
return werr
}
- printList(triggers)
+ sortByName := flags.common.nameSort
+ printList(triggers, sortByName)
return nil
},
}
@@ -510,6 +511,7 @@ func init() {
triggerListCmd.Flags().IntVarP(&Flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of triggers from the result"))
triggerListCmd.Flags().IntVarP(&Flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of triggers from the collection"))
+ triggerListCmd.Flags().BoolVarP(&Flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
triggerCmd.AddCommand(
triggerFireCmd,
diff --git a/commands/util.go b/commands/util.go
index 8bb5aae..de0b1f7 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -122,28 +122,99 @@ func getEscapedJSON(value string) (string) {
func isValidJSON(value string) (bool) {
var jsonInterface interface{}
err := json.Unmarshal([]byte(value), &jsonInterface)
+
return err == nil
}
var boldString = color.New(color.Bold).SprintFunc()
-func printList(collection interface{}) {
- switch collection := collection.(type) {
+type Sortables []whisk.Sortable
+// Uses quickSort to sort commands based on their compare methods
+// Param: Takes in a array of Sortable interfaces which contains a specific command
+func Swap(sortables Sortables, i, j int) { sortables[i], sortables[j] = sortables[j], sortables[i] }
+
+func toPrintable(sortable []whisk.Sortable) []whisk.Printable{
+ sortedPrintable := make([]whisk.Printable, len(sortable), len(sortable))
+ for i := range sortable {
+ sortedPrintable[i] = sortable[i].(whisk.Printable)
+ }
+ return sortedPrintable
+}
+
+// Prints the parameters/list for wsk xxxx list
+// Identifies type and then copies array into an array of interfaces(Sortable) to be sorted and printed
+// Param: Takes in an interace which contains an array of a command(Ex: []Action)
+func printList(collection interface{}, sortByName bool) {
+ var commandToSort []whisk.Sortable
+ switch collection := collection.(type){
case []whisk.Action:
- printActionList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
case []whisk.Trigger:
- printTriggerList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
case []whisk.Package:
- printPackageList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
case []whisk.Rule:
- printRuleList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
case []whisk.Namespace:
- printNamespaceList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
case []whisk.Activation:
- printActivationList(collection)
- case []whisk.Api:
- printApiList(collection)
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
+ case []whisk.ApiFilteredList:
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
+ case []whisk.ApiFilteredRow:
+ for i := range collection {
+ commandToSort = append(commandToSort, collection[i])
+ }
+ }
+ if sortByName && len(commandToSort) > 0 {
+ quickSort(commandToSort, 0, len(commandToSort)-1)
}
+ printCommandsList(toPrintable(commandToSort), makeDefaultHeader(collection))
+}
+
+func quickSort(toSort Sortables, left int, right int) {
+ low := left
+ high := right
+ pivot := toSort[(left + right) / 2]
+
+ for low <= high {
+ for toSort[low].Compare(pivot) { low++ }
+ for pivot.Compare(toSort[high]) { high-- }
+ if low <= high {
+ Swap(toSort, low, high)
+ low++
+ high--
+ }
+ }
+ if left < high { quickSort(toSort, left, high) }
+ if low < right { quickSort(toSort, low, right) }
+}
+
+// makeDefaultHeader(collection) returns the default header to be used in case
+// the list to be printed is empty.
+func makeDefaultHeader(collection interface{}) string {
+ defaultHeader := reflect.TypeOf(collection).String()
+ defaultHeader = strings.ToLower(defaultHeader[8:] + "s") // Removes '[]whisk.' from `[]whisk.ENTITY_TYPE`
+ if defaultHeader == "apifilteredrows" {
+ defaultHeader = fmt.Sprintf("%-30s %7s %20s %s", "Action", "Verb", "API Name", "URL")
+ } else if defaultHeader == "apifilteredlists" {
+ defaultHeader = ""
+ }
+ return defaultHeader
}
func printFullList(collection interface{}) {
@@ -179,53 +250,18 @@ func printSummary(collection interface{}) {
}
}
-func printActionList(actions []whisk.Action) {
- fmt.Fprintf(color.Output, "%s\n", boldString("actions"))
- for _, action := range actions {
- publishState := wski18n.T("private")
- kind := getValueString(action.Annotations, "exec")
- fmt.Printf("%-70s %s %s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState, kind)
- }
-}
-
-func printTriggerList(triggers []whisk.Trigger) {
- fmt.Fprintf(color.Output, "%s\n", boldString("triggers"))
- for _, trigger := range triggers {
- publishState := wski18n.T("private")
- fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", trigger.Namespace, trigger.Name), publishState)
- }
-}
-
-func printPackageList(packages []whisk.Package) {
- fmt.Fprintf(color.Output, "%s\n", boldString("packages"))
- for _, xPackage := range packages {
- publishState := wski18n.T("private")
- if xPackage.Publish != nil && *xPackage.Publish {
- publishState = wski18n.T("shared")
+// Used to print Action, Tigger, Package, and Rule lists
+// Param: Takes in a array of Printable interface, and the name of the command
+// being sent to it
+// **Note**: The name sould be an empty string for APIs.
+func printCommandsList(commands []whisk.Printable, defaultHeader string) {
+ if len(commands) != 0 {
+ fmt.Fprint(color.Output, boldString(commands[0].ToHeaderString()))
+ for i := range commands {
+ fmt.Print(commands[i].ToSummaryRowString())
}
- fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", xPackage.Namespace, xPackage.Name), publishState)
- }
-}
-
-func printRuleList(rules []whisk.Rule) {
- fmt.Fprintf(color.Output, "%s\n", boldString("rules"))
- for _, rule := range rules {
- publishState := wski18n.T("private")
- fmt.Printf("%-70s %-20s %s\n", fmt.Sprintf("/%s/%s", rule.Namespace, rule.Name), publishState, rule.Status)
- }
-}
-
-func printNamespaceList(namespaces []whisk.Namespace) {
- fmt.Fprintf(color.Output, "%s\n", boldString("namespaces"))
- for _, namespace := range namespaces {
- fmt.Printf("%s\n", namespace.Name)
- }
-}
-
-func printActivationList(activations []whisk.Activation) {
- fmt.Fprintf(color.Output, "%s\n", boldString("activations"))
- for _, activation := range activations {
- fmt.Printf("%s %-20s\n", activation.ActivationID, activation.Name)
+ } else {
+ fmt.Fprintf(color.Output, "%s\n", boldString(defaultHeader))
}
}
@@ -236,20 +272,6 @@ func printFullActivationList(activations []whisk.Activation) {
}
}
-func printApiList(apis []whisk.Api) {
- fmt.Fprintf(color.Output, "%s\n", boldString("apis"))
- for _, api := range apis {
- fmt.Printf("%s %20s %20s\n", api.ApiName, api.GatewayBasePath, api.GatewayFullPath)
- }
-}
-
-func printFullApiList(apis []whisk.Api) {
- fmt.Fprintf(color.Output, "%s\n", boldString("apis"))
- for _, api := range apis {
- printJSON(api)
- }
-}
-
func printActivationLogs(logs []string) {
for _, log := range logs {
fmt.Printf("%s\n", log)
diff --git a/commands/wsk.go b/commands/wsk.go
index f7f209b..874e549 100644
--- a/commands/wsk.go
+++ b/commands/wsk.go
@@ -44,6 +44,8 @@ func init() {
WskCmd.SetHelpTemplate(`{{with or .Long .Short }}{{.}}
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`)
+listCmd.Flags().BoolVarP(&flags.common.nameSort, "name-sort", "n", false, wski18n.T("sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"))
+
WskCmd.AddCommand(
actionCmd,
activationCmd,
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 0042ed4..0d90c6a 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -109,12 +109,12 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
-var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5d\x5f\x73\xdb\x38\x92\x7f\xcf\xa7\xe8\x9a\x17\x3b\x55\xb2\xb3\xfb\x74\x75\x99\x9a\x07\x4d\xec\xd9\x78\x93\xd8\xae\xc8\x99\xdd\xa9\x9b\xab\x11\x4c\x42\x12\xc6\x14\xc0\x01\x40\x2b\x4a\xd6\xdf\xfd\x0a\x00\x49\x91\x12\xfe\x92\x72\x72\x4f\x71\xc4\xee\x5f\x37\x80\x06\xd0\x68\x34\x80\xff\x79\x01\xf0\xf5\x05\x00\xc0\x0f\x24\xff\xe1\x35\xfc\x30\x2d\xcb\x82\x64\x48\x12\x46\x01\x7f\x26\x12\xe7\x50\x51\xfc\xb9 [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x4f\x73\xdb\x38\xd2\xf7\x7d\x3e\x45\x57\x2e\x76\xde\x92\x9d\xdd\xd3\x5b\x4f\x52\x73\xd0\x24\x9e\x8d\x37\x89\xed\x8a\x9d\xd9\x9d\xda\x6c\x8d\x20\x12\x92\xb0\xa6\x00\x0e\x00\x5a\x51\xb2\xfe\xee\x4f\x01\x20\x29\x52\xc2\x5f\x52\x4e\x9e\x53\x1c\xb1\xfb\xd7\x0d\xa0\x01\x34\x1a\x0d\xe0\x5f\x3f\x01\x7c\xfb\x09\x00\xe0\x19\xc9\x9f\xbd\x84\x67\xd3\xb2\x2c\x48\x86\x24\x61\x14\xf0\x17\x22\x71\x0e\x15\xc5\x5f [...]
func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
return bindataRead(
@@ -129,7 +129,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 49848, mode: os.FileMode(420), modTime: time.Unix(1502310784, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 50834, mode: os.FileMode(420), modTime: time.Unix(1502981211, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -149,7 +149,7 @@ func wski18nResourcesEs_esAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -169,7 +169,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -189,7 +189,7 @@ func wski18nResourcesIt_itAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -209,7 +209,7 @@ func wski18nResourcesJa_jaAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -229,7 +229,7 @@ func wski18nResourcesKo_krAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -249,7 +249,7 @@ func wski18nResourcesPt_brAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -269,7 +269,7 @@ func wski18nResourcesZh_hansAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -289,7 +289,7 @@ func wski18nResourcesZh_hantAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502310633, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 78acda0..39551d0 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -1400,8 +1400,8 @@
"translation": "display full description of each API"
},
{
- "id": "An API host must be provided.",
- "translation": "An API host must be provided."
+ "id": "order API list by action name first followed by base-path/rel-path/verb",
+ "translation": "order API list by action name first followed by base-path/rel-path/verb."
},
{
"id": "Request accepted, but processing not completed yet.",
@@ -1510,9 +1510,16 @@
{
"id": "Unable to output bash command completion {{.err}}",
"translation": "Unable to output bash command completion {{.err}}"
-},
-{
+ },
+ {
"id": "prints bash command completion script to stdout",
"translation": "prints bash command completion script to stdout"
-}
-]
+ },
+ {
+ "id": "sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block",
+ "translation": "sorts a list alphabetically by entity name; only applicable within the limit/skip returned entity block"
+ },
+ {
+ "id": "sorts a list alphabetically by order of [BASE_PATH | API_NAME], API_PATH, then API_VERB; only applicable within the limit/skip returned entity block",
+ "translation": "sorts a list alphabetically by order of [BASE_PATH | API_NAME], API_PATH, then API_VERB; only applicable within the limit/skip returned entity block"
+ }]
--
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.