openapi/library.go (173 lines of code) (raw):

// Copyright (c) 2009-present, Alibaba Cloud All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package openapi import ( "fmt" "io" "sort" "strings" "text/tabwriter" "github.com/aliyun/aliyun-cli/v3/cli" "github.com/aliyun/aliyun-cli/v3/i18n" "github.com/aliyun/aliyun-cli/v3/meta" "github.com/aliyun/aliyun-cli/v3/newmeta" ) type Library struct { builtinRepo *meta.Repository writer io.Writer } func NewLibrary(w io.Writer, lang string) *Library { return &Library{ builtinRepo: meta.LoadRepository(), writer: w, } } func (a *Library) GetProduct(productCode string) (meta.Product, bool) { return a.builtinRepo.GetProduct(productCode) } func (a *Library) GetApi(productCode string, version string, apiName string) (meta.Api, bool) { return a.builtinRepo.GetApi(productCode, version, apiName) } func (a *Library) GetApiByPath(productCode string, version string, method string, path string) (meta.Api, bool) { return a.builtinRepo.GetApiByPath(productCode, version, method, path) } func (a *Library) GetStyle(productCode string, version string) (string, bool) { return a.builtinRepo.GetStyle(productCode, version) } func (a *Library) GetProducts() []meta.Product { return a.builtinRepo.Products } func (a *Library) PrintProducts() { w := tabwriter.NewWriter(a.writer, 8, 0, 1, ' ', 0) cli.PrintfWithColor(w, cli.ColorOff, "\nProducts:\n") // sort products by code sort.Slice(a.builtinRepo.Products, func(i, j int) bool { return strings.ToLower(a.builtinRepo.Products[i].Code) < strings.ToLower(a.builtinRepo.Products[j].Code) }) for _, product := range a.builtinRepo.Products { var productName, _ = newmeta.GetProductName(i18n.GetLanguage(), product.Code) cli.PrintfWithColor(w, cli.Cyan, " %-20s\t%s\n", strings.ToLower(product.Code), productName) } w.Flush() } func (a *Library) PrintProductUsage(productCode string, withApi bool) error { product, ok := a.GetProduct(productCode) if !ok { return &InvalidProductError{Code: productCode, library: a} } if product.ApiStyle == "rpc" { cli.Printf(a.writer, "\nUsage:\n aliyun %s <ApiName> --parameter1 value1 --parameter2 value2 ...\n", strings.ToLower(product.Code)) } else { cli.Printf(a.writer, "\nUsage 1:\n aliyun %s [GET|PUT|POST|DELETE] <PathPattern> --body \"...\" \n", strings.ToLower(product.Code)) cli.Printf(a.writer, "\nUsage 2 (For API with NO PARAMS in PathPattern only.):\n aliyun %s <ApiName> --parameter1 value1 --parameter2 value2 ... --body \"...\"\n", strings.ToLower(product.Code)) } productName, _ := newmeta.GetProductName(i18n.GetLanguage(), product.Code) cli.Printf(a.writer, "\nProduct: %s (%s)\n", product.Code, productName) cli.Printf(a.writer, "Version: %s \n", product.Version) if withApi { cli.PrintfWithColor(a.writer, cli.ColorOff, "\nAvailable Api List: \n") maxNameLen := 0 for _, apiName := range product.ApiNames { if len(apiName) > maxNameLen { maxNameLen = len(apiName) } } for _, apiName := range product.ApiNames { if product.ApiStyle == "restful" { api, _ := a.GetApi(productCode, product.Version, apiName) ptn := fmt.Sprintf(" %%-%ds : %%s %%s\n", maxNameLen+1) cli.PrintfWithColor(a.writer, cli.Green, ptn, apiName, api.Method, api.PathPattern) } else { api, _ := newmeta.GetAPI(i18n.GetLanguage(), productCode, apiName) if api != nil { apiDetail, _ := newmeta.GetAPIDetail(i18n.GetLanguage(), productCode, apiName) // use new api metadata if api.Deprecated { fmt := fmt.Sprintf(" %%-%ds [Deprecated]%%s\n", maxNameLen+1) cli.PrintfWithColor(a.writer, cli.Green, fmt, apiName, api.Summary) } else if apiDetail.IsAnonymousAPI() { fmt := fmt.Sprintf(" %%-%ds [Anonymous]%%s\n", maxNameLen+1) cli.PrintfWithColor(a.writer, cli.Green, fmt, apiName, api.Summary) } else { fmt := fmt.Sprintf(" %%-%ds %%s\n", maxNameLen+1) cli.PrintfWithColor(a.writer, cli.Green, fmt, apiName, api.Summary) } } else { cli.PrintfWithColor(a.writer, cli.Green, " %s\n", apiName) } } } } cli.Printf(a.writer, "\nRun `aliyun %s <ApiName> --help` to get more information about this API\n", product.GetLowerCode()) return nil } func (a *Library) PrintApiUsage(productCode string, apiName string) error { product, ok := a.builtinRepo.GetProduct(productCode) if !ok { return &InvalidProductError{Code: productCode, library: a} } api, ok := a.builtinRepo.GetApi(productCode, product.Version, apiName) if !ok { 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, 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, productName) } cli.Printf(a.writer, "\nParameters:\n") w := tabwriter.NewWriter(a.writer, 8, 0, 1, ' ', 0) 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, detail *newmeta.APIDetail) { sort.Sort(meta.ParameterSlice(params)) for _, param := range params { if param.Hidden { continue } if param.Position == "Domain" { continue } if param.Position == "Header" { continue } if param.Type == "RepeatList" { if len(param.SubParameters) > 0 { printParameters(w, param.SubParameters, prefix+param.Name+".n.", detail) } else { 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\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" } else { return "Optional" } } 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 "" }