mirror of https://github.com/docker/cli.git
cli/config/configfile: Atomically rewrite the config file when saving.
The config file was being truncated first, which created a window during which it was empty, causing concurrent uses of the `docker` command to potentially fail with: WARNING: Error loading config file: /var/lib/jenkins/.docker/config.json: EOF Error response from daemon: Get https://registry/v2/foo/manifests/latest: no basic auth credentials Signed-off-by: Benoit Sigoure <tsunanet@gmail.com>
This commit is contained in:
parent
8ec21567a7
commit
7e9e2c10bc
|
@ -175,15 +175,21 @@ func (configFile *ConfigFile) Save() error {
|
|||
return errors.Errorf("Can't save config with empty filename")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(configFile.Filename), 0700); err != nil {
|
||||
dir := filepath.Dir(configFile.Filename)
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.OpenFile(configFile.Filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
temp, err := ioutil.TempFile(dir, filepath.Base(configFile.Filename))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return configFile.SaveToWriter(f)
|
||||
err = configFile.SaveToWriter(temp)
|
||||
temp.Close()
|
||||
if err != nil {
|
||||
os.Remove(temp.Name())
|
||||
return err
|
||||
}
|
||||
return os.Rename(temp.Name(), configFile.Filename)
|
||||
}
|
||||
|
||||
// ParseProxyConfig computes proxy configuration by retrieving the config for the provided host and
|
||||
|
|
|
@ -2,6 +2,8 @@ package configfile
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/config/credentials"
|
||||
|
@ -413,3 +415,13 @@ func TestCheckKubernetesConfigurationRaiseAnErrorOnInvalidValue(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSave(t *testing.T) {
|
||||
configFile := New("test-save")
|
||||
defer os.Remove("test-save")
|
||||
err := configFile.Save()
|
||||
assert.NilError(t, err)
|
||||
cfg, err := ioutil.ReadFile("test-save")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(string(cfg), "{\n \"auths\": {}\n}"))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue