remove.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package stack
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/docker/docker/api/types"
  6. "github.com/docker/docker/api/types/swarm"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/pkg/errors"
  10. "github.com/spf13/cobra"
  11. "golang.org/x/net/context"
  12. )
  13. type removeOptions struct {
  14. namespaces []string
  15. }
  16. func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
  17. var opts removeOptions
  18. cmd := &cobra.Command{
  19. Use: "rm STACK [STACK...]",
  20. Aliases: []string{"remove", "down"},
  21. Short: "Remove one or more stacks",
  22. Args: cli.RequiresMinArgs(1),
  23. RunE: func(cmd *cobra.Command, args []string) error {
  24. opts.namespaces = args
  25. return runRemove(dockerCli, opts)
  26. },
  27. }
  28. return cmd
  29. }
  30. func runRemove(dockerCli command.Cli, opts removeOptions) error {
  31. namespaces := opts.namespaces
  32. client := dockerCli.Client()
  33. ctx := context.Background()
  34. var errs []string
  35. for _, namespace := range namespaces {
  36. services, err := getServices(ctx, client, namespace)
  37. if err != nil {
  38. return err
  39. }
  40. networks, err := getStackNetworks(ctx, client, namespace)
  41. if err != nil {
  42. return err
  43. }
  44. secrets, err := getStackSecrets(ctx, client, namespace)
  45. if err != nil {
  46. return err
  47. }
  48. if len(services)+len(networks)+len(secrets) == 0 {
  49. fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace)
  50. continue
  51. }
  52. hasError := removeServices(ctx, dockerCli, services)
  53. hasError = removeSecrets(ctx, dockerCli, secrets) || hasError
  54. hasError = removeNetworks(ctx, dockerCli, networks) || hasError
  55. if hasError {
  56. errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace))
  57. }
  58. }
  59. if len(errs) > 0 {
  60. return errors.Errorf(strings.Join(errs, "\n"))
  61. }
  62. return nil
  63. }
  64. func removeServices(
  65. ctx context.Context,
  66. dockerCli command.Cli,
  67. services []swarm.Service,
  68. ) bool {
  69. var err error
  70. for _, service := range services {
  71. fmt.Fprintf(dockerCli.Err(), "Removing service %s\n", service.Spec.Name)
  72. if err = dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil {
  73. fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err)
  74. }
  75. }
  76. return err != nil
  77. }
  78. func removeNetworks(
  79. ctx context.Context,
  80. dockerCli command.Cli,
  81. networks []types.NetworkResource,
  82. ) bool {
  83. var err error
  84. for _, network := range networks {
  85. fmt.Fprintf(dockerCli.Err(), "Removing network %s\n", network.Name)
  86. if err = dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil {
  87. fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err)
  88. }
  89. }
  90. return err != nil
  91. }
  92. func removeSecrets(
  93. ctx context.Context,
  94. dockerCli command.Cli,
  95. secrets []swarm.Secret,
  96. ) bool {
  97. var err error
  98. for _, secret := range secrets {
  99. fmt.Fprintf(dockerCli.Err(), "Removing secret %s\n", secret.Spec.Name)
  100. if err = dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil {
  101. fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err)
  102. }
  103. }
  104. return err != nil
  105. }