Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli/config: remove warning for deprecated ~/.dockercfg file #4281

Merged
merged 2 commits into from
May 16, 2023
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
87 changes: 24 additions & 63 deletions cli/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,22 @@ const (
// ConfigFileName is the name of config file
ConfigFileName = "config.json"
configFileDir = ".docker"
oldConfigfile = ".dockercfg" // Deprecated: remove once we stop printing deprecation warning
contextsDir = "contexts"
)

var (
initConfigDir = new(sync.Once)
configDir string
homeDir string
)

// resetHomeDir is used in testing to reset the "homeDir" package variable to
// force re-lookup of the home directory between tests.
func resetHomeDir() {
homeDir = ""
}

func getHomeDir() string {
if homeDir == "" {
homeDir = homedir.Get()
}
return homeDir
}

// resetConfigDir is used in testing to reset the "configDir" package variable
// and its sync.Once to force re-lookup between tests.
func resetConfigDir() {
configDir = ""
initConfigDir = new(sync.Once)
}

func setConfigDir() {
if configDir != "" {
return
}
configDir = os.Getenv("DOCKER_CONFIG")
if configDir == "" {
configDir = filepath.Join(getHomeDir(), configFileDir)
}
}

// Dir returns the directory the configuration file is stored in
func Dir() string {
initConfigDir.Do(setConfigDir)
initConfigDir.Do(func() {
configDir = os.Getenv("DOCKER_CONFIG")
if configDir == "" {
configDir = filepath.Join(homedir.Get(), configFileDir)
}
})
return configDir
}

Expand Down Expand Up @@ -96,55 +69,43 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {

// Load reads the configuration files in the given directory, and sets up
// the auth config information and returns values.
// FIXME: use the internal golang config parser
func Load(configDir string) (*configfile.ConfigFile, error) {
cfg, _, err := load(configDir)
return cfg, err
}

// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
// so we can remove the bool return value and collapse this back into `Load`
func load(configDir string) (*configfile.ConfigFile, bool, error) {
printLegacyFileWarning := false

if configDir == "" {
configDir = Dir()
}
return load(configDir)
}

func load(configDir string) (*configfile.ConfigFile, error) {
filename := filepath.Join(configDir, ConfigFileName)
configFile := configfile.New(filename)

// Try happy path first - latest config file
if file, err := os.Open(filename); err == nil {
defer file.Close()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrap(err, filename)
file, err := os.Open(filename)
if err != nil {
if os.IsNotExist(err) {
//
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, nil
}
return configFile, printLegacyFileWarning, err
} else if !os.IsNotExist(err) {
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, printLegacyFileWarning, errors.Wrap(err, filename)
return configFile, nil
}

// Can't find latest config file so check for the old one
filename = filepath.Join(getHomeDir(), oldConfigfile)
if _, err := os.Stat(filename); err == nil {
printLegacyFileWarning = true
defer file.Close()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrap(err, filename)
}
return configFile, printLegacyFileWarning, nil
return configFile, err
}

// LoadDefaultConfigFile attempts to load the default config file and returns
// an initialized ConfigFile struct if none is found.
func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
configFile, printLegacyFileWarning, err := load(Dir())
configFile, err := load(Dir())
if err != nil {
fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
}
if printLegacyFileWarning {
_, _ = fmt.Fprintln(stderr, "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format has been removed and the configuration file will be ignored")
_, _ = fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
}
if !configFile.ContainsAuth() {
configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore)
Expand Down
30 changes: 0 additions & 30 deletions cli/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,15 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/cli/cli/config/types"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/env"
"gotest.tools/v3/fs"
)

var homeKey = "HOME"

func init() {
if runtime.GOOS == "windows" {
homeKey = "USERPROFILE"
}
}

func setupConfigDir(t *testing.T) string {
tmpdir := t.TempDir()
oldDir := Dir()
Expand Down Expand Up @@ -93,24 +81,6 @@ func TestEmptyJSON(t *testing.T) {
saveConfigAndValidateNewFormat(t, config, tmpHome)
}

func TestOldJSONFallbackDeprecationWarning(t *testing.T) {
js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
tmpHome := fs.NewDir(t, t.Name(), fs.WithFile(oldConfigfile, js))
defer tmpHome.Remove()
env.PatchAll(t, map[string]string{homeKey: tmpHome.Path(), "DOCKER_CONFIG": ""})

// reset the homeDir, configDir, and its sync.Once, to force them being resolved again
resetHomeDir()
resetConfigDir()

buffer := new(bytes.Buffer)
configFile := LoadDefaultConfigFile(buffer)
expected := configfile.New(tmpHome.Join(configFileDir, ConfigFileName))
expected.AuthConfigs = map[string]types.AuthConfig{}
assert.Assert(t, strings.Contains(buffer.String(), "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format has been removed and the configuration file will be ignored"))
assert.Check(t, is.DeepEqual(expected, configFile))
}

func TestNewJSON(t *testing.T) {
tmpHome := t.TempDir()

Expand Down
3 changes: 0 additions & 3 deletions docs/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,6 @@ Given that the old file format encourages insecure storage of credentials
Docker v1.7.0 has created this file, support for this file, and its format has
been removed.

A warning is printed in situations where the CLI would fall back to the old file,
notifying the user that the legacy file is present, but ignored.

### Configuration options for experimental CLI features

**Deprecated in Release: v19.03**
Expand Down