Replace manual request creation and marshaling with new client

This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-08-02 12:03:43 -04:00
parent 1b1c2bc1d1
commit fa666db1b8
5 changed files with 84 additions and 279 deletions

View File

@ -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)

View File

@ -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{}

View File

@ -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))

View File

@ -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

View File

@ -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
}