From 4363650424f5a9d582458b69bb72bf67803d11a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 10:58:35 +0000 Subject: [PATCH] Bump github.com/caarlos0/env Bumps [github.com/caarlos0/env](https://github.com/caarlos0/env) from 0.0.0-20170430215205-7110c4e2f569 to 3.5.0+incompatible. - [Release notes](https://github.com/caarlos0/env/releases) - [Commits](https://github.com/caarlos0/env/commits/v3.5.0) --- updated-dependencies: - dependency-name: github.com/caarlos0/env dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 +- vendor/github.com/caarlos0/env/.travis.yml | 6 +- vendor/github.com/caarlos0/env/README.md | 24 ++- vendor/github.com/caarlos0/env/env.go | 207 ++++++++++++++++++--- vendor/modules.txt | 2 +- 6 files changed, 218 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index c94f133..3481ecf 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/cjsaylor/jrnl go 1.12 require ( - github.com/caarlos0/env v0.0.0-20170430215205-7110c4e2f569 + github.com/caarlos0/env v3.5.0+incompatible github.com/ericaro/frontmatter v0.0.0-20141225210444-9fedef9406e4 github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.4.0 // indirect diff --git a/go.sum b/go.sum index 40e8d01..a8e475c 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,15 @@ -github.com/caarlos0/env v0.0.0-20170430215205-7110c4e2f569 h1:oy9Vz7le12lsFsBsxlkIwiziGxTZEQ/Fd6swnxXq+Mg= -github.com/caarlos0/env v0.0.0-20170430215205-7110c4e2f569/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= +github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= +github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ericaro/frontmatter v0.0.0-20141225210444-9fedef9406e4 h1:oiAMKnBLTEddU4iszyKbHft09X9tE49oO5SeJ+S3pvw= github.com/ericaro/frontmatter v0.0.0-20141225210444-9fedef9406e4/go.mod h1:Xy0DdToffIGb/ZMCwM5zFgIQOrVh0cKvNABpKRJYo1w= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= diff --git a/vendor/github.com/caarlos0/env/.travis.yml b/vendor/github.com/caarlos0/env/.travis.yml index d76f9df..5a5a2c8 100644 --- a/vendor/github.com/caarlos0/env/.travis.yml +++ b/vendor/github.com/caarlos0/env/.travis.yml @@ -1,8 +1,12 @@ language: go go: - - 1.4 - 1.5 - 1.6 + - 1.7 + - 1.8 + - 1.9 + - '1.10.x' + - '1.11.x' - tip before_install: - go get github.com/axw/gocov/gocov diff --git a/vendor/github.com/caarlos0/env/README.md b/vendor/github.com/caarlos0/env/README.md index 63594d5..ef50e91 100644 --- a/vendor/github.com/caarlos0/env/README.md +++ b/vendor/github.com/caarlos0/env/README.md @@ -36,6 +36,7 @@ type config struct { IsProduction bool `env:"PRODUCTION"` Hosts []string `env:"HOSTS" envSeparator:":"` Duration time.Duration `env:"DURATION"` + TempFolder string `env:"TEMP_FOLDER" envDefault:"${HOME}/tmp" envExpand:"true"` } func main() { @@ -57,19 +58,23 @@ $ PRODUCTION=true HOSTS="host1:host2:host3" DURATION=1s go run examples/first.go ## Supported types and defaults -The library has support for the following types: +The library has built-in support for the following types: * `string` * `int` +* `uint` * `int64` * `bool` * `float32` * `float64` +* `time.Duration` * `[]string` * `[]int` * `[]bool` * `[]float32` * `[]float64` +* `[]time.Duration` +* .. or use/define a [custom parser func](#custom-parser-funcs) for any other type If you set the `envDefault` tag for something, this value will be used in the case of absence of it in the environment. If you don't do that AND the @@ -79,6 +84,23 @@ and `0` for `int`s. By default, slice types will split the environment value on `,`; you can change this behavior by setting the `envSeparator` tag. +If you set the `envExpand` tag, environment variables (either in `${var}` or `$var` format) +in the string will be replaced according with the actual value of the variable. + +## Custom Parser Funcs + +If you have a type that is not supported out of the box by the lib, you are able +to use (or define) and pass custom parsers (and their associated `reflect.Type`) to the +`env.ParseWithFuncs()` function. + +In addition to accepting a struct pointer (same as `Parse()`), this function also +accepts a `env.CustomParsers` arg that under the covers is a `map[reflect.Type]env.ParserFunc`. + +To see what this looks like in practice, take a look at the [commented block in the example](https://github.com/caarlos0/env/blob/master/examples/first.go#L35-L39). + +`env` also ships with some pre-built custom parser funcs for common types. You +can check them out [here](parsers/). + ## Required fields The `env` tag option `required` (e.g., `env:"tagKey,required"`) can be added diff --git a/vendor/github.com/caarlos0/env/env.go b/vendor/github.com/caarlos0/env/env.go index d3de4a5..9e29045 100644 --- a/vendor/github.com/caarlos0/env/env.go +++ b/vendor/github.com/caarlos0/env/env.go @@ -1,7 +1,9 @@ package env import ( + "encoding" "errors" + "fmt" "os" "reflect" "strconv" @@ -17,15 +19,26 @@ var ( ErrUnsupportedType = errors.New("Type is not supported") // ErrUnsupportedSliceType if the slice element type is not supported by env ErrUnsupportedSliceType = errors.New("Unsupported slice type") + // OnEnvVarSet is an optional convenience callback, such as for logging purposes. + // If not nil, it's called after successfully setting the given field from the given value. + OnEnvVarSet func(reflect.StructField, string) // Friendly names for reflect types - sliceOfInts = reflect.TypeOf([]int(nil)) - sliceOfInt64s = reflect.TypeOf([]int64(nil)) - sliceOfStrings = reflect.TypeOf([]string(nil)) - sliceOfBools = reflect.TypeOf([]bool(nil)) - sliceOfFloat32s = reflect.TypeOf([]float32(nil)) - sliceOfFloat64s = reflect.TypeOf([]float64(nil)) + sliceOfInts = reflect.TypeOf([]int(nil)) + sliceOfInt64s = reflect.TypeOf([]int64(nil)) + sliceOfUint64s = reflect.TypeOf([]uint64(nil)) + sliceOfStrings = reflect.TypeOf([]string(nil)) + sliceOfBools = reflect.TypeOf([]bool(nil)) + sliceOfFloat32s = reflect.TypeOf([]float32(nil)) + sliceOfFloat64s = reflect.TypeOf([]float64(nil)) + sliceOfDurations = reflect.TypeOf([]time.Duration(nil)) ) +// CustomParsers is a friendly name for the type that `ParseWithFuncs()` accepts +type CustomParsers map[reflect.Type]ParserFunc + +// ParserFunc defines the signature of a function that can be used within `CustomParsers` +type ParserFunc func(v string) (interface{}, error) + // Parse parses a struct containing `env` tags and loads its values from // environment variables. func Parse(v interface{}) error { @@ -37,15 +50,38 @@ func Parse(v interface{}) error { if ref.Kind() != reflect.Struct { return ErrNotAStructPtr } - return doParse(ref) + return doParse(ref, make(map[reflect.Type]ParserFunc, 0)) +} + +// ParseWithFuncs is the same as `Parse` except it also allows the user to pass +// in custom parsers. +func ParseWithFuncs(v interface{}, funcMap CustomParsers) error { + ptrRef := reflect.ValueOf(v) + if ptrRef.Kind() != reflect.Ptr { + return ErrNotAStructPtr + } + ref := ptrRef.Elem() + if ref.Kind() != reflect.Struct { + return ErrNotAStructPtr + } + return doParse(ref, funcMap) } -func doParse(ref reflect.Value) error { +func doParse(ref reflect.Value, funcMap CustomParsers) error { refType := ref.Type() var errorList []string for i := 0; i < refType.NumField(); i++ { - value, err := get(refType.Field(i)) + refField := ref.Field(i) + if reflect.Ptr == refField.Kind() && !refField.IsNil() && refField.CanSet() { + err := Parse(refField.Interface()) + if nil != err { + return err + } + continue + } + refTypeField := refType.Field(i) + value, err := get(refTypeField) if err != nil { errorList = append(errorList, err.Error()) continue @@ -53,10 +89,13 @@ func doParse(ref reflect.Value) error { if value == "" { continue } - if err := set(ref.Field(i), refType.Field(i), value); err != nil { + if err := set(refField, refTypeField, value, funcMap); err != nil { errorList = append(errorList, err.Error()) continue } + if OnEnvVarSet != nil { + OnEnvVarSet(refTypeField, value) + } } if len(errorList) == 0 { return nil @@ -75,6 +114,11 @@ func get(field reflect.StructField) (string, error) { defaultValue := field.Tag.Get("envDefault") val = getOr(key, defaultValue) + expandVar := field.Tag.Get("envExpand") + if strings.ToLower(expandVar) == "true" { + val = os.ExpandEnv(val) + } + if len(opts) > 0 { for _, opt := range opts { // The only option supported is "required". @@ -84,7 +128,7 @@ func get(field reflect.StructField) (string, error) { case "required": val, err = getRequired(key) default: - err = errors.New("Env tag option " + opt + " not supported.") + err = fmt.Errorf("env tag option %q not supported", opt) } } } @@ -99,22 +143,33 @@ func parseKeyForOption(key string) (string, []string) { } func getRequired(key string) (string, error) { - if value := os.Getenv(key); value != "" { + if value, ok := os.LookupEnv(key); ok { return value, nil } - // We do not use fmt.Errorf to avoid another import. - return "", errors.New("Required environment variable " + key + " is not set") + return "", fmt.Errorf("required environment variable %q is not set", key) } func getOr(key, defaultValue string) string { - value := os.Getenv(key) - if value != "" { + value, ok := os.LookupEnv(key) + if ok { return value } return defaultValue } -func set(field reflect.Value, refType reflect.StructField, value string) error { +func set(field reflect.Value, refType reflect.StructField, value string, funcMap CustomParsers) error { + // use custom parser if configured for this type + parserFunc, ok := funcMap[refType.Type] + if ok { + val, err := parserFunc(value) + if err != nil { + return fmt.Errorf("Custom parser error: %v", err) + } + field.Set(reflect.ValueOf(val)) + return nil + } + + // fall back to built-in parsers switch field.Kind() { case reflect.Slice: separator := refType.Tag.Get("envSeparator") @@ -133,6 +188,12 @@ func set(field reflect.Value, refType reflect.StructField, value string) error { return err } field.SetInt(intValue) + case reflect.Uint: + uintValue, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return err + } + field.SetUint(uintValue) case reflect.Float32: v, err := strconv.ParseFloat(value, 32) if err != nil { @@ -159,8 +220,14 @@ func set(field reflect.Value, refType reflect.StructField, value string) error { } field.SetInt(intValue) } + case reflect.Uint64: + uintValue, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return err + } + field.SetUint(uintValue) default: - return ErrUnsupportedType + return handleTextUnmarshaler(field, value) } return nil } @@ -187,7 +254,12 @@ func handleSlice(field reflect.Value, value, separator string) error { return err } field.Set(reflect.ValueOf(int64Data)) - + case sliceOfUint64s: + uint64Data, err := parseUint64s(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(uint64Data)) case sliceOfFloat32s: data, err := parseFloat32s(splitData) if err != nil { @@ -206,14 +278,46 @@ func handleSlice(field reflect.Value, value, separator string) error { return err } field.Set(reflect.ValueOf(boolData)) + case sliceOfDurations: + durationData, err := parseDurations(splitData) + if err != nil { + return err + } + field.Set(reflect.ValueOf(durationData)) default: - return ErrUnsupportedSliceType + elemType := field.Type().Elem() + // Ensure we test *type as we can always address elements in a slice. + if elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + } + if _, ok := reflect.New(elemType).Interface().(encoding.TextUnmarshaler); !ok { + return ErrUnsupportedSliceType + } + return parseTextUnmarshalers(field, splitData) + } return nil } +func handleTextUnmarshaler(field reflect.Value, value string) error { + if reflect.Ptr == field.Kind() { + if field.IsNil() { + field.Set(reflect.New(field.Type().Elem())) + } + } else if field.CanAddr() { + field = field.Addr() + } + + tm, ok := field.Interface().(encoding.TextUnmarshaler) + if !ok { + return ErrUnsupportedType + } + + return tm.UnmarshalText([]byte(value)) +} + func parseInts(data []string) ([]int, error) { - var intSlice []int + intSlice := make([]int, 0, len(data)) for _, v := range data { intValue, err := strconv.ParseInt(v, 10, 32) @@ -226,7 +330,7 @@ func parseInts(data []string) ([]int, error) { } func parseInt64s(data []string) ([]int64, error) { - var intSlice []int64 + intSlice := make([]int64, 0, len(data)) for _, v := range data { intValue, err := strconv.ParseInt(v, 10, 64) @@ -238,8 +342,21 @@ func parseInt64s(data []string) ([]int64, error) { return intSlice, nil } +func parseUint64s(data []string) ([]uint64, error) { + var uintSlice []uint64 + + for _, v := range data { + uintValue, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return nil, err + } + uintSlice = append(uintSlice, uint64(uintValue)) + } + return uintSlice, nil +} + func parseFloat32s(data []string) ([]float32, error) { - var float32Slice []float32 + float32Slice := make([]float32, 0, len(data)) for _, v := range data { data, err := strconv.ParseFloat(v, 32) @@ -252,7 +369,7 @@ func parseFloat32s(data []string) ([]float32, error) { } func parseFloat64s(data []string) ([]float64, error) { - var float64Slice []float64 + float64Slice := make([]float64, 0, len(data)) for _, v := range data { data, err := strconv.ParseFloat(v, 64) @@ -265,7 +382,7 @@ func parseFloat64s(data []string) ([]float64, error) { } func parseBools(data []string) ([]bool, error) { - var boolSlice []bool + boolSlice := make([]bool, 0, len(data)) for _, v := range data { bvalue, err := strconv.ParseBool(v) @@ -277,3 +394,43 @@ func parseBools(data []string) ([]bool, error) { } return boolSlice, nil } + +func parseDurations(data []string) ([]time.Duration, error) { + durationSlice := make([]time.Duration, 0, len(data)) + + for _, v := range data { + dvalue, err := time.ParseDuration(v) + if err != nil { + return nil, err + } + + durationSlice = append(durationSlice, dvalue) + } + return durationSlice, nil +} + +func parseTextUnmarshalers(field reflect.Value, data []string) error { + s := len(data) + elemType := field.Type().Elem() + slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s) + for i, v := range data { + sv := slice.Index(i) + kind := sv.Kind() + if kind == reflect.Ptr { + sv = reflect.New(elemType.Elem()) + } else { + sv = sv.Addr() + } + tm := sv.Interface().(encoding.TextUnmarshaler) + if err := tm.UnmarshalText([]byte(v)); err != nil { + return err + } + if kind == reflect.Ptr { + slice.Index(i).Set(sv) + } + } + + field.Set(slice) + + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index dc99a4c..5e9b096 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/caarlos0/env v0.0.0-20170430215205-7110c4e2f569 +# github.com/caarlos0/env v3.5.0+incompatible github.com/caarlos0/env # github.com/ericaro/frontmatter v0.0.0-20141225210444-9fedef9406e4 github.com/ericaro/frontmatter