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  }