Change endpoint selection strategy from ID to Name

This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-08-15 22:43:51 -04:00
parent 6c4ecb1c90
commit 5b4f344247
3 changed files with 75 additions and 55 deletions

View File

@ -32,22 +32,28 @@ var stackDeployCmd = &cobra.Command{
common.CheckError(clientRetrievalErr) common.CheckError(clientRetrievalErr)
stackName := args[0] stackName := args[0]
endpointId := portainer.EndpointID(viper.GetInt("stack.deploy.endpoint"))
// Guess EndpointID if not set var endpoint portainer.Endpoint
if endpointId == 0 { if endpointName := viper.GetString("stack.deploy.endpoint"); endpointName == "" {
// Guess endpoint if not set
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"implications": "Command will fail if there is not exactly one endpoint available", "implications": "Command will fail if there is not exactly one endpoint available",
}).Warning("Endpoint ID not set") }).Warning("Endpoint not set")
endpoint, err := common.GetDefaultEndpoint() var endpointRetrievalErr error
common.CheckError(err) endpoint, endpointRetrievalErr = common.GetDefaultEndpoint()
endpointId = endpoint.ID common.CheckError(endpointRetrievalErr)
endpointName = endpoint.Name
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"endpoint": endpointId, "endpoint": endpointName,
}).Debug("Using the only available endpoint") }).Debug("Using the only available endpoint")
} else {
// Get endpoint by name
var endpointRetrievalErr error
endpoint, endpointRetrievalErr = common.GetEndpointByName(endpointName)
common.CheckError(endpointRetrievalErr)
} }
endpointSwarmClusterId, selectionErr := common.GetEndpointSwarmClusterId(endpointId) endpointSwarmClusterId, selectionErr := common.GetEndpointSwarmClusterId(endpoint.ID)
if selectionErr == nil { if selectionErr == nil {
// It's a swarm cluster // It's a swarm cluster
} else if selectionErr == common.ErrStackClusterNotFound { } else if selectionErr == common.ErrStackClusterNotFound {
@ -59,9 +65,9 @@ var stackDeployCmd = &cobra.Command{
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Getting stack") }).Debug("Getting stack")
retrievedStack, stackRetrievalErr := common.GetStackByName(stackName, endpointSwarmClusterId, endpointId) retrievedStack, stackRetrievalErr := common.GetStackByName(stackName, endpointSwarmClusterId, endpoint.ID)
if stackRetrievalErr == nil { if stackRetrievalErr == nil {
// We are updating an existing stack // We are updating an existing stack
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
@ -106,7 +112,7 @@ var stackDeployCmd = &cobra.Command{
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": retrievedStack.Name, "stack": retrievedStack.Name,
}).Info("Updating stack") }).Info("Updating stack")
err := portainerClient.UpdateStack(retrievedStack, newEnvironmentVariables, stackFileContent, viper.GetBool("stack.deploy.prune"), endpointId) err := portainerClient.UpdateStack(retrievedStack, newEnvironmentVariables, stackFileContent, viper.GetBool("stack.deploy.prune"), endpoint.ID)
common.CheckError(err) common.CheckError(err)
} else if stackRetrievalErr == common.ErrStackNotFound { } else if stackRetrievalErr == common.ErrStackNotFound {
// We are deploying a new stack // We are deploying a new stack
@ -124,26 +130,26 @@ var stackDeployCmd = &cobra.Command{
// It's a swarm cluster // It's a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Info("Creating stack") }).Info("Creating stack")
stack, deploymentErr := portainerClient.CreateSwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, endpointSwarmClusterId, endpointId) stack, deploymentErr := portainerClient.CreateSwarmStack(stackName, loadedEnvironmentVariables, stackFileContent, endpointSwarmClusterId, endpoint.ID)
common.CheckError(deploymentErr) common.CheckError(deploymentErr)
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stack.Name, "stack": stack.Name,
"endpoint": stack.EndpointID, "endpoint": endpoint.Name,
"id": stack.ID, "id": stack.ID,
}).Info("Stack created") }).Info("Stack created")
} else { } else {
// It's not a swarm cluster // It's not a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Info("Creating stack") }).Info("Creating stack")
stack, deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, endpointId) stack, deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, endpoint.ID)
common.CheckError(deploymentErr) common.CheckError(deploymentErr)
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stack.Name, "stack": stack.Name,
"endpoint": stack.EndpointID, "endpoint": endpoint.Name,
"id": stack.ID, "id": stack.ID,
}).Info("Stack created") }).Info("Stack created")
} }
@ -158,7 +164,7 @@ func init() {
stackCmd.AddCommand(stackDeployCmd) stackCmd.AddCommand(stackDeployCmd)
stackDeployCmd.Flags().StringP("stack-file", "c", "", "Path to a file with the content of the stack.") stackDeployCmd.Flags().StringP("stack-file", "c", "", "Path to a file with the content of the stack.")
stackDeployCmd.Flags().Int("endpoint", 0, "Endpoint ID.") stackDeployCmd.Flags().String("endpoint", "", "Endpoint name.")
stackDeployCmd.Flags().StringP("env-file", "e", "", "Path to a file with environment variables used during stack deployment.") stackDeployCmd.Flags().StringP("env-file", "e", "", "Path to a file with environment variables used during stack deployment.")
stackDeployCmd.Flags().Bool("replace-env", false, "Replace environment variables instead of merging them.") stackDeployCmd.Flags().Bool("replace-env", false, "Replace environment variables instead of merging them.")
stackDeployCmd.Flags().BoolP("prune", "r", false, "Prune services that are no longer referenced (only available for Swarm stacks).") stackDeployCmd.Flags().BoolP("prune", "r", false, "Prune services that are no longer referenced (only available for Swarm stacks).")

View File

@ -21,37 +21,43 @@ var stackListCmd = &cobra.Command{
Use: "list", Use: "list",
Short: "List stacks", Short: "List stacks",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Example: ` Print stacks in endpoint with ID=1 in a table format: Example: ` Print stacks in endpoint with name=primary in a table format:
psu stack ls --endpoint 1 psu stack ls --endpoint primary
Print names of stacks in endpoint with ID=1: Print names of stacks in endpoint with name=primary:
psu stack ls --endpoint 1 --format "{{ .Name }}" psu stack ls --endpoint primary --format "{{ .Name }}"
Print environment variables of stacks in endpoint with ID=1: Print environment variables of stacks in all endpoints:
psu stack ls --format "{{ .Name }}: {{ range .Env }}{{ .Name }}=\"{{ .Value }}\" {{ end }}"`, psu stack ls --format "{{ .Name }}: {{ range .Env }}{{ .Name }}=\"{{ .Value }}\" {{ end }}"`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
portainerClient, err := common.GetClient() portainerClient, err := common.GetClient()
common.CheckError(err) common.CheckError(err)
endpointId := portainer.EndpointID(viper.GetInt("stack.list.endpoint")) endpoints, endpointsRetrievalErr := portainerClient.GetEndpoints()
common.CheckError(endpointsRetrievalErr)
var endpointSwarmClusterId string var endpointSwarmClusterId string
var stacks []portainer.Stack var stacks []portainer.Stack
if endpointId != 0 { if endpointName := viper.GetString("stack.list.endpoint"); endpointName != "" {
// Get endpoint by name
endpoint, endpointRetrievalErr := common.GetEndpointFromListByName(endpoints, endpointName)
common.CheckError(endpointRetrievalErr)
var selectionErr error var selectionErr error
endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpointId) endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpoint.ID)
if selectionErr == nil { if selectionErr == nil {
// It's a swarm cluster // It's a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Getting stacks") }).Debug("Getting stacks")
stacks, err = portainerClient.GetStacks(endpointSwarmClusterId, endpointId) stacks, err = portainerClient.GetStacks(endpointSwarmClusterId, endpoint.ID)
common.CheckError(err) common.CheckError(err)
} else if selectionErr == common.ErrStackClusterNotFound { } else if selectionErr == common.ErrStackClusterNotFound {
// It's not a swarm cluster // It's not a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Getting stacks") }).Debug("Getting stacks")
stacks, err = portainerClient.GetStacks("", endpointId) stacks, err = portainerClient.GetStacks("", endpoint.ID)
common.CheckError(err) common.CheckError(err)
} else { } else {
// Something else happened // Something else happened
@ -70,16 +76,18 @@ var stackListCmd = &cobra.Command{
"ID", "ID",
"NAME", "NAME",
"TYPE", "TYPE",
"ENDPOINT ID", "ENDPOINT",
}) })
common.CheckError(err) common.CheckError(err)
for _, s := range stacks { for _, s := range stacks {
_, err := fmt.Fprintln(writer, fmt.Sprintf( stackEndpoint, err := common.GetEndpointFromListById(endpoints, s.EndpointID)
"%v\t%s\t%v\t%v", common.CheckError(err)
_, err = fmt.Fprintln(writer, fmt.Sprintf(
"%v\t%s\t%v\t%s",
s.ID, s.ID,
s.Name, s.Name,
client.GetTranslatedStackType(s), client.GetTranslatedStackType(s),
s.EndpointID, stackEndpoint.Name,
)) ))
common.CheckError(err) common.CheckError(err)
} }
@ -106,7 +114,7 @@ var stackListCmd = &cobra.Command{
func init() { func init() {
stackCmd.AddCommand(stackListCmd) stackCmd.AddCommand(stackListCmd)
stackListCmd.Flags().Int("endpoint", 0, "Filter by endpoint ID.") stackListCmd.Flags().String("endpoint", "", "Filter by endpoint name.")
stackListCmd.Flags().String("format", "table", `Output format. Can be "table", "json" or a Go template.`) stackListCmd.Flags().String("format", "table", `Output format. Can be "table", "json" or a Go template.`)
viper.BindPFlag("stack.list.endpoint", stackListCmd.Flags().Lookup("endpoint")) viper.BindPFlag("stack.list.endpoint", stackListCmd.Flags().Lookup("endpoint"))
viper.BindPFlag("stack.list.format", stackListCmd.Flags().Lookup("format")) viper.BindPFlag("stack.list.format", stackListCmd.Flags().Lookup("format"))

View File

@ -22,39 +22,45 @@ var stackRemoveCmd = &cobra.Command{
common.CheckError(clientRetrievalErr) common.CheckError(clientRetrievalErr)
stackName := args[0] stackName := args[0]
endpointId := portainer.EndpointID(viper.GetInt("stack.remove.endpoint"))
var endpointSwarmClusterId string var endpointSwarmClusterId string
var stack portainer.Stack var stack portainer.Stack
// Guess EndpointID if not set var endpoint portainer.Endpoint
if endpointId == 0 { if endpointName := viper.GetString("stack.remove.endpoint"); endpointName == "" {
// Guess endpoint if not set
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"implications": "Command will fail if there is not exactly one endpoint available", "implications": "Command will fail if there is not exactly one endpoint available",
}).Warning("Endpoint ID not set") }).Warning("Endpoint not set")
endpoint, err := common.GetDefaultEndpoint() var endpointRetrievalErr error
common.CheckError(err) endpoint, endpointRetrievalErr = common.GetDefaultEndpoint()
endpointId = endpoint.ID common.CheckError(endpointRetrievalErr)
endpointName = endpoint.Name
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"endpoint": endpointId, "endpoint": endpointName,
}).Debug("Using the only available endpoint") }).Debug("Using the only available endpoint")
} else {
// Get endpoint by name
var endpointRetrievalErr error
endpoint, endpointRetrievalErr = common.GetEndpointByName(endpointName)
common.CheckError(endpointRetrievalErr)
} }
var selectionErr, stackRetrievalErr error var selectionErr, stackRetrievalErr error
endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpointId) endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpoint.ID)
if selectionErr == nil { if selectionErr == nil {
// It's a swarm cluster // It's a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Getting stack") }).Debug("Getting stack")
stack, stackRetrievalErr = common.GetStackByName(stackName, endpointSwarmClusterId, endpointId) stack, stackRetrievalErr = common.GetStackByName(stackName, endpointSwarmClusterId, endpoint.ID)
} else if selectionErr == common.ErrStackClusterNotFound { } else if selectionErr == common.ErrStackClusterNotFound {
// It's not a swarm cluster // It's not a swarm cluster
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Getting stack") }).Debug("Getting stack")
stack, stackRetrievalErr = common.GetStackByName(stackName, "", endpointId) stack, stackRetrievalErr = common.GetStackByName(stackName, "", endpoint.ID)
} else { } else {
// Something else happened // Something else happened
common.CheckError(selectionErr) common.CheckError(selectionErr)
@ -66,25 +72,25 @@ var stackRemoveCmd = &cobra.Command{
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Info("Removing stack") }).Info("Removing stack")
err := portainerClient.DeleteStack(stackId) err := portainerClient.DeleteStack(stackId)
common.CheckError(err) common.CheckError(err)
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stack.Name, "stack": stack.Name,
"endpoint": stack.EndpointID, "endpoint": endpoint.Name,
}).Info("Stack removed") }).Info("Stack removed")
} else if stackRetrievalErr == common.ErrStackNotFound { } else if stackRetrievalErr == common.ErrStackNotFound {
// The stack does not exist // The stack does not exist
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
}).Debug("Stack not found") }).Debug("Stack not found")
if viper.GetBool("stack.remove.strict") { if viper.GetBool("stack.remove.strict") {
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"stack": stackName, "stack": stackName,
"endpoint": endpointId, "endpoint": endpoint.Name,
"suggestions": fmt.Sprintf("try with a different endpoint: psu stack rm %s --endpoint ENDPOINT_ID", stackName), "suggestions": fmt.Sprintf("try with a different endpoint: psu stack rm %s --endpoint ENDPOINT_NAME", stackName),
}).Fatal("stack does not exist") }).Fatal("stack does not exist")
} }
} else { } else {
@ -98,7 +104,7 @@ func init() {
stackCmd.AddCommand(stackRemoveCmd) stackCmd.AddCommand(stackRemoveCmd)
stackRemoveCmd.Flags().Bool("strict", false, "Fail if stack does not exist.") stackRemoveCmd.Flags().Bool("strict", false, "Fail if stack does not exist.")
stackRemoveCmd.Flags().Int("endpoint", 0, "Endpoint ID.") stackRemoveCmd.Flags().String("endpoint", "", "Endpoint name.")
viper.BindPFlag("stack.remove.strict", stackRemoveCmd.Flags().Lookup("strict")) viper.BindPFlag("stack.remove.strict", stackRemoveCmd.Flags().Lookup("strict"))
viper.BindPFlag("stack.remove.endpoint", stackRemoveCmd.Flags().Lookup("endpoint")) viper.BindPFlag("stack.remove.endpoint", stackRemoveCmd.Flags().Lookup("endpoint"))
} }