Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions cli/command/stack/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ type fakeClient struct {
services []string
networks []string
secrets []string
configs []string

removedServices []string
removedNetworks []string
removedSecrets []string
removedConfigs []string

serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error)
networkListFunc func(options types.NetworkListOptions) ([]types.NetworkResource, error)
secretListFunc func(options types.SecretListOptions) ([]swarm.Secret, error)
configListFunc func(options types.ConfigListOptions) ([]swarm.Config, error)
serviceRemoveFunc func(serviceID string) error
networkRemoveFunc func(networkID string) error
secretRemoveFunc func(secretID string) error
configRemoveFunc func(configID string) error
}

func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
Expand Down Expand Up @@ -75,6 +79,21 @@ func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListO
return secretsList, nil
}

func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
if cli.configListFunc != nil {
return cli.configListFunc(options)
}

namespace := namespaceFromFilters(options.Filters)
configsList := []swarm.Config{}
for _, name := range cli.configs {
if belongToNamespace(name, namespace) {
configsList = append(configsList, configFromName(name))
}
}
return configsList, nil
}

func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) error {
if cli.serviceRemoveFunc != nil {
return cli.serviceRemoveFunc(serviceID)
Expand Down Expand Up @@ -102,6 +121,15 @@ func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error
return nil
}

func (cli *fakeClient) ConfigRemove(ctx context.Context, configID string) error {
if cli.configRemoveFunc != nil {
return cli.configRemoveFunc(configID)
}

cli.removedConfigs = append(cli.removedConfigs, configID)
return nil
}

func serviceFromName(name string) swarm.Service {
return swarm.Service{
ID: "ID-" + name,
Expand All @@ -127,6 +155,15 @@ func secretFromName(name string) swarm.Secret {
}
}

func configFromName(name string) swarm.Config {
return swarm.Config{
ID: "ID-" + name,
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{Name: name},
},
}
}

func namespaceFromFilters(filters filters.Args) string {
label := filters.Get("label")[0]
return strings.TrimPrefix(label, convert.LabelNamespace+"=")
Expand Down
10 changes: 10 additions & 0 deletions cli/command/stack/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@ func getStackSecrets(
ctx,
types.SecretListOptions{Filters: getStackFilter(namespace)})
}

func getStackConfigs(
ctx context.Context,
apiclient client.APIClient,
namespace string,
) ([]swarm.Config, error) {
return apiclient.ConfigList(
ctx,
types.ConfigListOptions{Filters: getStackFilter(namespace)})
}
23 changes: 22 additions & 1 deletion cli/command/stack/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,19 @@ func runRemove(dockerCli command.Cli, opts removeOptions) error {
return err
}

if len(services)+len(networks)+len(secrets) == 0 {
configs, err := getStackConfigs(ctx, client, namespace)
if err != nil {
return err
}

if len(services)+len(networks)+len(secrets)+len(configs) == 0 {
fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace)
continue
}

hasError := removeServices(ctx, dockerCli, services)
hasError = removeSecrets(ctx, dockerCli, secrets) || hasError
hasError = removeConfigs(ctx, dockerCli, configs) || hasError
hasError = removeNetworks(ctx, dockerCli, networks) || hasError

if hasError {
Expand Down Expand Up @@ -119,3 +125,18 @@ func removeSecrets(
}
return err != nil
}

func removeConfigs(
ctx context.Context,
dockerCli command.Cli,
configs []swarm.Config,
) bool {
var err error
for _, config := range configs {
fmt.Fprintf(dockerCli.Err(), "Removing config %s\n", config.Spec.Name)
if err = dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil {
fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err)
}
}
return err != nil
}
19 changes: 19 additions & 0 deletions cli/command/stack/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,18 @@ func TestRemoveStack(t *testing.T) {
}
allSecretIDs := buildObjectIDs(allSecrets)

allConfigs := []string{
objectName("foo", "config1"),
objectName("foo", "config2"),
objectName("bar", "config1"),
}
allConfigIDs := buildObjectIDs(allConfigs)

cli := &fakeClient{
services: allServices,
networks: allNetworks,
secrets: allSecrets,
configs: allConfigs,
}
cmd := newRemoveCommand(test.NewFakeCli(cli, &bytes.Buffer{}))
cmd.SetArgs([]string{"foo", "bar"})
Expand All @@ -44,6 +52,7 @@ func TestRemoveStack(t *testing.T) {
assert.Equal(t, allServiceIDs, cli.removedServices)
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
assert.Equal(t, allSecretIDs, cli.removedSecrets)
assert.Equal(t, allConfigIDs, cli.removedConfigs)
}

func TestSkipEmptyStack(t *testing.T) {
Expand All @@ -57,10 +66,14 @@ func TestSkipEmptyStack(t *testing.T) {
allSecrets := []string{objectName("bar", "secret1")}
allSecretIDs := buildObjectIDs(allSecrets)

allConfigs := []string{objectName("bar", "config1")}
allConfigIDs := buildObjectIDs(allConfigs)

cli := &fakeClient{
services: allServices,
networks: allNetworks,
secrets: allSecrets,
configs: allConfigs,
}
cmd := newRemoveCommand(test.NewFakeCli(cli, buf))
cmd.SetArgs([]string{"foo", "bar"})
Expand All @@ -70,6 +83,7 @@ func TestSkipEmptyStack(t *testing.T) {
assert.Equal(t, allServiceIDs, cli.removedServices)
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
assert.Equal(t, allSecretIDs, cli.removedSecrets)
assert.Equal(t, allConfigIDs, cli.removedConfigs)
}

func TestContinueAfterError(t *testing.T) {
Expand All @@ -82,11 +96,15 @@ func TestContinueAfterError(t *testing.T) {
allSecrets := []string{objectName("foo", "secret1"), objectName("bar", "secret1")}
allSecretIDs := buildObjectIDs(allSecrets)

allConfigs := []string{objectName("foo", "config1"), objectName("bar", "config1")}
allConfigIDs := buildObjectIDs(allConfigs)

removedServices := []string{}
cli := &fakeClient{
services: allServices,
networks: allNetworks,
secrets: allSecrets,
configs: allConfigs,

serviceRemoveFunc: func(serviceID string) error {
removedServices = append(removedServices, serviceID)
Expand All @@ -104,4 +122,5 @@ func TestContinueAfterError(t *testing.T) {
assert.Equal(t, allServiceIDs, removedServices)
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
assert.Equal(t, allSecretIDs, cli.removedSecrets)
assert.Equal(t, allConfigIDs, cli.removedConfigs)
}