github.1git.de/docker/cli@v26.1.3+incompatible/cli/config/config.go (about) 1 package config 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 "strings" 9 "sync" 10 11 "github.com/docker/cli/cli/config/configfile" 12 "github.com/docker/cli/cli/config/credentials" 13 "github.com/docker/cli/cli/config/types" 14 "github.com/docker/docker/pkg/homedir" 15 "github.com/pkg/errors" 16 ) 17 18 const ( 19 // EnvOverrideConfigDir is the name of the environment variable that can be 20 // used to override the location of the client configuration files (~/.docker). 21 // 22 // It takes priority over the default, but can be overridden by the "--config" 23 // command line option. 24 EnvOverrideConfigDir = "DOCKER_CONFIG" 25 26 // ConfigFileName is the name of the client configuration file inside the 27 // config-directory. 28 ConfigFileName = "config.json" 29 configFileDir = ".docker" 30 contextsDir = "contexts" 31 ) 32 33 var ( 34 initConfigDir = new(sync.Once) 35 configDir string 36 ) 37 38 // resetConfigDir is used in testing to reset the "configDir" package variable 39 // and its sync.Once to force re-lookup between tests. 40 func resetConfigDir() { 41 configDir = "" 42 initConfigDir = new(sync.Once) 43 } 44 45 // Dir returns the directory the configuration file is stored in 46 func Dir() string { 47 initConfigDir.Do(func() { 48 configDir = os.Getenv(EnvOverrideConfigDir) 49 if configDir == "" { 50 configDir = filepath.Join(homedir.Get(), configFileDir) 51 } 52 }) 53 return configDir 54 } 55 56 // ContextStoreDir returns the directory the docker contexts are stored in 57 func ContextStoreDir() string { 58 return filepath.Join(Dir(), contextsDir) 59 } 60 61 // SetDir sets the directory the configuration file is stored in 62 func SetDir(dir string) { 63 // trigger the sync.Once to synchronise with Dir() 64 initConfigDir.Do(func() {}) 65 configDir = filepath.Clean(dir) 66 } 67 68 // Path returns the path to a file relative to the config dir 69 func Path(p ...string) (string, error) { 70 path := filepath.Join(append([]string{Dir()}, p...)...) 71 if !strings.HasPrefix(path, Dir()+string(filepath.Separator)) { 72 return "", errors.Errorf("path %q is outside of root config directory %q", path, Dir()) 73 } 74 return path, nil 75 } 76 77 // LoadFromReader is a convenience function that creates a ConfigFile object from 78 // a reader 79 func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) { 80 configFile := configfile.ConfigFile{ 81 AuthConfigs: make(map[string]types.AuthConfig), 82 } 83 err := configFile.LoadFromReader(configData) 84 return &configFile, err 85 } 86 87 // Load reads the configuration files in the given directory, and sets up 88 // the auth config information and returns values. 89 func Load(configDir string) (*configfile.ConfigFile, error) { 90 if configDir == "" { 91 configDir = Dir() 92 } 93 return load(configDir) 94 } 95 96 func load(configDir string) (*configfile.ConfigFile, error) { 97 filename := filepath.Join(configDir, ConfigFileName) 98 configFile := configfile.New(filename) 99 100 file, err := os.Open(filename) 101 if err != nil { 102 if os.IsNotExist(err) { 103 // 104 // if file is there but we can't stat it for any reason other 105 // than it doesn't exist then stop 106 return configFile, nil 107 } 108 // if file is there but we can't stat it for any reason other 109 // than it doesn't exist then stop 110 return configFile, nil 111 } 112 defer file.Close() 113 err = configFile.LoadFromReader(file) 114 if err != nil { 115 err = errors.Wrap(err, filename) 116 } 117 return configFile, err 118 } 119 120 // LoadDefaultConfigFile attempts to load the default config file and returns 121 // an initialized ConfigFile struct if none is found. 122 func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile { 123 configFile, err := load(Dir()) 124 if err != nil { 125 _, _ = fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err) 126 } 127 if !configFile.ContainsAuth() { 128 configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore) 129 } 130 return configFile 131 }