diff options
| author | Illia Volochii <[email protected]> | 2018-04-26 21:10:44 +0300 |
|---|---|---|
| committer | Illia Volochii <[email protected]> | 2018-04-26 21:10:44 +0300 |
| commit | 75bf1a1525e860418b617b6440255fddd2eed205 (patch) | |
| tree | 7d0e517277a2f398fecaa7dfb4ad874274277c8d | |
| parent | 074ee5f759999d103724b5594e33901adeb28e73 (diff) | |
Fix providing multiple values via environment variables
| -rw-r--r-- | README.md | 16 | ||||
| -rw-r--r-- | parse.go | 19 | ||||
| -rw-r--r-- | parse_test.go | 36 |
3 files changed, 70 insertions, 1 deletions
@@ -94,6 +94,22 @@ $ NUM_WORKERS=4 ./example Workers: 4 ``` +You should use a JSON array of strings (value will be converted if +necessary) in the case of multiple values: + +```go +var args struct { + Workers []int `arg:"env"` +} +arg.MustParse(&args) +fmt.Println("Workers:", args.Workers) +``` + +``` +$ WORKERS='["1", "99"]' ./example +Workers: [1 99] +``` + ### Usage strings ```go var args struct { @@ -2,6 +2,7 @@ package arg import ( "encoding" + "encoding/json" "errors" "fmt" "os" @@ -275,7 +276,23 @@ func process(specs []*spec, args []string) error { } if spec.env != "" { if value, found := os.LookupEnv(spec.env); found { - err := scalar.ParseValue(spec.dest, value) + var err error + if spec.multiple { + // expect a JSON array of strings in an environment + // variable in the case of multiple values + var values []string + err = json.Unmarshal([]byte(value), &values) + if err != nil { + return fmt.Errorf( + "error processing environment variable %s (it should be a JSON array of strings):\n%v", + spec.env, + err, + ) + } + err = setSlice(spec.dest, values, !spec.separate) + } else { + err = scalar.ParseValue(spec.dest, value) + } if err != nil { return fmt.Errorf("error processing environment variable %s: %v", spec.env, err) } diff --git a/parse_test.go b/parse_test.go index 1461c02..579d8b7 100644 --- a/parse_test.go +++ b/parse_test.go @@ -580,6 +580,42 @@ func TestEnvironmentVariableRequired(t *testing.T) { assert.Equal(t, "bar", args.Foo) } +func TestEnvironmentVariableSliceArgumentString(t *testing.T) { + var args struct { + Foo []string `arg:"env"` + } + setenv(t, "FOO", "[\"bar\", \"baz\"]") + MustParse(&args) + assert.Equal(t, []string{"bar", "baz"}, args.Foo) +} + +func TestEnvironmentVariableSliceArgumentInteger(t *testing.T) { + var args struct { + Foo []int `arg:"env"` + } + setenv(t, "FOO", "[\"1\", \"99\"]") + MustParse(&args) + assert.Equal(t, []int{1, 99}, args.Foo) +} + +func TestEnvironmentVariableSliceArgumentFloat(t *testing.T) { + var args struct { + Foo []float32 `arg:"env"` + } + setenv(t, "FOO", "[\"1.1\", \"99.9\"]") + MustParse(&args) + assert.Equal(t, []float32{1.1, 99.9}, args.Foo) +} + +func TestEnvironmentVariableSliceArgumentBool(t *testing.T) { + var args struct { + Foo []bool `arg:"env"` + } + setenv(t, "FOO", "[\"true\", \"false\", \"0\", \"1\"]") + MustParse(&args) + assert.Equal(t, []bool{true, false, false, true}, args.Foo) +} + type textUnmarshaler struct { val int } |
