From 66cf741263752f5bb49bca27c9527a19a05402a2 Mon Sep 17 00:00:00 2001 From: Cristian Ciutea Date: Mon, 11 Jun 2018 17:15:37 +0300 Subject: [PATCH] Added get server group by path (#14) * added get server group by path --- src/coscale/api/api.go | 45 +++++++++++++++++++++++++++------- src/coscale/api/common.go | 8 +++--- src/coscale/api/server.go | 43 ++++++++++++++++++++++++++++++++ src/coscale/command/alert.go | 26 ++++++++++---------- src/coscale/command/check.go | 2 +- src/coscale/command/command.go | 16 ++++++++---- src/coscale/command/common.go | 10 ++++---- src/coscale/command/config.go | 2 +- src/coscale/command/event.go | 10 ++++---- src/coscale/command/metric.go | 10 ++++---- src/coscale/command/server.go | 43 +++++++++++++++++++++++++++++--- 11 files changed, 164 insertions(+), 51 deletions(-) diff --git a/src/coscale/api/api.go b/src/coscale/api/api.go index a2b7f1d..7b7e3f2 100644 --- a/src/coscale/api/api.go +++ b/src/coscale/api/api.go @@ -129,21 +129,25 @@ type Api struct { // AccessToken is a UUID giving access permissions on the application. AccessToken string // AppID is a UUID defining the application. - AppID string - rawOutput bool - token string + AppID string + rawOutput bool + token string + // Set aditional query parameters. + query string validConfig bool + // Print aditional util information. + verbose bool } // NewApi creates a new Api connector using an email and a password. -func NewApi(baseUrl string, accessToken string, appID string, rawOutput bool) *Api { - api := &Api{baseUrl, accessToken, appID, rawOutput, "", true} +func NewApi(baseUrl string, accessToken string, appID string, rawOutput, verbose bool) *Api { + api := &Api{baseUrl, accessToken, appID, rawOutput, "", "", true, verbose} return api } // NewFakeApi creates a new Api connector using an email and a password. func NewFakeApi() *Api { - api := &Api{"", "", "", true, "", false} + api := &Api{"", "", "", true, "", "", false, false} return api } @@ -185,9 +189,21 @@ type RequestErrorResponse struct { // Do an http request. func (api *Api) doHttpRequest(method string, uri string, token string, data map[string][]string, timeout time.Duration) ([]byte, error) { + if method == "GET" && len(api.query) > 0 { + if strings.ContainsAny(uri, "?") { + uri = fmt.Sprintf("%s&%s", uri, api.query) + } else { + uri = fmt.Sprintf("%s?%s", uri, api.query) + } + } requestBody := url.Values(data).Encode() req, err := http.NewRequest(method, uri, strings.NewReader(requestBody)) + // Print the requested url. + if api.verbose { + fmt.Println(method, uri) + } + if err != nil { return nil, err } @@ -236,6 +252,12 @@ func (api *Api) doHttpRequest(method string, uri string, token string, data map[ return body, nil } +// SetQueryString set aditional query parameters only for the next call. +func (api *Api) SetQueryString(query string) { + // URL Encoded. + api.query = query +} + // LoginData contains the required fields for the login API function. type LoginData struct { // Token should contain the AccessToken. @@ -300,22 +322,27 @@ func (api *Api) makeCall(method string, uri string, data map[string][]string, js if err != nil { return err } + return api.HandleResponse(b, jsonOut, target) +} + +// HandleResponse is used the Handle the response from the API. +func (api *Api) HandleResponse(response []byte, jsonOut bool, target interface{}) error { if target != nil { if jsonOut { //if the output will be json, check if we need to format it or no var result string if api.rawOutput { - result = string(b) + result = string(response) } else { var out bytes.Buffer - json.Indent(&out, b, "", " ") + json.Indent(&out, response, "", " ") result = out.String() } if t, ok := target.(*string); ok { *t = result } } else { - return json.Unmarshal(b, target) + return json.Unmarshal(response, target) } } return nil diff --git a/src/coscale/api/common.go b/src/coscale/api/common.go index 09be4ff..3d11ba0 100644 --- a/src/coscale/api/common.go +++ b/src/coscale/api/common.go @@ -63,8 +63,8 @@ func (api *Api) GetObjectByName(objectName string, name string) (string, error) return result, nil } -// GetObejctRefByName will put in result a reference to the oject specified by objectName and name -func (api *Api) GetObejctRefByName(objectName string, name string, result Object) error { +// GetObjectRefByName will put in result a reference to the oject specified by objectName and name +func (api *Api) GetObjectRefByName(objectName string, name string, result Object) error { // URL Encoded. name = url.QueryEscape(name) @@ -79,8 +79,8 @@ func (api *Api) GetObejctRefByName(objectName string, name string, result Object return nil } -// GetObejctRefByNameFromGroup will return the object specified by objectName from objectGroup that have a certain name -func (api *Api) GetObejctRefByNameFromGroup(objectGroup, objectName string, groupID int64, name string, result Object) error { +// GetObjectRefByNameFromGroup will return the object specified by objectName from objectGroup that have a certain name +func (api *Api) GetObjectRefByNameFromGroup(objectGroup, objectName string, groupID int64, name string, result Object) error { // URL Encoded. name = url.QueryEscape(name) diff --git a/src/coscale/api/server.go b/src/coscale/api/server.go index d64bb78..2747ee8 100644 --- a/src/coscale/api/server.go +++ b/src/coscale/api/server.go @@ -3,6 +3,7 @@ package api import ( "fmt" "strconv" + "strings" ) // Server describes the server object on the API. @@ -83,6 +84,48 @@ func (api *Api) UpdateServer(server *Server) (string, error) { return api.GetObject("server", server.ID) } +// GetServerGroupByPath returns a server group by the hierarchy. +func (api *Api) GetServerGroupByPath(path string) (string, error) { + + var serverGroup *ServerGroup + + groupNames := strings.Split(path, "/") + for i, groupName := range groupNames { + + var query string + + if i == 0 { + query = "selectByRoot=true" + } else if serverGroup != nil && serverGroup.ID > 0 { + query = fmt.Sprintf("selectByParent_id=%d", serverGroup.ID) + } else { + return "[]", nil + } + + api.SetQueryString(query) + result, err := api.GetObjectByName("servergroup", groupName) + if err != nil { + return "", err + } + // For the last group just return it. + if i == len(groupNames)-1 { + return result, nil + } + + tmp := make([]*ServerGroup, 1) + err = api.HandleResponse([]byte(result), false, &tmp) + if err != nil { + return "", err + } + if len(tmp) != 1 { + return "[]", nil + } + serverGroup = tmp[0] + } + + return "[]", nil +} + // CreateServerGroup creates a new ServerGroup using the API. func (api *Api) CreateServerGroup(name, description, Type, state string, parentID int64) (string, error) { data := map[string][]string{ diff --git a/src/coscale/command/alert.go b/src/coscale/command/alert.go index 10f475f..028101b 100644 --- a/src/coscale/command/alert.go +++ b/src/coscale/command/alert.go @@ -265,7 +265,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRef("alerttype", id, alertTypeObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("alerttype", name, alertTypeObj) + err = cmd.Capi.GetObjectRefByName("alerttype", name, alertTypeObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -357,7 +357,7 @@ Mandatory: if id != -1 { cmd.PrintResult(cmd.Capi.GetTriggers(id)) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("alerttype", name, alertTypeObj) + err = cmd.Capi.GetObjectRefByName("alerttype", name, alertTypeObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -449,7 +449,7 @@ Optional: var metricObj = &api.Metric{} var err error if metricID == -1 { - err = cmd.Capi.GetObejctRefByName("metric", metric, metricObj) + err = cmd.Capi.GetObjectRefByName("metric", metric, metricObj) if err != nil { cmd.PrintResult("", err) } @@ -460,7 +460,7 @@ Optional: // Get the server id var serverObj = &api.Server{} if serverID == -1 && server != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("server", server, serverObj) + err = cmd.Capi.GetObjectRefByName("server", server, serverObj) if err != nil { cmd.PrintResult("", err) } @@ -471,7 +471,7 @@ Optional: // Get the servergroup id var serverGroupObj = &api.ServerGroup{} if serverGroupID == -1 && serverGroup != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("servergroup", serverGroup, serverGroupObj) + err = cmd.Capi.GetObjectRefByName("servergroup", serverGroup, serverGroupObj) if err != nil { cmd.PrintResult("", err) } @@ -485,7 +485,7 @@ Optional: // get the alert type for the trigger var alertTypeObj = &api.AlertType{} if typeID == -1 { - err = cmd.Capi.GetObejctRefByName("alerttype", typeName, alertTypeObj) + err = cmd.Capi.GetObjectRefByName("alerttype", typeName, alertTypeObj) if err != nil { cmd.PrintResult("", err) } @@ -580,7 +580,7 @@ Optional: var metricObj = &api.Metric{} var err error if metricID == -1 && metric != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("metric", metric, metricObj) + err = cmd.Capi.GetObjectRefByName("metric", metric, metricObj) if err != nil { cmd.PrintResult("", err) } @@ -591,7 +591,7 @@ Optional: // Get the server id var serverObj = &api.Server{} if serverID == -1 && server != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("server", server, serverObj) + err = cmd.Capi.GetObjectRefByName("server", server, serverObj) if err != nil { cmd.PrintResult("", err) } @@ -602,7 +602,7 @@ Optional: // Get the servergroup id var serverGroupObj = &api.ServerGroup{} if serverGroupID == -1 && serverGroup != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("servergroup", serverGroup, serverGroupObj) + err = cmd.Capi.GetObjectRefByName("servergroup", serverGroup, serverGroupObj) if err != nil { cmd.PrintResult("", err) } @@ -613,7 +613,7 @@ Optional: // get the alert type for the trigger var alertTypeObj = &api.AlertType{} if typeID == -1 { - err = cmd.Capi.GetObejctRefByName("alerttype", typeName, alertTypeObj) + err = cmd.Capi.GetObjectRefByName("alerttype", typeName, alertTypeObj) if err != nil { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -627,7 +627,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRefFromGroup("alerttype", "trigger", typeID, id, alertTriggerObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByNameFromGroup("alerttype", "trigger", typeID, name, alertTriggerObj) + err = cmd.Capi.GetObjectRefByNameFromGroup("alerttype", "trigger", typeID, name, alertTriggerObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -713,7 +713,7 @@ Mandatory: // get the alert type for the trigger var alertTypeObj = &api.AlertType{} if typeID == -1 { - err = cmd.Capi.GetObejctRefByName("alerttype", Type, alertTypeObj) + err = cmd.Capi.GetObjectRefByName("alerttype", Type, alertTypeObj) if err != nil { cmd.PrintResult("", err) } @@ -724,7 +724,7 @@ Mandatory: // Get the existing trigger. var alertTriggerObj = &api.AlertTrigger{} if id == -1 { - err = cmd.Capi.GetObejctRefByNameFromGroup("alerttype", "trigger", typeID, name, alertTriggerObj) + err = cmd.Capi.GetObjectRefByNameFromGroup("alerttype", "trigger", typeID, name, alertTriggerObj) if err != nil { cmd.PrintResult("", err) } diff --git a/src/coscale/command/check.go b/src/coscale/command/check.go index aebf810..cbd65ff 100644 --- a/src/coscale/command/check.go +++ b/src/coscale/command/check.go @@ -28,7 +28,7 @@ var CheckObject = &Command{ cmd.PrintResult("", err) } // check if we can loggin with this configuration - api := api.NewApi(config.BaseUrl, config.AccessToken, config.AppId, false) + api := api.NewApi(config.BaseUrl, config.AccessToken, config.AppId, false, false) err = api.Login() if err != nil { cmd.PrintResult("", err) diff --git a/src/coscale/command/command.go b/src/coscale/command/command.go index d5f28b1..4a90cd8 100644 --- a/src/coscale/command/command.go +++ b/src/coscale/command/command.go @@ -131,7 +131,7 @@ func (c *Command) PrintFullUsage() { } // GetApi returns a Api object -func (c *Command) GetApi(baseUrl, accessToken, appId string, rawOutput bool) *api.Api { +func (c *Command) GetApi(baseUrl, accessToken, appId string, rawOutput, verbose bool) *api.Api { if accessToken == "" || appId == "" { configPath, err := GetConfigPath() if err != nil { @@ -145,25 +145,27 @@ func (c *Command) GetApi(baseUrl, accessToken, appId string, rawOutput bool) *ap accessToken = config.AccessToken appId = config.AppId } - return api.NewApi(baseUrl, accessToken, appId, rawOutput) + return api.NewApi(baseUrl, accessToken, appId, rawOutput, verbose) } // ParseArgs takes the API configuration from the args and stores them in the Command. func (c *Command) ParseArgs(args []string) { //add the flags for the api configuration var baseUrl, accessToken, appId string - var rawOutput bool + var rawOutput, verbose bool c.Flag.StringVar(&baseUrl, "api-url", "https://api.coscale.com", "Base url for the api.") c.Flag.StringVar(&appId, "app-id", "", "The application id.") c.Flag.StringVar(&accessToken, "access-token", "", "A valid access token for the given application.") c.Flag.BoolVar(&rawOutput, "rawOutput", false, "The returned json objects are returned formatted by default.") + c.Flag.BoolVar(&verbose, "verbose", false, "Print the URLs of the API calls.") + c.Flag.Parse(args) unknownArgs := c.Flag.Args() if len(unknownArgs) > 0 && unknownArgs[0] != "help" { fmt.Fprintf(os.Stderr, "Unknown field %s\n", unknownArgs[0]) os.Exit(EXIT_FLAG_ERROR) } - c.Capi = c.GetApi(strings.Trim(baseUrl, "/"), accessToken, appId, rawOutput) + c.Capi = c.GetApi(strings.Trim(baseUrl, "/"), accessToken, appId, rawOutput, verbose) } // PrintResult formats the result or error and exits the process with the appropriate exit code. @@ -206,6 +208,10 @@ the credentials can also be provided on the command line using: The application id. --access-token A valid access token for the given application. + + + --verbose + Print the URLs of the API calls. ` var usageTemplate = `coscale-cli a tool for CoScale Api. @@ -213,7 +219,7 @@ var usageTemplate = `coscale-cli a tool for CoScale Api. Usage: {{.UsageLine}} {{if .Runnable}} -{{.Name | printf "Action \"%s\" usage:"}} +{{.Name | printf "Action \"%s\" usage:"}} {{.Long | trim}}{{else}} {{.Name | printf "Actions for command \"%s\":"}} diff --git a/src/coscale/command/common.go b/src/coscale/command/common.go index 45cb65c..f6e0435 100644 --- a/src/coscale/command/common.go +++ b/src/coscale/command/common.go @@ -100,7 +100,7 @@ Only one of them is necessary to be specified if id != -1 { err = cmd.Capi.GetObjectRef(objectName, id, object) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName(objectName, name, object) + err = cmd.Capi.GetObjectRefByName(objectName, name, object) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -149,7 +149,7 @@ Mandatory: if idObject != -1 { err = cmd.Capi.GetObjectRef(objectName, idObject, object) } else if nameObject != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName(objectName, nameObject, object) + err = cmd.Capi.GetObjectRefByName(objectName, nameObject, object) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -162,7 +162,7 @@ Mandatory: if idGroup != -1 { err = cmd.Capi.GetObjectRef(objectGroupName, idGroup, group) } else if nameObject != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName(objectGroupName, nameGroup, group) + err = cmd.Capi.GetObjectRefByName(objectGroupName, nameGroup, group) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -211,7 +211,7 @@ Mandatory: if idObject != -1 { err = cmd.Capi.GetObjectRef(objectName, idObject, object) } else if nameObject != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName(objectName, nameObject, object) + err = cmd.Capi.GetObjectRefByName(objectName, nameObject, object) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -224,7 +224,7 @@ Mandatory: if idGroup != -1 { err = cmd.Capi.GetObjectRef(objectGroupName, idGroup, group) } else if nameObject != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName(objectGroupName, nameGroup, group) + err = cmd.Capi.GetObjectRefByName(objectGroupName, nameGroup, group) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) diff --git a/src/coscale/command/config.go b/src/coscale/command/config.go index c63523d..627350c 100644 --- a/src/coscale/command/config.go +++ b/src/coscale/command/config.go @@ -36,7 +36,7 @@ Check the CLI configuration. os.Exit(EXIT_SUCCESS_ERROR) } // check if we can loggin with this configuration - api := api.NewApi(config.BaseUrl, config.AccessToken, config.AppId, false) + api := api.NewApi(config.BaseUrl, config.AccessToken, config.AppId, false, false) err = api.Login() if err != nil { fmt.Fprintln(os.Stderr, "Api authentication failed") diff --git a/src/coscale/command/event.go b/src/coscale/command/event.go index 9a1970c..dc64de3 100644 --- a/src/coscale/command/event.go +++ b/src/coscale/command/event.go @@ -83,7 +83,7 @@ The name or id should be specified if id != -1 { err = cmd.Capi.GetObjectRef("event", id, eventObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("event", name, eventObj) + err = cmd.Capi.GetObjectRefByName("event", name, eventObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -141,7 +141,7 @@ The name or id should be specified if id != -1 { err = cmd.Capi.GetObjectRef("event", id, eventObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("event", name, eventObj) + err = cmd.Capi.GetObjectRefByName("event", name, eventObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -182,7 +182,7 @@ Please use 'event newdata' instead. if id != -1 { err = cmd.Capi.GetObjectRef("event", id, eventObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("event", name, eventObj) + err = cmd.Capi.GetObjectRefByName("event", name, eventObj) } else { flagErr = true } @@ -245,7 +245,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRef("event", id, eventObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("event", name, eventObj) + err = cmd.Capi.GetObjectRefByName("event", name, eventObj) } else { flagErr = true } @@ -311,7 +311,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRef("event", id, eventObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("event", name, eventObj) + err = cmd.Capi.GetObjectRefByName("event", name, eventObj) } else { flagErr = true } diff --git a/src/coscale/command/metric.go b/src/coscale/command/metric.go index bd4eff8..538df3f 100644 --- a/src/coscale/command/metric.go +++ b/src/coscale/command/metric.go @@ -53,7 +53,7 @@ Mandatory: if id != -1 { err = cmd.Capi.GetObjectRef("metricgroup", id, metricGroupObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("metricgroup", name, metricGroupObj) + err = cmd.Capi.GetObjectRefByName("metricgroup", name, metricGroupObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -160,7 +160,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRef("metric", id, metricObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("metric", name, metricObj) + err = cmd.Capi.GetObjectRefByName("metric", name, metricObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -280,7 +280,7 @@ Optional: if id != -1 { err = cmd.Capi.GetObjectRef("metricgroup", id, metricGroupObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("metricgroup", name, metricGroupObj) + err = cmd.Capi.GetObjectRefByName("metricgroup", name, metricGroupObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -367,7 +367,7 @@ Optional: // Get the metric. if id == -1 && metric != DEFAULT_STRING_FLAG_VALUE { var metricObj = &api.Metric{} - err = cmd.Capi.GetObejctRefByName("metric", metric, metricObj) + err = cmd.Capi.GetObjectRefByName("metric", metric, metricObj) if err != nil { cmd.PrintResult("", err) } @@ -412,7 +412,7 @@ or if metricID != -1 { err = cmd.Capi.GetObjectRef("metric", metricID, metricObj) } else if metric != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("metric", metric, metricObj) + err = cmd.Capi.GetObjectRefByName("metric", metric, metricObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) diff --git a/src/coscale/command/server.go b/src/coscale/command/server.go index 2db14c3..b27b84b 100644 --- a/src/coscale/command/server.go +++ b/src/coscale/command/server.go @@ -82,7 +82,7 @@ The name or id should be specified if id != -1 { err = cmd.Capi.GetObjectRef("server", id, serverObj) } else if name != DEFAULT_STRING_FLAG_VALUE { - err = cmd.Capi.GetObejctRefByName("server", name, serverObj) + err = cmd.Capi.GetObjectRefByName("server", name, serverObj) } else { cmd.PrintUsage() os.Exit(EXIT_FLAG_ERROR) @@ -116,7 +116,44 @@ var ServerGroupObject = NewCommand("servergroup", "servergroup [--