diff --git a/cli/color.go b/cli/color.go index 334868c4f..0bef4e326 100644 --- a/cli/color.go +++ b/cli/color.go @@ -121,7 +121,7 @@ func APIListColor() string { return apiListColor } -func colorized(color string, a ...interface{}) string { +func Colorized(color string, a ...interface{}) string { if withColor && color != "" { return color + fmt.Sprint(a...) + ColorOff } @@ -129,15 +129,15 @@ func colorized(color string, a ...interface{}) string { } func PrintWithColor(w io.Writer, color string, a ...interface{}) (n int, err error) { - return Print(w, colorized(color, a...)) + return Print(w, Colorized(color, a...)) } func Notice(w io.Writer, a ...interface{}) (n int, err error) { - return Print(w, colorized(NoticeColor, a...)) + return Print(w, Colorized(NoticeColor, a...)) } func Error(w io.Writer, a ...interface{}) (n int, err error) { - return Print(w, colorized(ErrorColor, a...)) + return Print(w, Colorized(ErrorColor, a...)) } func Noticef(w io.Writer, format string, args ...interface{}) (n int, err error) { diff --git a/cli/color_test.go b/cli/color_test.go index a19feb43a..4728b8920 100644 --- a/cli/color_test.go +++ b/cli/color_test.go @@ -30,9 +30,9 @@ func TestColor(t *testing.T) { assert.Empty(t, ProductListColor()) assert.Empty(t, APIListColor()) - assert.Equal(t, "a", colorized("", "a")) + assert.Equal(t, "a", Colorized("", "a")) EnableColor() - assert.Equal(t, "reda\033[0m", colorized("red", "a")) + assert.Equal(t, "reda\033[0m", Colorized("red", "a")) } func TestCotainWriter(t *testing.T) { diff --git a/newmeta/meta.go b/newmeta/meta.go index 251fb1cbe..0fe28b4bd 100644 --- a/newmeta/meta.go +++ b/newmeta/meta.go @@ -73,6 +73,40 @@ type API struct { Deprecated bool `json:"deprecated"` } +// { +// "name": "AddEntriesToAcl", +// "deprecated": false, +// "protocol": "HTTP|HTTPS", +// "method": "GET|POST", +// "pathPattern": "", +// "parameters": [ +// { +// "name": "AclEntries", +// "description": "The IP entries that you want to add. You can add up to 20 IP entries in each call.", +// "position": "Query", +// "type": "Array", +// "required": true +// } +// ] +// } + +type APIDetail struct { + Name string `json:"name"` + Deprecated bool `json:"deprecated"` + Protocol string `json:"protocol"` + Method string `json:"method"` + PathPattern string `json:"pathPattern"` + Parameters []RequestParameter `json:"parameters"` +} + +type RequestParameter struct { + Name string `json:"name"` + Description string `json:"description"` + Position string `json:"position"` + Type string `json:"type"` + Required bool `json:"required"` +} + func GetProductName(language, code string) (name string, err error) { content, err := GetMetadata(language, "/products.json") if err != nil { @@ -81,6 +115,9 @@ func GetProductName(language, code string) (name string, err error) { products := new(ProductSet) err = json.Unmarshal(content, &products) + if err != nil { + return + } for _, p := range products.Products { if strings.EqualFold(p.Code, code) { @@ -100,6 +137,9 @@ func GetAPI(language, code, name string) (api *API, err error) { version := new(Version) err = json.Unmarshal(content, &version) + if err != nil { + return + } if found, ok := version.APIs[name]; ok { api = &found @@ -108,6 +148,22 @@ func GetAPI(language, code, name string) (api *API, err error) { return } +func GetAPIDetail(language, code, name string) (api *APIDetail, err error) { + content, err := GetMetadata(language, "/"+strings.ToLower(code)+"/"+name+".json") + if err != nil { + return + } + + detail := new(APIDetail) + err = json.Unmarshal(content, &detail) + if err != nil { + return + } + + api = detail + return +} + func GetMetadataPrefix(language string) string { if language == "en" { return "en-US" diff --git a/newmeta/meta_test.go b/newmeta/meta_test.go index 13f134335..ae8737e5e 100644 --- a/newmeta/meta_test.go +++ b/newmeta/meta_test.go @@ -29,3 +29,11 @@ func TestGetAPI(t *testing.T) { assert.Nil(t, err) assert.Nil(t, api2) } + +func TestGetAPIDetail(t *testing.T) { + api, err := GetAPIDetail("en", "ecs", "DescribeRegions") + assert.Nil(t, err) + assert.Equal(t, "DescribeRegions", api.Name) + assert.Equal(t, "GET|POST", api.Method) + assert.Equal(t, false, api.Deprecated) +} diff --git a/openapi/library.go b/openapi/library.go index 4624323e9..b33ce6860 100644 --- a/openapi/library.go +++ b/openapi/library.go @@ -135,24 +135,27 @@ func (a *Library) PrintApiUsage(productCode string, apiName string) error { return &InvalidApiError{Name: apiName, product: &product} } + productName, _ := newmeta.GetProductName(i18n.GetLanguage(), productCode) + if product.ApiStyle == "restful" { - cli.Printf(a.writer, "\nProduct: %s (%s)\n", product.Code, product.Name[i18n.GetLanguage()]) + cli.Printf(a.writer, "\nProduct: %s (%s)\n", product.Code, productName) cli.Printf(a.writer, "Method: %s\n", api.Method) cli.Printf(a.writer, "PathPattern: %s\n", api.PathPattern) } else { - cli.Printf(a.writer, "\nProduct: %s (%s)\n", product.Code, product.Name[i18n.GetLanguage()]) + cli.Printf(a.writer, "\nProduct: %s (%s)\n", product.Code, productName) } cli.Printf(a.writer, "\nParameters:\n") w := tabwriter.NewWriter(a.writer, 8, 0, 1, ' ', 0) - printParameters(w, api.Parameters, "") + detail, _ := newmeta.GetAPIDetail(i18n.GetLanguage(), productCode, apiName) + printParameters(w, api.Parameters, "", detail) w.Flush() return nil } -func printParameters(w io.Writer, params []meta.Parameter, prefix string) { +func printParameters(w io.Writer, params []meta.Parameter, prefix string, detail *newmeta.APIDetail) { sort.Sort(meta.ParameterSlice(params)) @@ -171,16 +174,26 @@ func printParameters(w io.Writer, params []meta.Parameter, prefix string) { if param.Type == "RepeatList" { if len(param.SubParameters) > 0 { - printParameters(w, param.SubParameters, prefix+param.Name+".n.") + printParameters(w, param.SubParameters, prefix+param.Name+".n.", detail) } else { - fmt.Fprintf(w, " --%s%s.n\t%s\t%s\t%s\n", prefix, param.Name, param.Type, required(param.Required), getDescription(param.Description)) + fmt.Fprintf(w, " --%s%s.n\t%s\t%s\n\n", cli.Colorized(cli.BBlack, prefix), cli.Colorized(cli.BBlack, param.Name), param.Type, required(param.Required)) + displayDescription(w, getDescription(detail, param.Name)) } } else { - fmt.Fprintf(w, " --%s%s\t%s\t%s\t%s\n", prefix, param.Name, param.Type, required(param.Required), getDescription(param.Description)) + fmt.Fprintf(w, " --%s%s\t%s\t%s\n\n", cli.Colorized(cli.BBlack, prefix), cli.Colorized(cli.BBlack, param.Name), param.Type, required(param.Required)) + displayDescription(w, getDescription(detail, param.Name)) } } } +func displayDescription(w io.Writer, desc string) { + lines := strings.Split(desc, "\n") + for _, v := range lines { + fmt.Fprintf(w, " %s\n", v) + } + fmt.Fprintf(w, "\n") +} + func required(r bool) string { if r { return "Required" @@ -189,15 +202,15 @@ func required(r bool) string { } } -func getDescription(d map[string]string) string { +func getDescription(detail *newmeta.APIDetail, name string) string { + if detail == nil { + return "" + } + for _, p := range detail.Parameters { + if name == p.Name { + return strings.TrimSpace(p.Description) + } + } + return "" - // TODO: description too long, need optimize for display - //if d == nil { - // return "" - //} - //if v, ok := d[i18n.GetLanguage()]; ok { - // return v - //} else { - // return "" - //} } diff --git a/openapi/library_test.go b/openapi/library_test.go index af6a25190..e51ce2680 100644 --- a/openapi/library_test.go +++ b/openapi/library_test.go @@ -15,6 +15,7 @@ package openapi import ( "github.com/aliyun/aliyun-cli/meta" + "github.com/aliyun/aliyun-cli/newmeta" "github.com/stretchr/testify/assert" "bytes" @@ -97,7 +98,7 @@ func Test_printParameters(t *testing.T) { }, }, } - printParameters(w, params, "") + printParameters(w, params, "", &newmeta.APIDetail{}) } func getRepository(content string) *meta.Repository {