context use: don't create/update config file and directories if not needed

Avoid updating the config-file if nothing changed. This also prevents creating
the file and config-directory if the default is used and no config-file existed
yet.

`config.Save()` performs various steps (creating the directory, updating
or copying permissions, etc etc), which are not needed if the defaults are
used; a445d97c25/cli/config/configfile/file.go (L135-L176)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-07-29 11:58:37 +02:00
parent cee286ff63
commit f87d7ed864
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
2 changed files with 40 additions and 3 deletions

View File

@ -37,9 +37,14 @@ func RunUse(dockerCli command.Cli, name string) error {
configValue = name configValue = name
} }
dockerConfig := dockerCli.ConfigFile() dockerConfig := dockerCli.ConfigFile()
dockerConfig.CurrentContext = configValue // Avoid updating the config-file if nothing changed. This also prevents
if err := dockerConfig.Save(); err != nil { // creating the file and config-directory if the default is used and
return err // no config-file existed yet.
if dockerConfig.CurrentContext != configValue {
dockerConfig.CurrentContext = configValue
if err := dockerConfig.Save(); err != nil {
return err
}
} }
fmt.Fprintln(dockerCli.Out(), name) fmt.Fprintln(dockerCli.Out(), name)
fmt.Fprintf(dockerCli.Err(), "Current context is now %q\n", name) fmt.Fprintf(dockerCli.Err(), "Current context is now %q\n", name)

View File

@ -2,6 +2,9 @@ package context
import ( import (
"bytes" "bytes"
"errors"
"io"
"os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -10,6 +13,7 @@ import (
"github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/context/store" "github.com/docker/cli/cli/context/store"
"github.com/docker/cli/cli/flags" "github.com/docker/cli/cli/flags"
"github.com/docker/docker/pkg/homedir"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
) )
@ -46,6 +50,34 @@ func TestUseNoExist(t *testing.T) {
assert.Check(t, store.IsErrContextDoesNotExist(err)) assert.Check(t, store.IsErrContextDoesNotExist(err))
} }
// TestUseDefaultWithoutConfigFile verifies that the CLI does not create
// the default config file and directory when using the default context.
func TestUseDefaultWithoutConfigFile(t *testing.T) {
// We must use a temporary home-directory, because this test covers
// the _default_ configuration file. If we specify a custom configuration
// file, the CLI produces an error if the file doesn't exist.
tmpHomeDir := t.TempDir()
t.Setenv(homedir.Key(), tmpHomeDir)
configDir := filepath.Join(tmpHomeDir, ".docker")
configFilePath := filepath.Join(configDir, "config.json")
// Verify config-dir and -file don't exist before
_, err := os.Stat(configDir)
assert.Check(t, errors.Is(err, os.ErrNotExist))
_, err = os.Stat(configFilePath)
assert.Check(t, errors.Is(err, os.ErrNotExist))
cli, err := command.NewDockerCli(command.WithCombinedStreams(io.Discard))
assert.NilError(t, err)
assert.NilError(t, newUseCommand(cli).RunE(nil, []string{"default"}))
// Verify config-dir and -file don't exist after
_, err = os.Stat(configDir)
assert.Check(t, errors.Is(err, os.ErrNotExist))
_, err = os.Stat(configFilePath)
assert.Check(t, errors.Is(err, os.ErrNotExist))
}
func TestUseHostOverride(t *testing.T) { func TestUseHostOverride(t *testing.T) {
t.Setenv("DOCKER_HOST", "tcp://ed:2375/") t.Setenv("DOCKER_HOST", "tcp://ed:2375/")