Move URL handling logic (calls to DoJson) into Client

This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-08-02 13:10:59 -04:00
parent 7f048def9c
commit 70621c750c
7 changed files with 134 additions and 125 deletions

View File

@ -18,11 +18,12 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/greenled/portainer-stack-utils/common"
"github.com/spf13/viper"
"os" "os"
"text/template" "text/template"
"github.com/greenled/portainer-stack-utils/common"
"github.com/spf13/viper"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -32,7 +33,10 @@ var endpointListCmd = &cobra.Command{
Short: "List endpoints", Short: "List endpoints",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
endpoints, err := common.GetAllEndpoints() client, err := common.GetClient()
common.CheckError(err)
endpoints, err := client.GetEndpoints()
common.CheckError(err) common.CheckError(err)
if viper.GetString("endpoint.list.format") != "" { if viper.GetString("endpoint.list.format") != "" {

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http"
"github.com/greenled/portainer-stack-utils/common" "github.com/greenled/portainer-stack-utils/common"
"github.com/joho/godotenv" "github.com/joho/godotenv"
@ -27,6 +26,9 @@ var stackDeployCmd = &cobra.Command{
common.CheckError(loadingErr) common.CheckError(loadingErr)
} }
client, clientRetrievalErr := common.GetClient()
common.CheckError(clientRetrievalErr)
stackName := args[0] stackName := args[0]
retrievedStack, stackRetrievalErr := common.GetStackByName(stackName) retrievedStack, stackRetrievalErr := common.GetStackByName(stackName)
switch stackRetrievalErr.(type) { switch stackRetrievalErr.(type) {
@ -41,7 +43,7 @@ var stackDeployCmd = &cobra.Command{
common.CheckError(loadingErr) common.CheckError(loadingErr)
} else { } else {
var stackFileContentRetrievalErr error var stackFileContentRetrievalErr error
stackFileContent, stackFileContentRetrievalErr = getStackFileContent(retrievedStack.Id) stackFileContent, stackFileContentRetrievalErr = client.GetStackFileContent(retrievedStack.Id)
common.CheckError(stackFileContentRetrievalErr) common.CheckError(stackFileContentRetrievalErr)
} }
@ -66,8 +68,8 @@ var stackDeployCmd = &cobra.Command{
} }
} }
updateErr := updateStack(retrievedStack, newEnvironmentVariables, stackFileContent, viper.GetBool("stack.deploy.prune")) err := client.UpdateStack(retrievedStack, newEnvironmentVariables, stackFileContent, viper.GetBool("stack.deploy.prune"), viper.GetString("stack.deploy.endpoint"))
common.CheckError(updateErr) common.CheckError(err)
case *common.StackNotFoundError: case *common.StackNotFoundError:
// We are deploying a new stack // We are deploying a new stack
common.PrintVerbose(fmt.Sprintf("Stack %s not found. Deploying...", stackName)) common.PrintVerbose(fmt.Sprintf("Stack %s not found. Deploying...", stackName))
@ -83,12 +85,12 @@ var stackDeployCmd = &cobra.Command{
case nil: case nil:
// It's a swarm cluster // It's a swarm cluster
common.PrintVerbose(fmt.Sprintf("Swarm cluster found with id %s", swarmClusterId)) common.PrintVerbose(fmt.Sprintf("Swarm cluster found with id %s", swarmClusterId))
deploymentErr := deploySwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, swarmClusterId) deploymentErr := client.CreateSwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, swarmClusterId, viper.GetString("stack.deploy.endpoint"))
common.CheckError(deploymentErr) common.CheckError(deploymentErr)
case *valueNotFoundError: case *valueNotFoundError:
// It's not a swarm cluster // It's not a swarm cluster
common.PrintVerbose("Swarm cluster not found") common.PrintVerbose("Swarm cluster not found")
deploymentErr := deployComposeStack(stackName, loadedEnvironmentVariables, stackFileContent) deploymentErr := client.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, viper.GetString("stack.deploy.endpoint"))
common.CheckError(deploymentErr) common.CheckError(deploymentErr)
default: default:
// Something else happened // Something else happened
@ -116,58 +118,6 @@ func init() {
viper.BindPFlag("stack.deploy.prune", stackDeployCmd.Flags().Lookup("prune")) viper.BindPFlag("stack.deploy.prune", stackDeployCmd.Flags().Lookup("prune"))
} }
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,
SwarmID: swarmClusterId,
StackFileContent: dockerComposeFileContent,
}
err = client.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 1, "string", viper.GetString("stack.deploy.endpoint")), http.MethodPost, &reqBody, nil)
return
}
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,
}
err = client.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 2, "string", viper.GetString("stack.deploy.endpoint")), http.MethodPost, &reqBody, nil)
return
}
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,
}
err = client.DoJSON(fmt.Sprintf("stacks/%v?endpointId=%s", stack.Id, viper.GetString("stack.deploy.endpoint")), http.MethodPut, &reqBody, nil)
return
}
func getSwarmClusterId() (id string, err error) { func getSwarmClusterId() (id string, err error) {
// Get docker information for endpoint // Get docker information for endpoint
client, err := common.GetClient() client, err := common.GetClient()
@ -175,9 +125,7 @@ func getSwarmClusterId() (id string, err error) {
return return
} }
var result map[string]interface{} result, err := client.GetEndpointDockerInfo(viper.GetString("stack.deploy.endpoint"))
err = client.DoJSON(fmt.Sprintf("endpoints/%v/docker/info", viper.GetString("stack.deploy.endpoint")), http.MethodGet, nil, &result)
if err != nil { if err != nil {
return return
} }
@ -229,24 +177,6 @@ func loadEnvironmentVariablesFile(path string) ([]common.StackEnv, error) {
return variables, nil return variables, nil
} }
func getStackFileContent(stackId uint32) (content string, err error) {
client, err := common.GetClient()
if err != nil {
return
}
var respBody common.StackFileInspectResponse
err = client.DoJSON(fmt.Sprintf("stacks/%v/file", stackId), http.MethodGet, nil, respBody)
if err != nil {
return
}
content = respBody.StackFileContent
return
}
type valueNotFoundError struct{} type valueNotFoundError struct{}
func (e *valueNotFoundError) Error() string { func (e *valueNotFoundError) Error() string {

View File

@ -2,11 +2,12 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"text/template"
"github.com/greenled/portainer-stack-utils/common" "github.com/greenled/portainer-stack-utils/common"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"os"
"text/template"
) )
// stackListCmd represents the remove command // stackListCmd represents the remove command
@ -16,10 +17,10 @@ var stackListCmd = &cobra.Command{
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Example: "psu stack list --endpoint 1", Example: "psu stack list --endpoint 1",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
stacks, err := common.GetAllStacksFiltered(common.StackListFilter{ client, err := common.GetClient()
SwarmId: viper.GetString("stack.list.swarm"), common.CheckError(err)
EndpointId: viper.GetUint32("stack.list.endpoint"),
}) stacks, err := client.GetStacks(viper.GetString("stack.list.swarm"), viper.GetUint32("stack.list.endpoint"))
common.CheckError(err) common.CheckError(err)
if viper.GetBool("stack.list.quiet") { if viper.GetBool("stack.list.quiet") {

View File

@ -3,7 +3,6 @@ package cmd
import ( import (
"fmt" "fmt"
"log" "log"
"net/http"
"github.com/greenled/portainer-stack-utils/common" "github.com/greenled/portainer-stack-utils/common"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -33,7 +32,7 @@ var stackRemoveCmd = &cobra.Command{
client, err := common.GetClient() client, err := common.GetClient()
common.CheckError(err) common.CheckError(err)
err = client.DoJSON(fmt.Sprintf("stacks/%d", stackId), http.MethodDelete, nil, nil) err = client.DeleteStack(stackId)
common.CheckError(err) common.CheckError(err)
case *common.StackNotFoundError: case *common.StackNotFoundError:
// The stack does not exist // The stack does not exist

View File

@ -2,7 +2,6 @@ package cmd
import ( import (
"fmt" "fmt"
"net/http"
"os" "os"
"text/template" "text/template"
@ -19,8 +18,7 @@ var statusCmd = &cobra.Command{
client, err := common.GetClient() client, err := common.GetClient()
common.CheckError(err) common.CheckError(err)
var respBody common.Status respBody, err := client.GetStatus()
err = client.DoJSON("status", http.MethodGet, nil, &respBody)
common.CheckError(err) common.CheckError(err)
if viper.GetString("status.format") != "" { if viper.GetString("status.format") != "" {

View File

@ -130,6 +130,110 @@ func (n *PortainerClient) Authenticate(user, password string) (token string, err
return return
} }
// Get endpoints
func (n *PortainerClient) GetEndpoints() (endpoints []EndpointSubset, err error) {
PrintVerbose("Getting endpoints...")
err = n.DoJSON("endpoints", http.MethodGet, nil, &endpoints)
return
}
// Get stacks, optionally filtered by swarmId and endpointId
func (n *PortainerClient) GetStacks(swarmId string, endpointId uint32) (stacks []Stack, err error) {
PrintVerbose("Getting stacks...")
filter := StackListFilter{
SwarmId: swarmId,
EndpointId: endpointId,
}
filterJsonBytes, _ := json.Marshal(filter)
filterJsonString := string(filterJsonBytes)
err = n.DoJSON(fmt.Sprintf("stacks?filters=%s", filterJsonString), http.MethodGet, nil, &stacks)
return
}
// Create swarm stack
func (n *PortainerClient) CreateSwarmStack(stackName string, environmentVariables []StackEnv, stackFileContent string, swarmClusterId string, endpointId string) (err error) {
PrintVerbose("Deploying stack...")
reqBody := StackCreateRequest{
Name: stackName,
Env: environmentVariables,
SwarmID: swarmClusterId,
StackFileContent: stackFileContent,
}
err = n.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 1, "string", endpointId), http.MethodPost, &reqBody, nil)
return
}
// Create compose stack
func (n *PortainerClient) CreateComposeStack(stackName string, environmentVariables []StackEnv, stackFileContent string, endpointId string) (err error) {
PrintVerbose("Deploying stack...")
reqBody := StackCreateRequest{
Name: stackName,
Env: environmentVariables,
StackFileContent: stackFileContent,
}
err = n.DoJSON(fmt.Sprintf("stacks?type=%v&method=%s&endpointId=%s", 2, "string", endpointId), http.MethodPost, &reqBody, nil)
return
}
// Update stack
func (n *PortainerClient) UpdateStack(stack Stack, environmentVariables []StackEnv, stackFileContent string, prune bool, endpointId string) (err error) {
PrintVerbose("Updating stack...")
reqBody := StackUpdateRequest{
Env: environmentVariables,
StackFileContent: stackFileContent,
Prune: prune,
}
err = n.DoJSON(fmt.Sprintf("stacks/%v?endpointId=%s", stack.Id, endpointId), http.MethodPut, &reqBody, nil)
return
}
// Delete stack
func (n *PortainerClient) DeleteStack(stackId uint32) (err error) {
PrintVerbose("Deleting stack...")
err = n.DoJSON(fmt.Sprintf("stacks/%d", stackId), http.MethodDelete, nil, nil)
return
}
// Get stack file content
func (n *PortainerClient) GetStackFileContent(stackId uint32) (content string, err error) {
PrintVerbose("Getting stack file content...")
var respBody StackFileInspectResponse
err = n.DoJSON(fmt.Sprintf("stacks/%v/file", stackId), http.MethodGet, nil, &respBody)
if err != nil {
return
}
content = respBody.StackFileContent
return
}
// Get endpoint Docker info
func (n *PortainerClient) GetEndpointDockerInfo(endpointId string) (info map[string]interface{}, err error) {
PrintVerbose("Getting endpoint Docker info...")
err = n.DoJSON(fmt.Sprintf("endpoints/%v/docker/info", endpointId), http.MethodGet, nil, &info)
return
}
// Get Portainer status info
func (n *PortainerClient) GetStatus() (status Status, err error) {
err = n.DoJSON("status", http.MethodGet, nil, &status)
return
}
type clientConfig struct { type clientConfig struct {
Url string Url string
User string User string

View File

@ -1,34 +1,18 @@
package common package common
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http"
) )
func GetAllStacks() ([]Stack, error) { func GetStackByName(name string) (stack Stack, err error) {
return GetAllStacksFiltered(StackListFilter{})
}
func GetAllStacksFiltered(filter StackListFilter) (stacks []Stack, err error) {
PrintVerbose("Getting all stacks...")
client, err := GetClient() client, err := GetClient()
if err != nil { if err != nil {
return return
} }
filterJsonBytes, _ := json.Marshal(filter) stacks, err := client.GetStacks("", 0)
filterJsonString := string(filterJsonBytes)
err = client.DoJSON(fmt.Sprintf("stacks?filters=%s", filterJsonString), http.MethodGet, nil, &stacks)
return
}
func GetStackByName(name string) (Stack, error) {
stacks, err := GetAllStacks()
if err != nil { if err != nil {
return Stack{}, err return
} }
PrintVerbose(fmt.Sprintf("Getting stack %s...", name)) PrintVerbose(fmt.Sprintf("Getting stack %s...", name))
@ -37,9 +21,10 @@ func GetStackByName(name string) (Stack, error) {
return stack, nil return stack, nil
} }
} }
return Stack{}, &StackNotFoundError{ err = &StackNotFoundError{
StackName: name, StackName: name,
} }
return
} }
type StackListFilter struct { type StackListFilter struct {
@ -55,15 +40,3 @@ type StackNotFoundError struct {
func (e *StackNotFoundError) Error() string { func (e *StackNotFoundError) Error() string {
return fmt.Sprintf("Stack %s not found", e.StackName) return fmt.Sprintf("Stack %s not found", e.StackName)
} }
func GetAllEndpoints() (endpoints []EndpointSubset, err error) {
PrintVerbose("Getting all endpoints...")
client, err := GetClient()
if err != nil {
return
}
err = client.DoJSON("endpoints", http.MethodGet, nil, &endpoints)
return
}