Merge pull request #65 from illia-v/env_multiple_values
Fix providing multiple values via environment variables
This commit is contained in:
commit
f7c0423bd1
15
README.md
15
README.md
|
@ -94,6 +94,21 @@ $ NUM_WORKERS=4 ./example
|
|||
Workers: 4
|
||||
```
|
||||
|
||||
You can provide multiple values using the CSV (RFC 4180) format:
|
||||
|
||||
```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 {
|
||||
|
|
26
parse.go
26
parse.go
|
@ -2,6 +2,7 @@ package arg
|
|||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -275,9 +276,28 @@ func process(specs []*spec, args []string) error {
|
|||
}
|
||||
if spec.env != "" {
|
||||
if value, found := os.LookupEnv(spec.env); found {
|
||||
err := scalar.ParseValue(spec.dest, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error processing environment variable %s: %v", spec.env, err)
|
||||
if spec.multiple {
|
||||
// expect a CSV string in an environment
|
||||
// variable in the case of multiple values
|
||||
values, err := csv.NewReader(strings.NewReader(value)).Read()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"error reading a CSV string from environment variable %s with multiple values: %v",
|
||||
spec.env,
|
||||
err,
|
||||
)
|
||||
}
|
||||
if err = setSlice(spec.dest, values, !spec.separate); err != nil {
|
||||
return fmt.Errorf(
|
||||
"error processing environment variable %s with multiple values: %v",
|
||||
spec.env,
|
||||
err,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if err := scalar.ParseValue(spec.dest, value); err != nil {
|
||||
return fmt.Errorf("error processing environment variable %s: %v", spec.env, err)
|
||||
}
|
||||
}
|
||||
spec.wasPresent = true
|
||||
}
|
||||
|
|
|
@ -580,6 +580,60 @@ 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, qux\"")
|
||||
MustParse(&args)
|
||||
assert.Equal(t, []string{"bar", "baz, qux"}, 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)
|
||||
}
|
||||
|
||||
func TestEnvironmentVariableSliceArgumentWrongCsv(t *testing.T) {
|
||||
var args struct {
|
||||
Foo []int `arg:"env"`
|
||||
}
|
||||
setenv(t, "FOO", "1,99\"")
|
||||
err := Parse(&args)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestEnvironmentVariableSliceArgumentWrongType(t *testing.T) {
|
||||
var args struct {
|
||||
Foo []bool `arg:"env"`
|
||||
}
|
||||
setenv(t, "FOO", "one,two")
|
||||
err := Parse(&args)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
type textUnmarshaler struct {
|
||||
val int
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue