From fbe8d48e4badf293012666e8d7a9065c0c9e633f Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Thu, 16 Apr 2020 22:19:21 +1000 Subject: [PATCH] Convert env management to a resolver. This ensures that hooks correctly detect when values are set via environment variables. Fixes #73. --- env.go | 21 +++++++++++++++++++++ kong.go | 1 + kong_test.go | 13 +++++++++++++ model.go | 11 ----------- 4 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 env.go diff --git a/env.go b/env.go new file mode 100644 index 0000000..aeee8d3 --- /dev/null +++ b/env.go @@ -0,0 +1,21 @@ +package kong + +import ( + "os" +) + +// EnvarResolver resolves values from environment variables. +// +// It is installed by default. Use ClearResolvers() to disable this. +func EnvarResolver() Resolver { + return ResolverFunc(func(context *Context, parent *Path, flag *Flag) (interface{}, error) { + if flag.Tag.Env == "" { + return nil, nil + } + envar := os.Getenv(flag.Tag.Env) + if envar != "" { + return envar, nil + } + return nil, nil + }) +} diff --git a/kong.go b/kong.go index 3a61567..017cf50 100644 --- a/kong.go +++ b/kong.go @@ -71,6 +71,7 @@ func New(grammar interface{}, options ...Option) (*Kong, error) { vars: Vars{}, bindings: bindings{}, helpFormatter: DefaultHelpValueFormatter, + resolvers: []Resolver{EnvarResolver()}, } options = append(options, Bind(k)) diff --git a/kong_test.go b/kong_test.go index b55093a..57f15b6 100644 --- a/kong_test.go +++ b/kong_test.go @@ -675,6 +675,19 @@ func TestHooksCalledForDefault(t *testing.T) { require.Equal(t, []string{"before:default", "after:default"}, ctx.values) } +func TestHooksCalledForEnv(t *testing.T) { + var cli struct { + Flag hookValue `env:"FLAG"` + } + defer tempEnv(envMap{"FLAG": "flagged"})() + + ctx := &hookContext{} + _, err := mustNew(t, &cli, kong.Bind(ctx)).Parse(nil) + require.NoError(t, err) + require.Equal(t, "flagged", string(cli.Flag)) + require.Equal(t, []string{"before:", "after:flagged"}, ctx.values) +} + func TestEnum(t *testing.T) { var cli struct { Flag string `enum:"a,b,c"` diff --git a/model.go b/model.go index 8023dce..c98625c 100644 --- a/model.go +++ b/model.go @@ -3,7 +3,6 @@ package kong import ( "fmt" "math" - "os" "reflect" "strconv" "strings" @@ -326,16 +325,6 @@ func (v *Value) ApplyDefault() error { // Does not include resolvers. func (v *Value) Reset() error { v.Target.Set(reflect.Zero(v.Target.Type())) - if v.Tag.Env != "" { - envar := os.Getenv(v.Tag.Env) - if envar != "" { - err := v.Parse(ScanFromTokens(Token{Type: FlagValueToken, Value: envar}), v.Target) - if err != nil { - return fmt.Errorf("%s (from envar %s=%q)", err, v.Tag.Env, envar) - } - return nil - } - } if v.Default != "" { return v.Parse(ScanFromTokens(Token{Type: FlagValueToken, Value: v.Default}), v.Target) }