diff --git a/CHANGELOG.md b/CHANGELOG.md index 514dc676..e86ce33f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - pkg: new `Config` interface type to support new generic `FromViper` config file parsing - changed flags `--k3s-server-arg` & `--k3s-agent-arg` into `--k3s-arg` with nodefilter support (#605) - new config path `options.k3s.extraArgs` +- config file: environment variables (`$VAR`, `${VAR}` will be expanded unconditionally) (#643) ### Misc diff --git a/cmd/cluster/clusterCreate.go b/cmd/cluster/clusterCreate.go index 89a2fbae..7e977f5a 100644 --- a/cmd/cluster/clusterCreate.go +++ b/cmd/cluster/clusterCreate.go @@ -24,7 +24,9 @@ package cluster import ( "fmt" + "io/ioutil" "os" + "path/filepath" "runtime" "strings" "time" @@ -72,12 +74,31 @@ func initConfig() { // Set config file, if specified if configFile != "" { - cfgViper.SetConfigFile(configFile) if _, err := os.Stat(configFile); err != nil { log.Fatalf("Failed to stat config file %s: %+v", configFile, err) } + // create temporary file to expand environment variables in the config without writing that back to the original file + // we're doing it here, because this happens just before absolutely all other processing + tmpfile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("k3d-config-tmp-%s", filepath.Base(configFile))) + if err != nil { + log.Fatalf("error creating temp copy of configfile %s for variable expansion: %v", configFile, err) + } + defer tmpfile.Close() + + originalcontent, err := ioutil.ReadFile(configFile) + if err != nil { + log.Fatalf("error reading config file %s: %v", configFile, err) + } + expandedcontent := os.ExpandEnv(string(originalcontent)) + if _, err := tmpfile.WriteString(expandedcontent); err != nil { + log.Fatalf("error writing expanded config file contents to temp file %s: %v", tmpfile.Name(), err) + } + + // use temp file with expanded variables + cfgViper.SetConfigFile(tmpfile.Name()) + // try to read config into memory (viper map structure) if err := cfgViper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { @@ -96,7 +117,7 @@ func initConfig() { log.Fatalf("Schema Validation failed for config file %s: %+v", configFile, err) } - log.Infof("Using config file %s (%s#%s)", cfgViper.ConfigFileUsed(), strings.ToLower(cfgViper.GetString("apiVersion")), strings.ToLower(cfgViper.GetString("kind"))) + log.Infof("Using config file %s (%s#%s)", configFile, strings.ToLower(cfgViper.GetString("apiVersion")), strings.ToLower(cfgViper.GetString("kind"))) } if log.GetLevel() >= log.DebugLevel { c, _ := yaml.Marshal(cfgViper.AllSettings()) diff --git a/tests/assets/config_test_simple.yaml b/tests/assets/config_test_simple.yaml index 75588924..0d4440fa 100755 --- a/tests/assets/config_test_simple.yaml +++ b/tests/assets/config_test_simple.yaml @@ -8,7 +8,7 @@ kubeAPI: hostPort: "6446" image: rancher/k3s:latest volumes: - - volume: /my/path:/some/path + - volume: $HOME:/some/path nodeFilters: - all ports: