diff --git a/cmd/stackDeploy.go b/cmd/stackDeploy.go index 90d2eb9..3e0864d 100644 --- a/cmd/stackDeploy.go +++ b/cmd/stackDeploy.go @@ -32,22 +32,28 @@ var stackDeployCmd = &cobra.Command{ common.CheckError(clientRetrievalErr) stackName := args[0] - endpointId := portainer.EndpointID(viper.GetInt("stack.deploy.endpoint")) - // Guess EndpointID if not set - if endpointId == 0 { + var endpoint portainer.Endpoint + if endpointName := viper.GetString("stack.deploy.endpoint"); endpointName == "" { + // Guess endpoint if not set logrus.WithFields(logrus.Fields{ "implications": "Command will fail if there is not exactly one endpoint available", - }).Warning("Endpoint ID not set") - endpoint, err := common.GetDefaultEndpoint() - common.CheckError(err) - endpointId = endpoint.ID + }).Warning("Endpoint not set") + var endpointRetrievalErr error + endpoint, endpointRetrievalErr = common.GetDefaultEndpoint() + common.CheckError(endpointRetrievalErr) + endpointName = endpoint.Name logrus.WithFields(logrus.Fields{ - "endpoint": endpointId, + "endpoint": endpointName, }).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 { // It's a swarm cluster } else if selectionErr == common.ErrStackClusterNotFound { @@ -59,9 +65,9 @@ var stackDeployCmd = &cobra.Command{ logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Getting stack") - retrievedStack, stackRetrievalErr := common.GetStackByName(stackName, endpointSwarmClusterId, endpointId) + retrievedStack, stackRetrievalErr := common.GetStackByName(stackName, endpointSwarmClusterId, endpoint.ID) if stackRetrievalErr == nil { // We are updating an existing stack logrus.WithFields(logrus.Fields{ @@ -106,7 +112,7 @@ var stackDeployCmd = &cobra.Command{ logrus.WithFields(logrus.Fields{ "stack": retrievedStack.Name, }).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) } else if stackRetrievalErr == common.ErrStackNotFound { // We are deploying a new stack @@ -124,26 +130,26 @@ var stackDeployCmd = &cobra.Command{ // It's a swarm cluster logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).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) logrus.WithFields(logrus.Fields{ "stack": stack.Name, - "endpoint": stack.EndpointID, + "endpoint": endpoint.Name, "id": stack.ID, }).Info("Stack created") } else { // It's not a swarm cluster logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Info("Creating stack") - stack, deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, endpointId) + stack, deploymentErr := portainerClient.CreateComposeStack(stackName, loadedEnvironmentVariables, stackFileContent, endpoint.ID) common.CheckError(deploymentErr) logrus.WithFields(logrus.Fields{ "stack": stack.Name, - "endpoint": stack.EndpointID, + "endpoint": endpoint.Name, "id": stack.ID, }).Info("Stack created") } @@ -158,7 +164,7 @@ func init() { stackCmd.AddCommand(stackDeployCmd) 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().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).") diff --git a/cmd/stackList.go b/cmd/stackList.go index 3fd140d..a663c5c 100644 --- a/cmd/stackList.go +++ b/cmd/stackList.go @@ -21,37 +21,43 @@ var stackListCmd = &cobra.Command{ Use: "list", Short: "List stacks", Aliases: []string{"ls"}, - Example: ` Print stacks in endpoint with ID=1 in a table format: - psu stack ls --endpoint 1 + Example: ` Print stacks in endpoint with name=primary in a table format: + psu stack ls --endpoint primary - Print names of stacks in endpoint with ID=1: - psu stack ls --endpoint 1 --format "{{ .Name }}" + Print names of stacks in endpoint with name=primary: + 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 }}"`, Run: func(cmd *cobra.Command, args []string) { portainerClient, err := common.GetClient() common.CheckError(err) - endpointId := portainer.EndpointID(viper.GetInt("stack.list.endpoint")) + endpoints, endpointsRetrievalErr := portainerClient.GetEndpoints() + common.CheckError(endpointsRetrievalErr) + var endpointSwarmClusterId string 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 - endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpointId) + endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpoint.ID) if selectionErr == nil { // It's a swarm cluster logrus.WithFields(logrus.Fields{ - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Getting stacks") - stacks, err = portainerClient.GetStacks(endpointSwarmClusterId, endpointId) + stacks, err = portainerClient.GetStacks(endpointSwarmClusterId, endpoint.ID) common.CheckError(err) } else if selectionErr == common.ErrStackClusterNotFound { // It's not a swarm cluster logrus.WithFields(logrus.Fields{ - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Getting stacks") - stacks, err = portainerClient.GetStacks("", endpointId) + stacks, err = portainerClient.GetStacks("", endpoint.ID) common.CheckError(err) } else { // Something else happened @@ -70,16 +76,18 @@ var stackListCmd = &cobra.Command{ "ID", "NAME", "TYPE", - "ENDPOINT ID", + "ENDPOINT", }) common.CheckError(err) for _, s := range stacks { - _, err := fmt.Fprintln(writer, fmt.Sprintf( - "%v\t%s\t%v\t%v", + stackEndpoint, err := common.GetEndpointFromListById(endpoints, s.EndpointID) + common.CheckError(err) + _, err = fmt.Fprintln(writer, fmt.Sprintf( + "%v\t%s\t%v\t%s", s.ID, s.Name, client.GetTranslatedStackType(s), - s.EndpointID, + stackEndpoint.Name, )) common.CheckError(err) } @@ -106,7 +114,7 @@ var stackListCmd = &cobra.Command{ func init() { 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.`) viper.BindPFlag("stack.list.endpoint", stackListCmd.Flags().Lookup("endpoint")) viper.BindPFlag("stack.list.format", stackListCmd.Flags().Lookup("format")) diff --git a/cmd/stackRemove.go b/cmd/stackRemove.go index 512d735..fe97b69 100644 --- a/cmd/stackRemove.go +++ b/cmd/stackRemove.go @@ -22,39 +22,45 @@ var stackRemoveCmd = &cobra.Command{ common.CheckError(clientRetrievalErr) stackName := args[0] - endpointId := portainer.EndpointID(viper.GetInt("stack.remove.endpoint")) var endpointSwarmClusterId string var stack portainer.Stack - // Guess EndpointID if not set - if endpointId == 0 { + var endpoint portainer.Endpoint + if endpointName := viper.GetString("stack.remove.endpoint"); endpointName == "" { + // Guess endpoint if not set logrus.WithFields(logrus.Fields{ "implications": "Command will fail if there is not exactly one endpoint available", - }).Warning("Endpoint ID not set") - endpoint, err := common.GetDefaultEndpoint() - common.CheckError(err) - endpointId = endpoint.ID + }).Warning("Endpoint not set") + var endpointRetrievalErr error + endpoint, endpointRetrievalErr = common.GetDefaultEndpoint() + common.CheckError(endpointRetrievalErr) + endpointName = endpoint.Name logrus.WithFields(logrus.Fields{ - "endpoint": endpointId, + "endpoint": endpointName, }).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 - endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpointId) + endpointSwarmClusterId, selectionErr = common.GetEndpointSwarmClusterId(endpoint.ID) if selectionErr == nil { // It's a swarm cluster logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Getting stack") - stack, stackRetrievalErr = common.GetStackByName(stackName, endpointSwarmClusterId, endpointId) + stack, stackRetrievalErr = common.GetStackByName(stackName, endpointSwarmClusterId, endpoint.ID) } else if selectionErr == common.ErrStackClusterNotFound { // It's not a swarm cluster logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Getting stack") - stack, stackRetrievalErr = common.GetStackByName(stackName, "", endpointId) + stack, stackRetrievalErr = common.GetStackByName(stackName, "", endpoint.ID) } else { // Something else happened common.CheckError(selectionErr) @@ -66,25 +72,25 @@ var stackRemoveCmd = &cobra.Command{ logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Info("Removing stack") err := portainerClient.DeleteStack(stackId) common.CheckError(err) logrus.WithFields(logrus.Fields{ "stack": stack.Name, - "endpoint": stack.EndpointID, + "endpoint": endpoint.Name, }).Info("Stack removed") } else if stackRetrievalErr == common.ErrStackNotFound { // The stack does not exist logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, + "endpoint": endpoint.Name, }).Debug("Stack not found") if viper.GetBool("stack.remove.strict") { logrus.WithFields(logrus.Fields{ "stack": stackName, - "endpoint": endpointId, - "suggestions": fmt.Sprintf("try with a different endpoint: psu stack rm %s --endpoint ENDPOINT_ID", stackName), + "endpoint": endpoint.Name, + "suggestions": fmt.Sprintf("try with a different endpoint: psu stack rm %s --endpoint ENDPOINT_NAME", stackName), }).Fatal("stack does not exist") } } else { @@ -98,7 +104,7 @@ func init() { stackCmd.AddCommand(stackRemoveCmd) 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.endpoint", stackRemoveCmd.Flags().Lookup("endpoint")) }