From fa666db1b80e03c9bae2488a28f8219797084272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Mej=C3=ADas=20Rodr=C3=ADguez?= Date: Fri, 2 Aug 2019 12:03:43 -0400 Subject: [PATCH] Replace manual request creation and marshaling with new client --- cmd/login.go | 8 +- cmd/stackDeploy.go | 228 +++++++++++---------------------------------- cmd/stackRemove.go | 21 +---- cmd/status.go | 32 ++----- common/utils.go | 74 +++------------ 5 files changed, 84 insertions(+), 279 deletions(-) diff --git a/cmd/login.go b/cmd/login.go index 8d76db3..e12a31a 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/greenled/portainer-stack-utils/common" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -13,8 +14,11 @@ var loginCmd = &cobra.Command{ Short: "Log in to a Portainer instance", Run: func(cmd *cobra.Command, args []string) { // Get auth token - authToken, authenticationTokenRetrievalError := common.GetNewAuthenticationToken() - common.CheckError(authenticationTokenRetrievalError) + client, err := common.GetClient() + common.CheckError(err) + + authToken, err := client.Authenticate(viper.GetString("url"), viper.GetString("password")) + common.CheckError(err) if viper.GetBool("login.print") { fmt.Println(authToken) diff --git a/cmd/stackDeploy.go b/cmd/stackDeploy.go index 749ccdf..7090be0 100644 --- a/cmd/stackDeploy.go +++ b/cmd/stackDeploy.go @@ -1,17 +1,15 @@ package cmd import ( - "bytes" - "encoding/json" "fmt" + "io/ioutil" + "log" + "net/http" + "github.com/greenled/portainer-stack-utils/common" "github.com/joho/godotenv" "github.com/spf13/cobra" "github.com/spf13/viper" - "io/ioutil" - "log" - "net/http" - "net/url" ) // stackDeployCmd represents the undeploy command @@ -118,7 +116,12 @@ func init() { viper.BindPFlag("stack.deploy.prune", stackDeployCmd.Flags().Lookup("prune")) } -func deploySwarmStack(stackName string, environmentVariables []common.StackEnv, dockerComposeFileContent string, swarmClusterId string) error { +func deploySwarmStack(stackName string, environmentVariables []common.StackEnv, dockerComposeFileContent string, swarmClusterId string) (err error) { + client, err := common.GetClient() + if err != nil { + return + } + reqBody := common.StackCreateRequest{ Name: stackName, Env: environmentVariables, @@ -126,174 +129,67 @@ func deploySwarmStack(stackName string, environmentVariables []common.StackEnv, StackFileContent: dockerComposeFileContent, } - reqBodyBytes, marshalingErr := json.Marshal(reqBody) - if marshalingErr != nil { - return marshalingErr - } + err = client.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 1, "string", viper.GetString("stack.deploy.endpoint")), http.MethodPost, &reqBody, nil) - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/stacks?type=%v&method=%s&endpointId=%s", viper.GetString("url"), 1, "string", viper.GetString("stack.deploy.endpoint"))) - if parsingErr != nil { - return parsingErr - } - - req, newRequestErr := http.NewRequest(http.MethodPost, reqUrl.String(), bytes.NewBuffer(reqBodyBytes)) - if newRequestErr != nil { - return newRequestErr - } - headerErr := common.AddAuthorizationHeader(req) - req.Header.Add("Content-Type", "application/json") - if headerErr != nil { - return headerErr - } - common.PrintDebugRequest("Deploy stack request", req) - - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - if requestExecutionErr != nil { - return requestExecutionErr - } - common.PrintDebugResponse("Deploy stack response", resp) - - responseErr := common.CheckResponseForErrors(resp) - if responseErr != nil { - return responseErr - } - - return nil + return } -func deployComposeStack(stackName string, environmentVariables []common.StackEnv, stackFileContent string) error { +func deployComposeStack(stackName string, environmentVariables []common.StackEnv, stackFileContent string) (err error) { + client, err := common.GetClient() + if err != nil { + return + } + reqBody := common.StackCreateRequest{ Name: stackName, Env: environmentVariables, StackFileContent: stackFileContent, } - reqBodyBytes, marshalingErr := json.Marshal(reqBody) - if marshalingErr != nil { - return marshalingErr - } + err = client.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 2, "string", viper.GetString("stack.deploy.endpoint")), http.MethodPost, &reqBody, nil) - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/stacks?type=%v&method=%s&endpointId=%s", viper.GetString("url"), 2, "string", viper.GetString("stack.deploy.endpoint"))) - if parsingErr != nil { - return parsingErr - } - - req, newRequestErr := http.NewRequest(http.MethodPost, reqUrl.String(), bytes.NewBuffer(reqBodyBytes)) - if newRequestErr != nil { - return newRequestErr - } - headerErr := common.AddAuthorizationHeader(req) - req.Header.Add("Content-Type", "application/json") - if headerErr != nil { - return headerErr - } - common.PrintDebugRequest("Deploy stack request", req) - - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - if requestExecutionErr != nil { - return requestExecutionErr - } - common.PrintDebugResponse("Deploy stack response", resp) - - responseErr := common.CheckResponseForErrors(resp) - if responseErr != nil { - return responseErr - } - - return nil + return } -func updateStack(stack common.Stack, environmentVariables []common.StackEnv, stackFileContent string, prune bool) error { +func updateStack(stack common.Stack, environmentVariables []common.StackEnv, stackFileContent string, prune bool) (err error) { + client, err := common.GetClient() + if err != nil { + return + } + reqBody := common.StackUpdateRequest{ Env: environmentVariables, StackFileContent: stackFileContent, Prune: prune, } - reqBodyBytes, marshalingErr := json.Marshal(reqBody) - if marshalingErr != nil { - return marshalingErr - } + err = client.DoJSON(fmt.Sprintf("stacks/%v?endpointId=%s", stack.Id, viper.GetString("stack.deploy.endpoint")), http.MethodPut, &reqBody, nil) - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/stacks/%v?endpointId=%s", viper.GetString("url"), stack.Id, viper.GetString("stack.deploy.endpoint"))) - if parsingErr != nil { - return parsingErr - } - - req, newRequestErr := http.NewRequest(http.MethodPut, reqUrl.String(), bytes.NewBuffer(reqBodyBytes)) - if newRequestErr != nil { - return newRequestErr - } - headerErr := common.AddAuthorizationHeader(req) - req.Header.Add("Content-Type", "application/json") - if headerErr != nil { - return headerErr - } - common.PrintDebugRequest("Update stack request", req) - - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - if requestExecutionErr != nil { - return requestExecutionErr - } - common.PrintDebugResponse("Update stack response", resp) - - responseErr := common.CheckResponseForErrors(resp) - if responseErr != nil { - return responseErr - } - - return nil + return } -func getSwarmClusterId() (string, error) { +func getSwarmClusterId() (id string, err error) { // Get docker information for endpoint - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/endpoints/%v/docker/info", viper.GetString("url"), viper.GetString("stack.deploy.endpoint"))) - if parsingErr != nil { - return "", parsingErr + client, err := common.GetClient() + if err != nil { + return } - req, newRequestErr := http.NewRequest(http.MethodGet, reqUrl.String(), nil) - if newRequestErr != nil { - return "", newRequestErr - } - headerErr := common.AddAuthorizationHeader(req) - if headerErr != nil { - return "", headerErr - } - common.PrintDebugRequest("Get docker info request", req) + var result map[string]interface{} - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - if requestExecutionErr != nil { - return "", requestExecutionErr - } - common.PrintDebugResponse("Get docker info response", resp) - - responseErr := common.CheckResponseForErrors(resp) - if responseErr != nil { - return "", responseErr + err = client.DoJSON(fmt.Sprintf("endpoints/%v/docker/info", viper.GetString("stack.deploy.endpoint")), http.MethodGet, nil, &result) + if err != nil { + return } // Get swarm (if any) information for endpoint - var result map[string]interface{} - decodingError := json.NewDecoder(resp.Body).Decode(&result) - if decodingError != nil { - return "", decodingError + swarmClusterId, err := selectValue(result, []string{"Swarm", "Cluster", "ID"}) + if err != nil { + return } + id = swarmClusterId.(string) - swarmClusterId, selectionErr := selectValue(result, []string{"Swarm", "Cluster", "ID"}) - if selectionErr != nil { - return "", selectionErr - } - - return swarmClusterId.(string), nil + return } func selectValue(jsonMap map[string]interface{}, jsonPath []string) (interface{}, error) { @@ -333,42 +229,22 @@ func loadEnvironmentVariablesFile(path string) ([]common.StackEnv, error) { return variables, nil } -func getStackFileContent(stackId uint32) (string, error) { - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/stacks/%v/file", viper.GetString("url"), stackId)) - if parsingErr != nil { - return "", parsingErr - } - - req, newRequestErr := http.NewRequest(http.MethodGet, reqUrl.String(), nil) - if newRequestErr != nil { - return "", newRequestErr - } - headerErr := common.AddAuthorizationHeader(req) - if headerErr != nil { - return "", headerErr - } - common.PrintDebugRequest("Get stack file content request", req) - - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - if requestExecutionErr != nil { - return "", requestExecutionErr - } - common.PrintDebugResponse("Get stack file content response", resp) - - responseErr := common.CheckResponseForErrors(resp) - if responseErr != nil { - return "", responseErr +func getStackFileContent(stackId uint32) (content string, err error) { + client, err := common.GetClient() + if err != nil { + return } var respBody common.StackFileInspectResponse - decodingErr := json.NewDecoder(resp.Body).Decode(&respBody) - if decodingErr != nil { - return "", decodingErr + + err = client.DoJSON(fmt.Sprintf("stacks/%v/file", stackId), http.MethodGet, nil, respBody) + if err != nil { + return } - return respBody.StackFileContent, nil + content = respBody.StackFileContent + + return } type valueNotFoundError struct{} diff --git a/cmd/stackRemove.go b/cmd/stackRemove.go index 5d6450d..74d5721 100644 --- a/cmd/stackRemove.go +++ b/cmd/stackRemove.go @@ -2,13 +2,12 @@ package cmd import ( "fmt" - "github.com/greenled/portainer-stack-utils/common" - "github.com/spf13/viper" "log" "net/http" - "net/url" + "github.com/greenled/portainer-stack-utils/common" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // stackRemoveCmd represents the remove command @@ -30,22 +29,12 @@ var stackRemoveCmd = &cobra.Command{ stackId := stack.Id common.PrintVerbose(fmt.Sprintf("Removing stack %s...", stackName)) - reqUrl, err := url.Parse(fmt.Sprintf("%s/api/stacks/%d", viper.GetString("url"), stackId)) + + client, err := common.GetClient() common.CheckError(err) - req, err := http.NewRequest(http.MethodDelete, reqUrl.String(), nil) + err = client.DoJSON(fmt.Sprintf("stacks/%d", stackId), http.MethodDelete, nil, nil) common.CheckError(err) - headerErr := common.AddAuthorizationHeader(req) - common.CheckError(headerErr) - common.PrintDebugRequest("Remove stack request", req) - - client := common.NewHttpClient() - - resp, err := client.Do(req) - common.PrintDebugResponse("Remove stack response", resp) - common.CheckError(err) - - common.CheckError(common.CheckResponseForErrors(resp)) case *common.StackNotFoundError: // The stack does not exist common.PrintVerbose(fmt.Sprintf("Stack %s does not exist.", stackName)) diff --git a/cmd/status.go b/cmd/status.go index 735ed31..7a95c5c 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -1,15 +1,14 @@ package cmd import ( - "encoding/json" "fmt" + "net/http" + "os" + "text/template" + "github.com/greenled/portainer-stack-utils/common" "github.com/spf13/cobra" "github.com/spf13/viper" - "net/http" - "net/url" - "os" - "text/template" ) // statusCmd represents the status command @@ -17,27 +16,12 @@ var statusCmd = &cobra.Command{ Use: "status", Short: "Check Portainer status", Run: func(cmd *cobra.Command, args []string) { - reqUrl, parsingErr := url.Parse(fmt.Sprintf("%s/api/status", viper.GetString("url"))) - common.CheckError(parsingErr) - - req, newRequestErr := http.NewRequest(http.MethodGet, reqUrl.String(), nil) - common.CheckError(newRequestErr) - headerErr := common.AddAuthorizationHeader(req) - common.CheckError(headerErr) - common.PrintDebugRequest("Get status request", req) - - client := common.NewHttpClient() - - resp, requestExecutionErr := client.Do(req) - common.CheckError(requestExecutionErr) - common.PrintDebugResponse("Get status response", resp) - - responseErr := common.CheckResponseForErrors(resp) - common.CheckError(responseErr) + client, err := common.GetClient() + common.CheckError(err) var respBody common.Status - decodingErr := json.NewDecoder(resp.Body).Decode(&respBody) - common.CheckError(decodingErr) + err = client.DoJSON("status", http.MethodGet, nil, &respBody) + common.CheckError(err) if viper.GetString("status.format") != "" { // Print stack fields formatted diff --git a/common/utils.go b/common/utils.go index 8db896a..7a6b87a 100644 --- a/common/utils.go +++ b/common/utils.go @@ -3,51 +3,26 @@ package common import ( "encoding/json" "fmt" - "github.com/spf13/viper" "net/http" - "net/url" ) func GetAllStacks() ([]Stack, error) { return GetAllStacksFiltered(StackListFilter{}) } -func GetAllStacksFiltered(filter StackListFilter) ([]Stack, error) { +func GetAllStacksFiltered(filter StackListFilter) (stacks []Stack, err error) { PrintVerbose("Getting all stacks...") + client, err := GetClient() + if err != nil { + return + } + filterJsonBytes, _ := json.Marshal(filter) filterJsonString := string(filterJsonBytes) - reqUrl, err := url.Parse(fmt.Sprintf("%s/api/stacks?filters=%s", viper.GetString("url"), filterJsonString)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest(http.MethodGet, reqUrl.String(), nil) - if err != nil { - return nil, err - } - headerErr := AddAuthorizationHeader(req) - if headerErr != nil { - return nil, err - } - PrintDebugRequest("Get stacks request", req) - - client := NewHttpClient() - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - PrintDebugResponse("Get stacks response", resp) - - CheckError(CheckResponseForErrors(resp)) - - var respBody []Stack - decodingErr := json.NewDecoder(resp.Body).Decode(&respBody) - CheckError(decodingErr) - - return respBody, nil + err = client.DoJSON(fmt.Sprintf("stacks?filters=%s", filterJsonString), http.MethodGet, nil, &stacks) + return } func GetStackByName(name string) (Stack, error) { @@ -81,37 +56,14 @@ func (e *StackNotFoundError) Error() string { return fmt.Sprintf("Stack %s not found", e.StackName) } -func GetAllEndpoints() ([]EndpointSubset, error) { +func GetAllEndpoints() (endpoints []EndpointSubset, err error) { PrintVerbose("Getting all endpoints...") - reqUrl, err := url.Parse(fmt.Sprintf("%s/api/endpoints", viper.GetString("url"))) + client, err := GetClient() if err != nil { - return nil, err + return } - req, err := http.NewRequest(http.MethodGet, reqUrl.String(), nil) - if err != nil { - return nil, err - } - headerErr := AddAuthorizationHeader(req) - if headerErr != nil { - return nil, err - } - PrintDebugRequest("Get endpoints request", req) - - client := NewHttpClient() - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - PrintDebugResponse("Get endpoints response", resp) - - CheckError(CheckResponseForErrors(resp)) - - var respBody []EndpointSubset - decodingErr := json.NewDecoder(resp.Body).Decode(&respBody) - CheckError(decodingErr) - - return respBody, nil + err = client.DoJSON("endpoints", http.MethodGet, nil, &endpoints) + return }