Skip to content

Commit

Permalink
feat(config): Allow avoiding reading default config file (#2227)
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
  • Loading branch information
hairyhenderson authored Sep 30, 2024
1 parent 69d3e0c commit 18791a4
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,7 @@ jobs:
--exclude="https://docs\.aws.*" \
--exclude="https://linux.die\.net.*" \
--exclude="https://jqplay\.org.*" \
--exclude="https://json\.org.*" \
--exclude="https://goessner\.net.*"
kill %1
2 changes: 1 addition & 1 deletion docs/content/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Hello, hairyhenderson

### `--config`

Specify the path to a [gomplate config file](../config). The default is `.gomplate.yaml`. Can also be set with the `GOMPLATE_CONFIG` environment variable.
Specify the path to a [gomplate config file](../config). The default is `.gomplate.yaml`. Can also be set with the `GOMPLATE_CONFIG` environment variable. Setting `--config` or `GOMPLATE_CONFIG` to an empty string (`--config=""` or `export GOMPLATE_CONFIG=""`) will disable the use of a config file, skipping the default `.gomplate.yaml` file.

For example:

Expand Down
10 changes: 10 additions & 0 deletions env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,13 @@ func ExpandEnv(s string) string {
fsys := datafs.WrapWdFS(osfs.NewFS())
return datafs.ExpandEnvFsys(fsys, s)
}

// LookupEnv - retrieves the value of the environment variable named by the key.
// If the variable is unset, but the same variable ending in `_FILE` is set, the
// referenced file will be read into the value. If the key is not set, the
// second return value will be false.
// Otherwise the provided default (or an emptry string) is returned.
func LookupEnv(key string) (string, bool) {
fsys := datafs.WrapWdFS(osfs.NewFS())
return datafs.LookupEnvFsys(fsys, key)
}
26 changes: 19 additions & 7 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,34 @@ func loadConfig(ctx context.Context, cmd *cobra.Command, args []string) (*gompla
return cfg, nil
}

func pickConfigFile(cmd *cobra.Command) (cfgFile string, required bool) {
func pickConfigFile(cmd *cobra.Command) (cfgFile string, required, skip bool) {
cfgFile = defaultConfigFile
if c := env.Getenv("GOMPLATE_CONFIG"); c != "" {
if c, found := env.LookupEnv("GOMPLATE_CONFIG"); found {
cfgFile = c
required = true
if cfgFile == "" {
skip = true
} else {
required = true
}
}
if cmd.Flags().Changed("config") && cmd.Flag("config").Value.String() != "" {
if cmd.Flags().Changed("config") {
// Use config file from the flag if specified
cfgFile = cmd.Flag("config").Value.String()
required = true
if cfgFile == "" {
skip = true
} else {
required = true
}
}
return cfgFile, required
return cfgFile, required, skip
}

func readConfigFile(ctx context.Context, cmd *cobra.Command) (*gomplate.Config, error) {
cfgFile, configRequired := pickConfigFile(cmd)
cfgFile, configRequired, skip := pickConfigFile(cmd)
if skip {
// --config was specified with an empty value
return nil, nil
}

// we only support loading configs from the local filesystem for now
fsys, err := datafs.FSysForPath(ctx, cfgFile)
Expand Down
28 changes: 24 additions & 4 deletions internal/cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,29 +188,49 @@ func TestPickConfigFile(t *testing.T) {
cmd.Flags().String("config", defaultConfigFile, "foo")

t.Run("default", func(t *testing.T) {
cf, req := pickConfigFile(cmd)
cf, req, skip := pickConfigFile(cmd)
assert.False(t, req)
assert.False(t, skip)
assert.Equal(t, defaultConfigFile, cf)
})

t.Run("GOMPLATE_CONFIG env var", func(t *testing.T) {
t.Setenv("GOMPLATE_CONFIG", "foo.yaml")
cf, req := pickConfigFile(cmd)
cf, req, skip := pickConfigFile(cmd)
assert.True(t, req)
assert.False(t, skip)
assert.Equal(t, "foo.yaml", cf)
})

t.Run("--config flag", func(t *testing.T) {
cmd.ParseFlags([]string{"--config", "config.file"})
cf, req := pickConfigFile(cmd)
cf, req, skip := pickConfigFile(cmd)
assert.True(t, req)
assert.False(t, skip)
assert.Equal(t, "config.file", cf)

t.Setenv("GOMPLATE_CONFIG", "ignored.yaml")
cf, req = pickConfigFile(cmd)
cf, req, skip = pickConfigFile(cmd)
assert.True(t, req)
assert.False(t, skip)
assert.Equal(t, "config.file", cf)
})

t.Run("--config flag with empty value should skip reading", func(t *testing.T) {
cmd.ParseFlags([]string{"--config", ""})
cf, req, skip := pickConfigFile(cmd)
assert.False(t, req)
assert.True(t, skip)
assert.Equal(t, "", cf)
})

t.Run("GOMPLATE_CONFIG env var with empty value should skip reading", func(t *testing.T) {
t.Setenv("GOMPLATE_CONFIG", "")
cf, req, skip := pickConfigFile(cmd)
assert.False(t, req)
assert.True(t, skip)
assert.Equal(t, "", cf)
})
}

func TestApplyEnvVars(t *testing.T) {
Expand Down
20 changes: 13 additions & 7 deletions internal/datafs/getenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,36 @@ func ExpandEnvFsys(fsys fs.FS, s string) string {

// GetenvFsys - a convenience function intended for internal use only!
func GetenvFsys(fsys fs.FS, key string, def ...string) string {
val := getenvFile(fsys, key)
val, _ := getenvFile(fsys, key)
if val == "" && len(def) > 0 {
return def[0]
}

return val
}

func getenvFile(fsys fs.FS, key string) string {
val := os.Getenv(key)
// LookupEnvFsys - a convenience function intended for internal use only!
func LookupEnvFsys(fsys fs.FS, key string) (string, bool) {
return getenvFile(fsys, key)
}

func getenvFile(fsys fs.FS, key string) (string, bool) {
val, found := os.LookupEnv(key)
if val != "" {
return val
return val, true
}

p := os.Getenv(key + "_FILE")
if p != "" {
val, err := readFile(fsys, p)
if err != nil {
return ""
return "", false
}
return strings.TrimSpace(val)

return strings.TrimSpace(val), true
}

return ""
return "", found
}

func readFile(fsys fs.FS, p string) (string, error) {
Expand Down
14 changes: 14 additions & 0 deletions internal/tests/integration/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ func TestConfig_EnvConfigFile(t *testing.T) {
assertSuccess(t, o, e, err, "yet another alternate config")
}

func TestConfig_SkipConfigFile(t *testing.T) {
tmpDir := setupConfigTest(t)

// first set a poisoned default config to prove that it's not being read
writeFile(t, tmpDir, ".gomplate.yaml", `badyaml`)

o, e, err := cmd(t, "--config", "", "--in", "foo").withDir(tmpDir.Path()).run()
assertSuccess(t, o, e, err, "foo")

o, e, err = cmd(t, "--in", "foo").withDir(tmpDir.Path()).
withEnv("GOMPLATE_CONFIG", "").run()
assertSuccess(t, o, e, err, "foo")
}

func TestConfig_ConfigOverridesEnvDelim(t *testing.T) {
if isWindows {
t.Skip()
Expand Down
3 changes: 2 additions & 1 deletion internal/tests/integration/datasources_consul_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func setupDatasourcesConsulTest(t *testing.T) (string, *vaultClient) {
"serf_lan": `+strconv.Itoa(serfLanPort)+`,
"serf_wan": -1,
"dns": -1,
"grpc": -1
"grpc": -1,
"grpc_tls": -1
},
"connect": { "enabled": false }
}`,
Expand Down

0 comments on commit 18791a4

Please sign in to comment.