From b14df87162f70ea8976fb64865895e24fdc7b357 Mon Sep 17 00:00:00 2001 From: pr0n1x Date: Tue, 16 Jul 2024 13:45:02 +0700 Subject: [PATCH] Completed fix of issue #148 with respecting of env-prefix and partially saved backward compatibility by using new tag no_pfx --- envconfig.go | 27 +++++++++++++++++++-------- envconfig_test.go | 23 ++++++++++++++++++++--- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/envconfig.go b/envconfig.go index 28a8561..a7285da 100644 --- a/envconfig.go +++ b/envconfig.go @@ -121,14 +121,28 @@ func gatherInfo(prefix string, spec interface{}) ([]varInfo, error) { if prefix != "" { info.Key = fmt.Sprintf("%s_%s", prefix, info.Key) } - // If name is overridden, switch .Key and .Alt and don't forget about prefix. - // Now the overridden name is for the first attempt to find value in environment. - // The initial name is an alternative name used if the first attempt is not successful. + + // override default env-variable name with an envconfig tag if info.Alt != "" { if prefix != "" { - info.Alt = fmt.Sprintf("%s_%s", prefix, info.Alt) + noPfxPlace := ftype.Tag.Get("no_pfx") + if noPfxPlace == "key" { + // now the key name is overridden and prefixed + // alt name is not used + info.Key = info.Alt + info.Alt = "" + } else if noPfxPlace == "alt" { + // now the key name is overridden and prefixed + // and alt name is overridden name without prefix + info.Key = fmt.Sprintf("%s_%s", prefix, info.Alt) + } else { + // now key name is overridden and prefixed + // but alt is the prev key name (source struct field name) with prefix + prefixedStructFieldName := info.Key + info.Key = fmt.Sprintf("%s_%s", prefix, info.Alt) + info.Alt = prefixedStructFieldName + } } - info.Key, info.Alt = info.Alt, info.Key } info.Key = strings.ToUpper(info.Key) info.Alt = strings.ToUpper(info.Alt) @@ -211,9 +225,6 @@ func Process(prefix string, spec interface{}) error { if !ok && def == "" { if isTrue(req) { key := info.Key - if info.Alt != "" { - key = info.Alt - } return fmt.Errorf("required key %s missing value", key) } continue diff --git a/envconfig_test.go b/envconfig_test.go index c184fc3..6446b8c 100644 --- a/envconfig_test.go +++ b/envconfig_test.go @@ -54,14 +54,14 @@ type Specification struct { SomePointerWithDefault *string `default:"foo2baz" desc:"foorbar is the word"` MultiWordVarWithAlt string `envconfig:"MULTI_WORD_VAR_WITH_ALT" desc:"what alt"` MultiWordVarWithLowerCaseAlt string `envconfig:"multi_word_var_with_lower_case_alt"` - NoPrefixWithAlt string `envconfig:"SERVICE_HOST"` + NoPrefixWithAlt string `envconfig:"SERVICE_HOST" no_pfx:"alt"` DefaultVar string `default:"foobar"` RequiredVar string `required:"True"` - NoPrefixDefault string `envconfig:"BROKER" default:"127.0.0.1"` + NoPrefixDefault string `envconfig:"BROKER" default:"127.0.0.1" no_pfx:"alt"` RequiredDefault string `required:"true" default:"foo2bar"` Ignored string `ignored:"true"` NestedSpecification struct { - Property string `envconfig:"inner"` + Property string `envconfig:"inner" no_pfx:"alt"` PropertyWithDefault string `default:"fuzzybydefault"` } `envconfig:"outer"` AfterNested string @@ -804,6 +804,23 @@ func TestErrorMessageForRequiredAltVar(t *testing.T) { t.Error("no failure when missing required variable") } + if !strings.Contains(err.Error(), " ENV_CONFIG_BAR ") { + t.Errorf("expected error message to contain BAR, got \"%v\"", err) + } +} + +func TestErrorMessageForRequiredOverriddenKeyVar(t *testing.T) { + var s struct { + Foo string `envconfig:"BAR" required:"true" no_pfx:"key"` + } + + os.Clearenv() + err := Process("env_config", &s) + + if err == nil { + t.Error("no failure when missing required variable") + } + if !strings.Contains(err.Error(), " BAR ") { t.Errorf("expected error message to contain BAR, got \"%v\"", err) }