diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/cmd/config.go | 5 | ||||
| -rw-r--r-- | internal/cmd/main.go | 2 | ||||
| -rw-r--r-- | internal/config/configfile.go | 14 | ||||
| -rw-r--r-- | internal/config/configfile_test.go | 1 | ||||
| -rw-r--r-- | internal/tests/integration/config_test.go | 20 | ||||
| -rw-r--r-- | internal/tests/integration/integration_test.go | 21 | ||||
| -rw-r--r-- | internal/tests/integration/missing_key_test.go | 25 |
7 files changed, 86 insertions, 2 deletions
diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 1fae0346..7f071417 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -160,6 +160,11 @@ func cobraConfig(cmd *cobra.Command, args []string) (cfg *config.Config, err err return nil, err } + cfg.MissingKey, err = getString(cmd, "missing-key") + if err != nil { + return nil, err + } + ds, err := getStringSlice(cmd, "datasource") if err != nil { return nil, err diff --git a/internal/cmd/main.go b/internal/cmd/main.go index 7533f855..3cce83e2 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -156,6 +156,8 @@ func InitFlags(command *cobra.Command) { command.Flags().String("left-delim", ldDefault, "override the default left-`delimiter` [$GOMPLATE_LEFT_DELIM]") command.Flags().String("right-delim", rdDefault, "override the default right-`delimiter` [$GOMPLATE_RIGHT_DELIM]") + command.Flags().String("missing-key", "error", "Control the behavior during execution if a map is indexed with a key that is not present in the map. error (default) - return an error, zero - fallback to zero value, default/invalid - print <no value>") + command.Flags().Bool("experimental", false, "enable experimental features [$GOMPLATE_EXPERIMENTAL]") command.Flags().BoolP("verbose", "V", false, "output extra information about what gomplate is doing") diff --git a/internal/config/configfile.go b/internal/config/configfile.go index 712d7310..1ed266b3 100644 --- a/internal/config/configfile.go +++ b/internal/config/configfile.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "golang.org/x/exp/slices" + "github.com/hairyhenderson/gomplate/v4/internal/datafs" "github.com/hairyhenderson/gomplate/v4/internal/iohelpers" "github.com/hairyhenderson/yaml" @@ -60,6 +62,8 @@ type Config struct { LDelim string `yaml:"leftDelim,omitempty"` RDelim string `yaml:"rightDelim,omitempty"` + MissingKey string `yaml:"missingKey,omitempty"` + PostExec []string `yaml:"postExec,omitempty,flow"` PluginTimeout time.Duration `yaml:"pluginTimeout,omitempty"` @@ -465,6 +469,13 @@ func (c Config) Validate() (err error) { } } + if err == nil { + missingKeyValues := []string{"", "error", "zero", "default", "invalid"} + if !slices.Contains(missingKeyValues, c.MissingKey) { + err = fmt.Errorf("not allowed value for the 'missing-key' flag: %s. Allowed values: %s", c.MissingKey, strings.Join(missingKeyValues, ",")) + } + } + return err } @@ -533,6 +544,9 @@ func (c *Config) ApplyDefaults() { if c.RDelim == "" { c.RDelim = "}}" } + if c.MissingKey == "" { + c.MissingKey = "error" + } if c.ExecPipe { pipe := &bytes.Buffer{} diff --git a/internal/config/configfile_test.go b/internal/config/configfile_test.go index e99fc8b4..449c379b 100644 --- a/internal/config/configfile_test.go +++ b/internal/config/configfile_test.go @@ -539,6 +539,7 @@ inputFiles: ['-'] outputFiles: ['-'] leftDelim: '{{' rightDelim: '}}' +missingKey: error pluginTimeout: 5s ` assert.Equal(t, expected, c.String()) diff --git a/internal/tests/integration/config_test.go b/internal/tests/integration/config_test.go index d56616ae..00ab4f89 100644 --- a/internal/tests/integration/config_test.go +++ b/internal/tests/integration/config_test.go @@ -275,3 +275,23 @@ templates: o, e, err := cmd(t).withDir(tmpDir.Path()).run() assertSuccess(t, o, e, err, "12345") } + +func TestConfig_MissingKeyDefault(t *testing.T) { + tmpDir := setupConfigTest(t) + writeConfig(t, tmpDir, `inputFiles: [in] +missingKey: default +`) + writeFile(t, tmpDir, "in", `{{ .name }}`) + + o, e, err := cmd(t).withDir(tmpDir.Path()).run() + assertSuccess(t, o, e, err, `<no value>`) +} + +func TestConfig_MissingKeyNotDefined(t *testing.T) { + tmpDir := setupConfigTest(t) + writeConfig(t, tmpDir, `inputFiles: [in]`) + writeFile(t, tmpDir, "in", `{{ .name }}`) + + o, e, err := cmd(t).withDir(tmpDir.Path()).run() + assertFailed(t, o, e, err, `map has no entry for key \"name\"`) +} diff --git a/internal/tests/integration/integration_test.go b/internal/tests/integration/integration_test.go index bc79862a..a57d8d0b 100644 --- a/internal/tests/integration/integration_test.go +++ b/internal/tests/integration/integration_test.go @@ -25,13 +25,22 @@ import ( const isWindows = runtime.GOOS == "windows" // a convenience... -func inOutTest(t *testing.T, i, o string) { +func inOutTest(t *testing.T, i, o string, args ...string) { t.Helper() - stdout, stderr, err := cmd(t, "-i", i).run() + args = append(args, "-i", i) + stdout, stderr, err := cmd(t, args...).run() assertSuccess(t, stdout, stderr, err, o) } +func inOutContainsError(t *testing.T, i, e string, args ...string) { + t.Helper() + + args = append(args, "-i", i) + stdout, stderr, err := cmd(t, args...).run() + assertFailed(t, stdout, stderr, err, e) +} + func inOutTestExperimental(t *testing.T, i, o string) { t.Helper() @@ -56,6 +65,14 @@ func assertSuccess(t *testing.T, o, e string, err error, expected string) { require.NoError(t, err) } +func assertFailed(t *testing.T, o, e string, err error, expected string) { + t.Helper() + + assert.Contains(t, e, expected) + assert.Equal(t, "", o) + require.Error(t, err) +} + // mirrorHandler - reflects back the HTTP headers from the request func mirrorHandler(w http.ResponseWriter, r *http.Request) { type Req struct { diff --git a/internal/tests/integration/missing_key_test.go b/internal/tests/integration/missing_key_test.go new file mode 100644 index 00000000..076ff236 --- /dev/null +++ b/internal/tests/integration/missing_key_test.go @@ -0,0 +1,25 @@ +package integration + +import ( + "testing" +) + +func TestMissingKey_Default(t *testing.T) { + inOutTest(t, `{{ .name }}`, "<no value>", "--missing-key", "default") +} + +func TestMissingKey_Zero(t *testing.T) { + inOutTest(t, `{{ .name }}`, "<no value>", "--missing-key", "zero") +} + +func TestMissingKey_Fallback(t *testing.T) { + inOutTest(t, `{{ .name | default "Alex" }}`, "Alex", "--missing-key", "default") +} + +func TestMissingKey_NotSpecified(t *testing.T) { + inOutContainsError(t, `{{ .name | default "Alex" }}`, `map has no entry for key \"name\"`) +} + +func TestMissingKey_Error(t *testing.T) { + inOutContainsError(t, `{{ .name | default "Alex" }}`, `map has no entry for key \"name\"`, "--missing-key", "error") +} |
