Don't attempt to remove unsupported resources on older daemon

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>
This commit is contained in:
Sebastiaan van Stijn 2017-06-30 17:00:16 -07:00
parent 6908e58f0f
commit 2429f15672
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
3 changed files with 51 additions and 11 deletions

View File

@ -15,6 +15,8 @@ import (
type fakeClient struct {
client.Client
version string
services []string
networks []string
secrets []string
@ -45,6 +47,10 @@ func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error)
}, nil
}
func (cli *fakeClient) ClientVersion() string {
return cli.version
}
func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
if cli.serviceListFunc != nil {
return cli.serviceListFunc(options)

View File

@ -51,20 +51,16 @@ func runRemove(dockerCli command.Cli, opts removeOptions) error {
return err
}
secrets, err := getStackSecrets(ctx, client, namespace)
if err != nil {
return err
var secrets []swarm.Secret
if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.25") {
secrets, err = getStackSecrets(ctx, client, namespace)
if err != nil {
return err
}
}
var configs []swarm.Config
version, err := client.ServerVersion(ctx)
if err != nil {
return err
}
if versions.LessThan(version.APIVersion, "1.30") {
fmt.Fprintf(dockerCli.Err(), "WARNING: ignoring \"configs\" (requires API version 1.30, but the Docker daemon API version is %s)\n", version.APIVersion)
} else {
if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.30") {
configs, err = getStackConfigs(ctx, client, namespace)
if err != nil {
return err

View File

@ -40,7 +40,9 @@ func TestRemoveStack(t *testing.T) {
}
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,
@ -49,6 +51,40 @@ func TestRemoveStack(t *testing.T) {
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)
@ -72,6 +108,7 @@ func TestRemoveStackSkipEmpty(t *testing.T) {
allConfigIDs := buildObjectIDs(allConfigs)
fakeClient := &fakeClient{
version: "1.30",
services: allServices,
networks: allNetworks,
secrets: allSecrets,
@ -106,6 +143,7 @@ func TestRemoveContinueAfterError(t *testing.T) {
removedServices := []string{}
cli := &fakeClient{
version: "1.30",
services: allServices,
networks: allNetworks,
secrets: allSecrets,