github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/cli/command/stack/swarm/remove.go (about) 1 package swarm 2 3 import ( 4 "context" 5 "fmt" 6 "sort" 7 "strings" 8 9 "github.com/docker/cli/cli/command" 10 "github.com/docker/cli/cli/command/stack/options" 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/swarm" 13 "github.com/docker/docker/api/types/versions" 14 "github.com/pkg/errors" 15 ) 16 17 // RunRemove is the swarm implementation of docker stack remove 18 func RunRemove(ctx context.Context, dockerCli command.Cli, opts options.Remove) error { 19 client := dockerCli.Client() 20 21 var errs []string 22 for _, namespace := range opts.Namespaces { 23 services, err := getStackServices(ctx, client, namespace) 24 if err != nil { 25 return err 26 } 27 28 networks, err := getStackNetworks(ctx, client, namespace) 29 if err != nil { 30 return err 31 } 32 33 var secrets []swarm.Secret 34 if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.25") { 35 secrets, err = getStackSecrets(ctx, client, namespace) 36 if err != nil { 37 return err 38 } 39 } 40 41 var configs []swarm.Config 42 if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.30") { 43 configs, err = getStackConfigs(ctx, client, namespace) 44 if err != nil { 45 return err 46 } 47 } 48 49 if len(services)+len(networks)+len(secrets)+len(configs) == 0 { 50 fmt.Fprintf(dockerCli.Err(), "Nothing found in stack: %s\n", namespace) 51 continue 52 } 53 54 hasError := removeServices(ctx, dockerCli, services) 55 hasError = removeSecrets(ctx, dockerCli, secrets) || hasError 56 hasError = removeConfigs(ctx, dockerCli, configs) || hasError 57 hasError = removeNetworks(ctx, dockerCli, networks) || hasError 58 59 if hasError { 60 errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace)) 61 } 62 } 63 64 if len(errs) > 0 { 65 return errors.Errorf(strings.Join(errs, "\n")) 66 } 67 return nil 68 } 69 70 func sortServiceByName(services []swarm.Service) func(i, j int) bool { 71 return func(i, j int) bool { 72 return services[i].Spec.Name < services[j].Spec.Name 73 } 74 } 75 76 func removeServices( 77 ctx context.Context, 78 dockerCli command.Cli, 79 services []swarm.Service, 80 ) bool { 81 var hasError bool 82 sort.Slice(services, sortServiceByName(services)) 83 for _, service := range services { 84 fmt.Fprintf(dockerCli.Out(), "Removing service %s\n", service.Spec.Name) 85 if err := dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil { 86 hasError = true 87 fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err) 88 } 89 } 90 return hasError 91 } 92 93 func removeNetworks( 94 ctx context.Context, 95 dockerCli command.Cli, 96 networks []types.NetworkResource, 97 ) bool { 98 var hasError bool 99 for _, network := range networks { 100 fmt.Fprintf(dockerCli.Out(), "Removing network %s\n", network.Name) 101 if err := dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil { 102 hasError = true 103 fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err) 104 } 105 } 106 return hasError 107 } 108 109 func removeSecrets( 110 ctx context.Context, 111 dockerCli command.Cli, 112 secrets []swarm.Secret, 113 ) bool { 114 var hasError bool 115 for _, secret := range secrets { 116 fmt.Fprintf(dockerCli.Out(), "Removing secret %s\n", secret.Spec.Name) 117 if err := dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil { 118 hasError = true 119 fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err) 120 } 121 } 122 return hasError 123 } 124 125 func removeConfigs( 126 ctx context.Context, 127 dockerCli command.Cli, 128 configs []swarm.Config, 129 ) bool { 130 var hasError bool 131 for _, config := range configs { 132 fmt.Fprintf(dockerCli.Out(), "Removing config %s\n", config.Spec.Name) 133 if err := dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil { 134 hasError = true 135 fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err) 136 } 137 } 138 return hasError 139 }