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 14:13:30 UTC
[incubator-openwhisk-client-go] branch master updated: 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-client-go.git
The following commit(s) were added to refs/heads/master by this push:
new b239221 Allow CLI to sort entities by name (#2326)
b239221 is described below
commit b239221db78b0578518daa81d97ab66cad6d08db
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`
---
whisk/action.go | 45 ++++++++++++++++++++++++
whisk/activation.go | 20 +++++++++++
whisk/api.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++-
whisk/namespace.go | 29 +++++++++++++++
whisk/package.go | 39 +++++++++++++++++++++
whisk/rule.go | 32 ++++++++++++++++-
whisk/trigger.go | 34 +++++++++++++++++-
whisk/util.go | 15 ++++++++
wski18n/i18n_resources.go | 20 +++++------
9 files changed, 310 insertions(+), 13 deletions(-)
diff --git a/whisk/action.go b/whisk/action.go
index d5cd43f..e2cfed5 100644
--- a/whisk/action.go
+++ b/whisk/action.go
@@ -58,6 +58,51 @@ type ActionListOptions struct {
Docs bool `url:"docs,omitempty"`
}
+// Compare(sortable) compares action to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Action.
+// ***Method of type Sortable***
+func(action Action) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by NAMESPACE -> PACKAGE_NAME -> ACTION_NAME, with
+ // actions under default package at the top.
+ var actionString string
+ var compareString string
+ actionToCompare := sortable.(Action)
+
+ actionString = strings.ToLower(fmt.Sprintf("%s%s", action.Namespace, action.Name))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s", actionToCompare.Namespace,
+ actionToCompare.Name))
+ if strings.Contains(action.Namespace, "/") && !strings.Contains(actionToCompare.Namespace, "/") {
+ return false
+ } else if !strings.Contains(action.Namespace, "/") && strings.Contains(actionToCompare.Namespace, "/") {
+ return true
+ } else if strings.Contains(action.Namespace, "/") && strings.Contains(actionToCompare.Namespace, "/") {
+ return actionString < compareString
+ } else {
+ return action.Name < actionToCompare.Name
+ }
+}
+
+// ToHeaderString() returns the header for a list of actions
+func(action Action) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "actions")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk action list`.
+// ***Method of type Sortable***
+func(action Action) ToSummaryRowString() string{
+ var kind string
+ publishState := wski18n.T("private")
+
+ for i := range action.Annotations {
+ if (action.Annotations[i].Key == "exec") {
+ kind = action.Annotations[i].Value.(string)
+ break
+ }
+ }
+ return fmt.Sprintf("%-70s %s %s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState, kind)
+}
+
/*
Determines if an action is a web action by examining the action's annotations. A value of true is returned if the
action's annotations contains a "web-export" key and its associated value is a boolean value of "true". Otherwise, false
diff --git a/whisk/activation.go b/whisk/activation.go
index 654c405..62d472f 100644
--- a/whisk/activation.go
+++ b/whisk/activation.go
@@ -70,6 +70,26 @@ type Log struct {
Time string `json:"time,omitempty"`
}
+// Compare(sortable) compares activation to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Activation.
+// ***Method of type Sortable***
+// ***Currently, no method of sorting defined***
+func(activation Activation) Compare(sortable Sortable) (bool) {
+ return true
+}
+
+// ToHeaderString() returns the header for a list of activations
+func(activation Activation) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "activations")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk activation list`.
+// ***Method of type Sortable***
+func(activation Activation) ToSummaryRowString() string {
+ return fmt.Sprintf("%s %-20s\n", activation.ActivationID, activation.Name)
+}
+
func (s *ActivationService) List(options *ActivationListOptions) ([]Activation, *http.Response, error) {
// TODO :: for some reason /activations only works with "_" as namespace
s.client.Namespace = "_"
diff --git a/whisk/api.go b/whisk/api.go
index 1fa8d7b..0d318d2 100644
--- a/whisk/api.go
+++ b/whisk/api.go
@@ -21,6 +21,8 @@ import (
"net/http"
"errors"
"github.com/apache/incubator-openwhisk-client-go/wski18n"
+ "strings"
+ "fmt"
)
type ApiService struct {
@@ -143,6 +145,27 @@ type ApiSwaggerOpXOpenWhisk struct {
ApiUrl string `json:"url"`
}
+// Used for printing individual APIs in non-truncated form
+type ApiFilteredList struct {
+ ActionName string
+ ApiName string
+ BasePath string
+ RelPath string
+ Verb string
+ Url string
+}
+
+// Used for printing individual APIs in truncated form
+type ApiFilteredRow struct {
+ ActionName string
+ ApiName string
+ BasePath string
+ RelPath string
+ Verb string
+ Url string
+ FmtString string
+}
+
var ApiVerbs map[string]bool = map[string]bool {
"GET": true,
"PUT": true,
@@ -162,6 +185,70 @@ const (
// Api Methods //
/////////////////
+// Compare(sortable) compares api to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type ApiFilteredList.
+// ***Method of type Sortable***
+func(api ApiFilteredList) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by [BASE_PATH | API_NAME] -> REL_PATH -> API_VERB
+ apiToCompare := sortable.(ApiFilteredList)
+ var apiString string
+ var compareString string
+
+ apiString = strings.ToLower(fmt.Sprintf("%s%s%s",api.BasePath, api.RelPath,
+ api.Verb))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s%s", apiToCompare.BasePath,
+ apiToCompare.RelPath, apiToCompare.Verb))
+
+ return apiString < compareString
+}
+
+// ToHeaderString() returns the header for a list of apis
+func(api ApiFilteredList) ToHeaderString() string {
+ return ""
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk api list` or `wsk api-experimental list`.
+// ***Method of type Sortable***
+func(api ApiFilteredList) ToSummaryRowString() string {
+ return fmt.Sprintf("%s %s %s %s %s %s",
+ fmt.Sprintf("%s: %s\n", wski18n.T("Action"), api.ActionName),
+ fmt.Sprintf(" %s: %s\n", wski18n.T("API Name"), api.ApiName),
+ fmt.Sprintf(" %s: %s\n", wski18n.T("Base path"), api.BasePath),
+ fmt.Sprintf(" %s: %s\n", wski18n.T("Path"), api.RelPath),
+ fmt.Sprintf(" %s: %s\n", wski18n.T("Verb"), api.Verb),
+ fmt.Sprintf(" %s: %s\n", wski18n.T("URL"), api.Url))
+}
+
+// Compare(sortable) compares api to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type ApiFilteredRow.
+// ***Method of type Sortable***
+func(api ApiFilteredRow) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by [BASE_PATH | API_NAME] -> REL_PATH -> API_VERB
+ var apiString string
+ var compareString string
+ apiToCompare := sortable.(ApiFilteredRow)
+
+ apiString = strings.ToLower(fmt.Sprintf("%s%s%s",api.BasePath, api.RelPath,
+ api.Verb))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s%s", apiToCompare.BasePath,
+ apiToCompare.RelPath, apiToCompare.Verb))
+
+ return apiString < compareString
+}
+
+// ToHeaderString() returns the header for a list of apis
+func(api ApiFilteredRow) ToHeaderString() string {
+ return fmt.Sprintf("%s", fmt.Sprintf(api.FmtString, "Action", "Verb", "API Name", "URL"))
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk api list -f` or `wsk api-experimental list -f`.
+// ***Method of type Sortable***
+func(api ApiFilteredRow) ToSummaryRowString() string {
+ return fmt.Sprintf(api.FmtString, api.ActionName, api.Verb, api.ApiName, api.Url)
+}
+
func (s *ApiService) List(apiListOptions *ApiListRequestOptions) (*ApiListResponse, *http.Response, error) {
route := "web/whisk.system/apimgmt/getApi.http"
@@ -315,7 +402,7 @@ func (s *ApiService) Delete(api *ApiDeleteRequest, options *ApiDeleteRequestOpti
func validateApiListResponse(apiList *ApiListResponse) error {
- for i:=0; i<len(apiList.Apis); i++ {
+ for i := 0; i < len(apiList.Apis); i++ {
if apiList.Apis[i].ApiValue == nil {
Debug(DbgError, "validateApiResponse: No value stanza in api %v\n", apiList.Apis[i])
errMsg := wski18n.T("Internal error. Missing value stanza in API configuration response")
diff --git a/whisk/namespace.go b/whisk/namespace.go
index 0705608..0fc2403 100644
--- a/whisk/namespace.go
+++ b/whisk/namespace.go
@@ -21,6 +21,8 @@ import (
"net/http"
"errors"
"github.com/apache/incubator-openwhisk-client-go/wski18n"
+ "strings"
+ "fmt"
)
type Namespace struct {
@@ -39,6 +41,33 @@ type NamespaceService struct {
client *Client
}
+// Compare(sortable) compares namespace to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Namespace.
+// ***Method of type Sortable***
+func(namespace Namespace) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically
+ namespaceToCompare := sortable.(Namespace)
+ var namespaceString string
+ var compareString string
+
+ namespaceString = strings.ToLower(namespace.Name)
+ compareString = strings.ToLower(namespaceToCompare.Name)
+
+ return namespaceString < compareString
+}
+
+// ToHeaderString() returns the header for a list of namespaces
+func(namespace Namespace) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "namespaces")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk namespace list`.
+// ***Method of type Sortable***
+func(namespace Namespace) ToSummaryRowString() string {
+ return fmt.Sprintf("%s\n", namespace.Name)
+}
+
// get a list of available namespaces
func (s *NamespaceService) List() ([]Namespace, *http.Response, error) {
// make a request to c.BaseURL / namespaces
diff --git a/whisk/package.go b/whisk/package.go
index 7b96180..8597f15 100644
--- a/whisk/package.go
+++ b/whisk/package.go
@@ -23,6 +23,7 @@ import (
"net/url"
"errors"
"github.com/apache/incubator-openwhisk-client-go/wski18n"
+ "strings"
)
type PackageService struct {
@@ -46,6 +47,7 @@ type Package struct {
Actions []Action `json:"actions,omitempty"`
Feeds []Action `json:"feeds,omitempty"`
}
+
func (p *Package) GetName() string {
return p.Name
}
@@ -84,6 +86,43 @@ type PackageListOptions struct {
Docs bool `url:"docs,omitempty"`
}
+// Compare(sortable) compares xPackage to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Package.
+// ***Method of type Sortable***
+func(xPackage Package) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by NAMESPACE -> PACKAGE_NAME
+ packageToCompare := sortable.(Package)
+
+ var packageString string
+ var compareString string
+
+ packageString = strings.ToLower(fmt.Sprintf("%s%s",xPackage.Namespace,
+ xPackage.Name))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s", packageToCompare.Namespace,
+ packageToCompare.Name))
+
+ return packageString < compareString
+}
+
+// ToHeaderString() returns the header for a list of actions
+func(pkg Package) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "packages")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk package list`.
+// ***Method of type Sortable***
+func(xPackage Package) ToSummaryRowString() string{
+ publishState := wski18n.T("private")
+
+ if xPackage.Publish != nil && *xPackage.Publish {
+ publishState = wski18n.T("shared")
+ }
+
+ return fmt.Sprintf("%-70s %s\n", fmt.Sprintf("/%s/%s", xPackage.Namespace,
+ xPackage.Name), publishState)
+}
+
func (s *PackageService) List(options *PackageListOptions) ([]Package, *http.Response, error) {
route := fmt.Sprintf("packages")
routeUrl, err := addRouteOptions(route, options)
diff --git a/whisk/rule.go b/whisk/rule.go
index ab268e2..86261ad 100644
--- a/whisk/rule.go
+++ b/whisk/rule.go
@@ -38,7 +38,6 @@ type Rule struct {
Trigger interface{} `json:"trigger"`
Action interface{} `json:"action"`
Publish *bool `json:"publish,omitempty"`
-
}
type RuleListOptions struct {
@@ -47,6 +46,37 @@ type RuleListOptions struct {
Docs bool `url:"docs,omitempty"`
}
+// Compare(sortable) compares rule to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Rule.
+// ***Method of type Sortable***
+func(rule Rule) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by NAMESPACE -> PACKAGE_NAME
+ ruleToCompare := sortable.(Rule)
+ var ruleString string
+ var compareString string
+
+ ruleString = strings.ToLower(fmt.Sprintf("%s%s",rule.Namespace, rule.Name))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s", ruleToCompare.Namespace,
+ ruleToCompare.Name))
+
+ return ruleString < compareString
+}
+
+// ToHeaderString() returns the header for a list of rules
+func(rule Rule) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "rules")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk rule list`.
+// ***Method of type Sortable***
+func(rule Rule) ToSummaryRowString() string{
+ publishState := wski18n.T("private")
+
+ return fmt.Sprintf("%-70s %-20s %s\n", fmt.Sprintf("/%s/%s", rule.Namespace,
+ rule.Name), publishState, rule.Status)
+}
+
func (s *RuleService) List(options *RuleListOptions) ([]Rule, *http.Response, error) {
route := "rules"
routeUrl, err := addRouteOptions(route, options)
diff --git a/whisk/trigger.go b/whisk/trigger.go
index 0d0fb76..5bc6b12 100644
--- a/whisk/trigger.go
+++ b/whisk/trigger.go
@@ -23,6 +23,7 @@ import (
"errors"
"net/url"
"github.com/apache/incubator-openwhisk-client-go/wski18n"
+ "strings"
)
type TriggerService struct {
@@ -38,7 +39,6 @@ type Trigger struct {
Parameters KeyValueArr `json:"parameters,omitempty"`
Limits *Limits `json:"limits,omitempty"`
Publish *bool `json:"publish,omitempty"`
-
}
type TriggerListOptions struct {
@@ -47,6 +47,38 @@ type TriggerListOptions struct {
Docs bool `url:"docs,omitempty"`
}
+// Compare(sortable) compares trigger to sortable for the purpose of sorting.
+// REQUIRED: sortable must also be of type Trigger.
+// ***Method of type Sortable***
+func(trigger Trigger) Compare(sortable Sortable) (bool) {
+ // Sorts alphabetically by NAMESPACE -> TRIGGER_NAME
+ triggerToCompare := sortable.(Trigger)
+ var triggerString string
+ var compareString string
+
+ triggerString = strings.ToLower(fmt.Sprintf("%s%s",trigger.Namespace,
+ trigger.Name))
+ compareString = strings.ToLower(fmt.Sprintf("%s%s", triggerToCompare.Namespace,
+ triggerToCompare.Name))
+
+ return triggerString < compareString
+}
+
+// ToHeaderString() returns the header for a list of triggers
+func(trigger Trigger) ToHeaderString() string {
+ return fmt.Sprintf("%s\n", "triggers")
+}
+
+// ToSummaryRowString() returns a compound string of required parameters for printing
+// from CLI command `wsk trigger list`.
+// ***Method of type Sortable***
+func(trigger Trigger) ToSummaryRowString() string {
+ publishState := wski18n.T("private")
+
+ return fmt.Sprintf("%-70s %s\n", fmt.Sprintf("/%s/%s", trigger.Namespace,
+ trigger.Name), publishState)
+}
+
func (s *TriggerService) List(options *TriggerListOptions) ([]Trigger, *http.Response, error) {
route := "triggers"
routeUrl, err := addRouteOptions(route, options)
diff --git a/whisk/util.go b/whisk/util.go
index 150647f..329e9ea 100644
--- a/whisk/util.go
+++ b/whisk/util.go
@@ -29,6 +29,21 @@ import (
"github.com/apache/incubator-openwhisk-client-go/wski18n"
)
+// Sortable items are anything that needs to be sorted for listing purposes.
+type Sortable interface {
+ // Compare(sortable) compares an two sortables and returns true
+ // if the item calling the Compare method is less than toBeCompared.
+ // Sorts alphabetically by default, can have other parameters to sort by
+ // passed by sortByName.
+ Compare(toBeCompared Sortable) (bool)
+}
+
+// Printable items are anything that need to be printed for listing purposes.
+type Printable interface {
+ ToHeaderString() string // Prints header information of a Printable
+ ToSummaryRowString() string // Prints summary info of one Printable
+}
+
// addOptions adds the parameters in opt as URL query parameters to s. opt
// must be a struct whose fields may contain "url" tags.
func addRouteOptions(route string, options interface{}) (*url.URL, error) {
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index b7418d9..10fb30a 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -113,7 +113,7 @@ 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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -133,7 +133,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 4659, mode: os.FileMode(420), modTime: time.Unix(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 4659, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -153,7 +153,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -173,7 +173,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
return nil, err
}
- info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -193,7 +193,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -213,7 +213,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -233,7 +233,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -253,7 +253,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -273,7 +273,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -293,7 +293,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(1502307767, 0)}
+ info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502918884, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].