When running `docker stack rm <some stack>` against an older daemon, a warning was printed for "configs" being ignored; WARNING: ignoring "configs" (requires API version 1.30, but the Docker daemon API version is 1.26) Given that an old daemon cannot _have_ configs, there should not be a need to warn, or _attempt_ to remove these resources. This patch removes the warning, and skips fetching (and removing) configs. A check if _secrets_ are supported by the daemon is also added, given that this would result in an error when attempted against an older (pre 1.13) daemon. There is one situation where this could lead to secrets or configs being left behind; if the client is connecting to a daemon that _does_ support secrets, configs, but the API version is overridden using `DOCKER_API_VERSION`, no warning is printed, and secrets and configs are not attempted to be removed. Given that `DOCKER_API_VERSION` is regarded a feature for debugging / "power users", it should be ok to ignore this. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
171 lines
5.0 KiB
Go
171 lines
5.0 KiB
Go
package stack
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io/ioutil"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/docker/cli/cli/internal/test"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestRemoveStack(t *testing.T) {
|
|
allServices := []string{
|
|
objectName("foo", "service1"),
|
|
objectName("foo", "service2"),
|
|
objectName("bar", "service1"),
|
|
objectName("bar", "service2"),
|
|
}
|
|
allServiceIDs := buildObjectIDs(allServices)
|
|
|
|
allNetworks := []string{
|
|
objectName("foo", "network1"),
|
|
objectName("bar", "network1"),
|
|
}
|
|
allNetworkIDs := buildObjectIDs(allNetworks)
|
|
|
|
allSecrets := []string{
|
|
objectName("foo", "secret1"),
|
|
objectName("foo", "secret2"),
|
|
objectName("bar", "secret1"),
|
|
}
|
|
allSecretIDs := buildObjectIDs(allSecrets)
|
|
|
|
allConfigs := []string{
|
|
objectName("foo", "config1"),
|
|
objectName("foo", "config2"),
|
|
objectName("bar", "config1"),
|
|
}
|
|
allConfigIDs := buildObjectIDs(allConfigs)
|
|
|
|
// Using API 1.24; removes services, networks, but doesn't remove configs and secrets
|
|
cli := &fakeClient{
|
|
version: "1.24",
|
|
services: allServices,
|
|
networks: allNetworks,
|
|
secrets: allSecrets,
|
|
configs: allConfigs,
|
|
}
|
|
cmd := newRemoveCommand(test.NewFakeCli(cli, &bytes.Buffer{}))
|
|
cmd.SetArgs([]string{"foo", "bar"})
|
|
|
|
assert.NoError(t, cmd.Execute())
|
|
assert.Equal(t, allServiceIDs, cli.removedServices)
|
|
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
|
|
assert.Nil(t, cli.removedSecrets)
|
|
assert.Nil(t, cli.removedConfigs)
|
|
|
|
// Using API 1.25; removes services, networks, but doesn't remove configs
|
|
cli = &fakeClient{
|
|
version: "1.25",
|
|
services: allServices,
|
|
networks: allNetworks,
|
|
secrets: allSecrets,
|
|
configs: allConfigs,
|
|
}
|
|
cmd = newRemoveCommand(test.NewFakeCli(cli, &bytes.Buffer{}))
|
|
cmd.SetArgs([]string{"foo", "bar"})
|
|
|
|
assert.NoError(t, cmd.Execute())
|
|
assert.Equal(t, allServiceIDs, cli.removedServices)
|
|
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
|
|
assert.Equal(t, allSecretIDs, cli.removedSecrets)
|
|
assert.Nil(t, cli.removedConfigs)
|
|
|
|
// Using API 1.30; removes services, networks, configs, and secrets
|
|
cli = &fakeClient{
|
|
version: "1.30",
|
|
services: allServices,
|
|
networks: allNetworks,
|
|
secrets: allSecrets,
|
|
configs: allConfigs,
|
|
}
|
|
cmd = newRemoveCommand(test.NewFakeCli(cli, &bytes.Buffer{}))
|
|
cmd.SetArgs([]string{"foo", "bar"})
|
|
|
|
assert.NoError(t, cmd.Execute())
|
|
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 TestRemoveStackSkipEmpty(t *testing.T) {
|
|
out := new(bytes.Buffer)
|
|
stderr := new(bytes.Buffer)
|
|
allServices := []string{objectName("bar", "service1"), objectName("bar", "service2")}
|
|
allServiceIDs := buildObjectIDs(allServices)
|
|
|
|
allNetworks := []string{objectName("bar", "network1")}
|
|
allNetworkIDs := buildObjectIDs(allNetworks)
|
|
|
|
allSecrets := []string{objectName("bar", "secret1")}
|
|
allSecretIDs := buildObjectIDs(allSecrets)
|
|
|
|
allConfigs := []string{objectName("bar", "config1")}
|
|
allConfigIDs := buildObjectIDs(allConfigs)
|
|
|
|
fakeClient := &fakeClient{
|
|
version: "1.30",
|
|
services: allServices,
|
|
networks: allNetworks,
|
|
secrets: allSecrets,
|
|
configs: allConfigs,
|
|
}
|
|
fakeCli := test.NewFakeCli(fakeClient, out)
|
|
fakeCli.SetErr(stderr)
|
|
cmd := newRemoveCommand(fakeCli)
|
|
cmd.SetArgs([]string{"foo", "bar"})
|
|
|
|
assert.NoError(t, cmd.Execute())
|
|
assert.Equal(t, "", out.String())
|
|
assert.Contains(t, stderr.String(), "Nothing found in stack: foo\n")
|
|
assert.Equal(t, allServiceIDs, fakeClient.removedServices)
|
|
assert.Equal(t, allNetworkIDs, fakeClient.removedNetworks)
|
|
assert.Equal(t, allSecretIDs, fakeClient.removedSecrets)
|
|
assert.Equal(t, allConfigIDs, fakeClient.removedConfigs)
|
|
}
|
|
|
|
func TestRemoveContinueAfterError(t *testing.T) {
|
|
allServices := []string{objectName("foo", "service1"), objectName("bar", "service1")}
|
|
allServiceIDs := buildObjectIDs(allServices)
|
|
|
|
allNetworks := []string{objectName("foo", "network1"), objectName("bar", "network1")}
|
|
allNetworkIDs := buildObjectIDs(allNetworks)
|
|
|
|
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{
|
|
version: "1.30",
|
|
services: allServices,
|
|
networks: allNetworks,
|
|
secrets: allSecrets,
|
|
configs: allConfigs,
|
|
|
|
serviceRemoveFunc: func(serviceID string) error {
|
|
removedServices = append(removedServices, serviceID)
|
|
|
|
if strings.Contains(serviceID, "foo") {
|
|
return errors.New("")
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
cmd := newRemoveCommand(test.NewFakeCli(cli, &bytes.Buffer{}))
|
|
cmd.SetOutput(ioutil.Discard)
|
|
cmd.SetArgs([]string{"foo", "bar"})
|
|
|
|
assert.EqualError(t, cmd.Execute(), "Failed to remove some resources from stack: foo")
|
|
assert.Equal(t, allServiceIDs, removedServices)
|
|
assert.Equal(t, allNetworkIDs, cli.removedNetworks)
|
|
assert.Equal(t, allSecretIDs, cli.removedSecrets)
|
|
assert.Equal(t, allConfigIDs, cli.removedConfigs)
|
|
}
|