snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
19
internal/config/envconfig/LICENSE
Normal file
19
internal/config/envconfig/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Kelsey Hightower
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
2
internal/config/envconfig/MAINTAINERS
Normal file
2
internal/config/envconfig/MAINTAINERS
Normal file
@@ -0,0 +1,2 @@
|
||||
Kelsey Hightower kelsey.hightower@gmail.com github.com/kelseyhightower
|
||||
Travis Parker travis.parker@gmail.com github.com/teepark
|
||||
5
internal/config/envconfig/README.md
Normal file
5
internal/config/envconfig/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# envconfig
|
||||
|
||||
This is a fork of https://github.com/kelseyhightower/envconfig to make it fit Centrifugo, original license left unchanged.
|
||||
|
||||
There are changes to have access to VarInfo and to avoid using defaults for non-zero values.
|
||||
8
internal/config/envconfig/doc.go
Normal file
8
internal/config/envconfig/doc.go
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
|
||||
// Use of this source code is governed by the MIT License that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
// Package envconfig implements decoding of environment variables based on a user
|
||||
// defined specification. A typical use is using environment variables for
|
||||
// configuration settings.
|
||||
package envconfig
|
||||
7
internal/config/envconfig/env_os.go
Normal file
7
internal/config/envconfig/env_os.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build appengine || go1.5
|
||||
|
||||
package envconfig
|
||||
|
||||
import "os"
|
||||
|
||||
var lookupEnv = os.LookupEnv
|
||||
8
internal/config/envconfig/env_syscall.go
Normal file
8
internal/config/envconfig/env_syscall.go
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build !appengine && !go1.5
|
||||
// +build !appengine,!go1.5
|
||||
|
||||
package envconfig
|
||||
|
||||
import "syscall"
|
||||
|
||||
var lookupEnv = syscall.Getenv
|
||||
425
internal/config/envconfig/envconfig.go
Normal file
425
internal/config/envconfig/envconfig.go
Normal file
@@ -0,0 +1,425 @@
|
||||
// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
|
||||
// Use of this source code is governed by the MIT License that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
package envconfig
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrInvalidSpecification indicates that a specification is of the wrong type.
|
||||
var ErrInvalidSpecification = errors.New("specification must be a struct pointer")
|
||||
|
||||
var gatherRegexp = regexp.MustCompile("([^A-Z]+|[A-Z]+[^A-Z]+|[A-Z]+)")
|
||||
var acronymRegexp = regexp.MustCompile("([A-Z]+)([A-Z][^A-Z]+)")
|
||||
|
||||
// A ParseError occurs when an environment variable cannot be converted to
|
||||
// the type required by a struct field during assignment.
|
||||
type ParseError struct {
|
||||
KeyName string
|
||||
FieldName string
|
||||
TypeName string
|
||||
Value string
|
||||
Err error
|
||||
}
|
||||
|
||||
// Decoder has the same semantics as Setter, but takes higher precedence.
|
||||
// It is provided for historical compatibility.
|
||||
type Decoder interface {
|
||||
Decode(value string) error
|
||||
}
|
||||
|
||||
// Setter is implemented by types can self-deserialize values.
|
||||
// Any type that implements flag.Value also implements Setter.
|
||||
type Setter interface {
|
||||
Set(value string) error
|
||||
}
|
||||
|
||||
func (e *ParseError) Error() string {
|
||||
return fmt.Sprintf("envconfig.Process: assigning %[1]s to %[2]s: converting '%[3]s' to type %[4]s. details: %[5]s", e.KeyName, e.FieldName, e.Value, e.TypeName, e.Err)
|
||||
}
|
||||
|
||||
// VarInfo maintains information about the configuration variable
|
||||
type VarInfo struct {
|
||||
Name string
|
||||
Alt string
|
||||
Key string
|
||||
NestedKey string
|
||||
Field reflect.Value
|
||||
Tags reflect.StructTag
|
||||
|
||||
NonZeroInFile bool
|
||||
}
|
||||
|
||||
// GatherInfo gathers information about the specified struct
|
||||
func gatherInfo(prefix string, spec interface{}) ([]VarInfo, error) {
|
||||
s := reflect.ValueOf(spec)
|
||||
|
||||
if s.Kind() != reflect.Pointer {
|
||||
return nil, ErrInvalidSpecification
|
||||
}
|
||||
s = s.Elem()
|
||||
if s.Kind() != reflect.Struct {
|
||||
return nil, ErrInvalidSpecification
|
||||
}
|
||||
typeOfSpec := s.Type()
|
||||
|
||||
// over allocate an info array, we will extend if needed later
|
||||
infos := make([]VarInfo, 0, s.NumField())
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
f := s.Field(i)
|
||||
ftype := typeOfSpec.Field(i)
|
||||
if !f.CanSet() || isTrue(ftype.Tag.Get("ignored")) {
|
||||
continue
|
||||
}
|
||||
|
||||
for f.Kind() == reflect.Pointer {
|
||||
if f.IsNil() {
|
||||
if f.Type().Elem().Kind() != reflect.Struct {
|
||||
// nil pointer to a non-struct: leave it alone
|
||||
break
|
||||
}
|
||||
// nil pointer to struct: create a zero instance
|
||||
f.Set(reflect.New(f.Type().Elem()))
|
||||
}
|
||||
f = f.Elem()
|
||||
}
|
||||
|
||||
name := strings.ToUpper(ftype.Tag.Get("envconfig"))
|
||||
if name == "" {
|
||||
name = ftype.Name
|
||||
}
|
||||
|
||||
// Capture information about the config variable
|
||||
info := VarInfo{
|
||||
Name: name,
|
||||
Field: f,
|
||||
Tags: ftype.Tag,
|
||||
//Alt: strings.ToUpper(ftype.Tag.Get("envconfig")),
|
||||
NonZeroInFile: !f.IsZero(),
|
||||
}
|
||||
|
||||
// Default to the field name as the env var name (will be upcased)
|
||||
info.Key = info.Name
|
||||
|
||||
// Best effort to un-pick camel casing as separate words
|
||||
if isTrue(ftype.Tag.Get("split_words")) {
|
||||
words := gatherRegexp.FindAllStringSubmatch(ftype.Name, -1)
|
||||
if len(words) > 0 {
|
||||
var name []string
|
||||
for _, words := range words {
|
||||
if m := acronymRegexp.FindStringSubmatch(words[0]); len(m) == 3 {
|
||||
name = append(name, m[1], m[2])
|
||||
} else {
|
||||
name = append(name, words[0])
|
||||
}
|
||||
}
|
||||
|
||||
info.Key = strings.Join(name, "_")
|
||||
}
|
||||
}
|
||||
if info.Alt != "" {
|
||||
info.Key = info.Alt
|
||||
}
|
||||
if prefix != "" {
|
||||
info.Key = fmt.Sprintf("%s_%s", prefix, info.Key)
|
||||
}
|
||||
info.Key = strings.ToUpper(info.Key)
|
||||
|
||||
// Construct NestedKey: lowercase, without prefix.
|
||||
info.NestedKey = strings.ToLower(info.Name)
|
||||
|
||||
infos = append(infos, info)
|
||||
|
||||
if f.Kind() == reflect.Struct {
|
||||
// honor Decode if present
|
||||
if decoderFrom(f) == nil && setterFrom(f) == nil && textUnmarshaler(f) == nil && binaryUnmarshaler(f) == nil {
|
||||
innerPrefix := prefix
|
||||
if !ftype.Anonymous {
|
||||
innerPrefix = info.Key
|
||||
}
|
||||
|
||||
embeddedPtr := f.Addr().Interface()
|
||||
embeddedInfos, err := gatherInfo(innerPrefix, embeddedPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Update NestedKey for embedded fields.
|
||||
for i := range embeddedInfos {
|
||||
if !ftype.Anonymous {
|
||||
nestedPrefix := strings.ToLower(info.Name)
|
||||
embeddedInfos[i].NestedKey = nestedPrefix + "." + embeddedInfos[i].NestedKey
|
||||
}
|
||||
}
|
||||
infos = append(infos[:len(infos)-1], embeddedInfos...)
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
// CheckDisallowed checks that no environment variables with the prefix are set
|
||||
// that we don't know how or want to parse. This is likely only meaningful with
|
||||
// a non-empty prefix.
|
||||
func CheckDisallowed(prefix string, spec interface{}) error {
|
||||
infos, err := gatherInfo(prefix, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vars := make(map[string]struct{})
|
||||
for _, info := range infos {
|
||||
vars[info.Key] = struct{}{}
|
||||
}
|
||||
|
||||
if prefix != "" {
|
||||
prefix = strings.ToUpper(prefix) + "_"
|
||||
}
|
||||
|
||||
for _, env := range os.Environ() {
|
||||
if !strings.HasPrefix(env, prefix) {
|
||||
continue
|
||||
}
|
||||
v := strings.SplitN(env, "=", 2)[0]
|
||||
if _, found := vars[v]; !found {
|
||||
return fmt.Errorf("unknown environment variable %s", v)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process populates the specified struct based on environment variables
|
||||
func Process(prefix string, spec interface{}) ([]VarInfo, error) {
|
||||
return ProcessWithoutNestedKeys(prefix, spec, nil)
|
||||
}
|
||||
|
||||
// ProcessWithoutNestedKeys populates the specified struct based on environment variables
|
||||
// but excludes fields whose NestedKey is in the excludeKeys list
|
||||
func ProcessWithoutNestedKeys(prefix string, spec interface{}, excludeKeys []string) ([]VarInfo, error) {
|
||||
infos, err := gatherInfo(prefix, spec)
|
||||
|
||||
for _, info := range infos {
|
||||
// Skip processing if this key is excluded.
|
||||
if slices.Contains(excludeKeys, info.NestedKey) {
|
||||
continue
|
||||
}
|
||||
|
||||
// `os.Getenv` cannot differentiate between an explicitly set empty value
|
||||
// and an unset value. `os.LookupEnv` is preferred to `syscall.Getenv`,
|
||||
// but it is only available in go1.5 or newer. We're using Go build tags
|
||||
// here to use os.LookupEnv for >=go1.5
|
||||
value, ok := lookupEnv(info.Key)
|
||||
if !ok && info.Alt != "" {
|
||||
value, ok = lookupEnv(info.Alt)
|
||||
}
|
||||
|
||||
var defaultIsUsed bool
|
||||
def := info.Tags.Get("default")
|
||||
if def != "" && (!ok || value == "") { // Empty values are considered unset.
|
||||
value = def
|
||||
defaultIsUsed = true
|
||||
}
|
||||
|
||||
req := info.Tags.Get("required")
|
||||
if !ok && def == "" {
|
||||
if isTrue(req) {
|
||||
key := info.Key
|
||||
if info.Alt != "" {
|
||||
key = info.Alt
|
||||
}
|
||||
return nil, fmt.Errorf("required key %s missing value", key)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
err = processField(value, info.Field, defaultIsUsed)
|
||||
if err != nil {
|
||||
return nil, &ParseError{
|
||||
KeyName: info.Key,
|
||||
FieldName: info.Name,
|
||||
TypeName: info.Field.Type().String(),
|
||||
Value: value,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return infos, err
|
||||
}
|
||||
|
||||
// MustProcess is the same as Process but panics if an error occurs
|
||||
func MustProcess(prefix string, spec interface{}) {
|
||||
if _, err := Process(prefix, spec); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
const SliceSep = " "
|
||||
|
||||
func processField(value string, field reflect.Value, defaultIsUsed bool) error {
|
||||
// If the value is default but field is not zero already, we don't want to overwrite it.
|
||||
if defaultIsUsed && !field.IsZero() {
|
||||
return nil
|
||||
}
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
typ := field.Type()
|
||||
|
||||
decoder := decoderFrom(field)
|
||||
if decoder != nil {
|
||||
return decoder.Decode(value)
|
||||
}
|
||||
// look for Set method if Decode not defined
|
||||
setter := setterFrom(field)
|
||||
if setter != nil {
|
||||
return setter.Set(value)
|
||||
}
|
||||
|
||||
if t := textUnmarshaler(field); t != nil {
|
||||
return t.UnmarshalText([]byte(value))
|
||||
}
|
||||
|
||||
if b := binaryUnmarshaler(field); b != nil {
|
||||
return b.UnmarshalBinary([]byte(value))
|
||||
}
|
||||
|
||||
if typ.Kind() == reflect.Pointer {
|
||||
typ = typ.Elem()
|
||||
if field.IsNil() {
|
||||
field.Set(reflect.New(typ))
|
||||
}
|
||||
field = field.Elem()
|
||||
}
|
||||
|
||||
switch typ.Kind() {
|
||||
case reflect.String:
|
||||
field.SetString(value)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
var (
|
||||
val int64
|
||||
err error
|
||||
)
|
||||
if field.Kind() == reflect.Int64 && typ.Name() == "Duration" {
|
||||
var d time.Duration
|
||||
d, err = time.ParseDuration(value)
|
||||
val = int64(d)
|
||||
} else {
|
||||
val, err = strconv.ParseInt(value, 0, typ.Bits())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
field.SetInt(val)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
val, err := strconv.ParseUint(value, 0, typ.Bits())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetUint(val)
|
||||
case reflect.Bool:
|
||||
val, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetBool(val)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
val, err := strconv.ParseFloat(value, typ.Bits())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetFloat(val)
|
||||
case reflect.Slice:
|
||||
sl := reflect.MakeSlice(typ, 0, 0)
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
sl = reflect.ValueOf([]byte(value))
|
||||
} else if strings.TrimSpace(value) != "" {
|
||||
vals := strings.Split(value, SliceSep)
|
||||
sl = reflect.MakeSlice(typ, len(vals), len(vals))
|
||||
for i, val := range vals {
|
||||
err := processField(val, sl.Index(i), defaultIsUsed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
field.Set(sl)
|
||||
case reflect.Map:
|
||||
mp := reflect.MakeMap(typ)
|
||||
if strings.TrimSpace(value) != "" {
|
||||
pairs := strings.Split(value, ",")
|
||||
for _, pair := range pairs {
|
||||
kvpair := strings.Split(pair, ":")
|
||||
if len(kvpair) != 2 {
|
||||
return fmt.Errorf("invalid map item: %q", pair)
|
||||
}
|
||||
k := reflect.New(typ.Key()).Elem()
|
||||
err := processField(kvpair[0], k, defaultIsUsed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v := reflect.New(typ.Elem()).Elem()
|
||||
err = processField(kvpair[1], v, defaultIsUsed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mp.SetMapIndex(k, v)
|
||||
}
|
||||
}
|
||||
field.Set(mp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func interfaceFrom(field reflect.Value, fn func(interface{}, *bool)) {
|
||||
// it may be impossible for a struct field to fail this check
|
||||
if !field.CanInterface() {
|
||||
return
|
||||
}
|
||||
var ok bool
|
||||
fn(field.Interface(), &ok)
|
||||
if !ok && field.CanAddr() {
|
||||
fn(field.Addr().Interface(), &ok)
|
||||
}
|
||||
}
|
||||
|
||||
func decoderFrom(field reflect.Value) (d Decoder) {
|
||||
interfaceFrom(field, func(v interface{}, ok *bool) { d, *ok = v.(Decoder) })
|
||||
return d
|
||||
}
|
||||
|
||||
func setterFrom(field reflect.Value) (s Setter) {
|
||||
interfaceFrom(field, func(v interface{}, ok *bool) { s, *ok = v.(Setter) })
|
||||
return s
|
||||
}
|
||||
|
||||
func textUnmarshaler(field reflect.Value) (t encoding.TextUnmarshaler) {
|
||||
interfaceFrom(field, func(v interface{}, ok *bool) { t, *ok = v.(encoding.TextUnmarshaler) })
|
||||
return t
|
||||
}
|
||||
|
||||
func binaryUnmarshaler(field reflect.Value) (b encoding.BinaryUnmarshaler) {
|
||||
interfaceFrom(field, func(v interface{}, ok *bool) { b, *ok = v.(encoding.BinaryUnmarshaler) })
|
||||
return b
|
||||
}
|
||||
|
||||
func isTrue(s string) bool {
|
||||
b, _ := strconv.ParseBool(s)
|
||||
return b
|
||||
}
|
||||
68
internal/config/envconfig/envconfig_1.8_test.go
Normal file
68
internal/config/envconfig/envconfig_1.8_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
//go:build go1.8
|
||||
|
||||
package envconfig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type SpecWithURL struct {
|
||||
UrlValue url.URL
|
||||
UrlPointer *url.URL
|
||||
}
|
||||
|
||||
func TestParseURL(t *testing.T) {
|
||||
var s SpecWithURL
|
||||
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("ENV_CONFIG_URLVALUE", "https://github.com/kelseyhightower/envconfig")
|
||||
_ = os.Setenv("ENV_CONFIG_URLPOINTER", "https://github.com/kelseyhightower/envconfig")
|
||||
|
||||
_, err := Process("env_config", &s)
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error:", err)
|
||||
}
|
||||
|
||||
u, err := url.Parse("https://github.com/kelseyhightower/envconfig")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if s.UrlValue != *u {
|
||||
t.Errorf("expected %q, got %q", u, s.UrlValue.String())
|
||||
}
|
||||
|
||||
if *s.UrlPointer != *u {
|
||||
t.Errorf("expected %q, got %q", u, s.UrlPointer)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseURLError(t *testing.T) {
|
||||
var s SpecWithURL
|
||||
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("ENV_CONFIG_URLPOINTER", "http_://foo")
|
||||
|
||||
_, err := Process("env_config", &s)
|
||||
|
||||
v, ok := err.(*ParseError)
|
||||
if !ok {
|
||||
t.Fatalf("expected ParseError, got %T %v", err, err)
|
||||
}
|
||||
if v.FieldName != "UrlPointer" {
|
||||
t.Errorf("expected %s, got %v", "UrlPointer", v.FieldName)
|
||||
}
|
||||
|
||||
expectedUnderlyingError := url.Error{
|
||||
Op: "parse",
|
||||
URL: "http_://foo",
|
||||
Err: errors.New("first path segment in URL cannot contain colon"),
|
||||
}
|
||||
|
||||
if v.Err.Error() != expectedUnderlyingError.Error() {
|
||||
t.Errorf("expected %q, got %q", expectedUnderlyingError, v.Err)
|
||||
}
|
||||
}
|
||||
1100
internal/config/envconfig/envconfig_test.go
Normal file
1100
internal/config/envconfig/envconfig_test.go
Normal file
File diff suppressed because it is too large
Load Diff
36
internal/config/envconfig/testdata/custom.txt
vendored
Normal file
36
internal/config/envconfig/testdata/custom.txt
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
ENV_CONFIG_ENABLED=some.embedded.value
|
||||
ENV_CONFIG_EMBEDDEDPORT=
|
||||
ENV_CONFIG_MULTIWORDVAR=
|
||||
ENV_CONFIG_MULTI_WITH_DIFFERENT_ALT=
|
||||
ENV_CONFIG_EMBEDDED_WITH_ALT=
|
||||
ENV_CONFIG_DEBUG=
|
||||
ENV_CONFIG_PORT=
|
||||
ENV_CONFIG_RATE=
|
||||
ENV_CONFIG_USER=
|
||||
ENV_CONFIG_TTL=
|
||||
ENV_CONFIG_TIMEOUT=
|
||||
ENV_CONFIG_ADMINUSERS=
|
||||
ENV_CONFIG_MAGICNUMBERS=
|
||||
ENV_CONFIG_EMPTYNUMBERS=
|
||||
ENV_CONFIG_BYTESLICE=
|
||||
ENV_CONFIG_COLORCODES=
|
||||
ENV_CONFIG_MULTIWORDVAR=
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_AUTO_SPLIT=
|
||||
ENV_CONFIG_MULTI_WORD_ACR_WITH_AUTO_SPLIT=
|
||||
ENV_CONFIG_SOMEPOINTER=
|
||||
ENV_CONFIG_SOMEPOINTERWITHDEFAULT=foorbar.is.the.word
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_ALT=what.alt
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_LOWER_CASE_ALT=
|
||||
ENV_CONFIG_SERVICE_HOST=
|
||||
ENV_CONFIG_DEFAULTVAR=
|
||||
ENV_CONFIG_REQUIREDVAR=
|
||||
ENV_CONFIG_BROKER=
|
||||
ENV_CONFIG_REQUIREDDEFAULT=
|
||||
ENV_CONFIG_OUTER_INNER=
|
||||
ENV_CONFIG_OUTER_PROPERTYWITHDEFAULT=
|
||||
ENV_CONFIG_AFTERNESTED=
|
||||
ENV_CONFIG_HONOR=
|
||||
ENV_CONFIG_DATETIME=
|
||||
ENV_CONFIG_MAPFIELD=
|
||||
ENV_CONFIG_URLVALUE=
|
||||
ENV_CONFIG_URLPOINTER=
|
||||
183
internal/config/envconfig/testdata/default_list.txt
vendored
Normal file
183
internal/config/envconfig/testdata/default_list.txt
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
This.application.is.configured.via.the.environment..The.following.environment
|
||||
variables.can.be.used:
|
||||
|
||||
ENV_CONFIG_ENABLED
|
||||
..[description].some.embedded.value
|
||||
..[type]........True.or.False
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_EMBEDDEDPORT
|
||||
..[description].
|
||||
..[type]........Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTIWORDVAR
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTI_WITH_DIFFERENT_ALT
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_EMBEDDED_WITH_ALT
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_DEBUG
|
||||
..[description].
|
||||
..[type]........True.or.False
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_PORT
|
||||
..[description].
|
||||
..[type]........Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_RATE
|
||||
..[description].
|
||||
..[type]........Float
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_USER
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_TTL
|
||||
..[description].
|
||||
..[type]........Unsigned.Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_TIMEOUT
|
||||
..[description].
|
||||
..[type]........Duration
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_ADMINUSERS
|
||||
..[description].
|
||||
..[type]........Comma-separated.list.of.String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MAGICNUMBERS
|
||||
..[description].
|
||||
..[type]........Comma-separated.list.of.Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_EMPTYNUMBERS
|
||||
..[description].
|
||||
..[type]........Comma-separated.list.of.Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_BYTESLICE
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_COLORCODES
|
||||
..[description].
|
||||
..[type]........Comma-separated.list.of.String:Integer.pairs
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTIWORDVAR
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_AUTO_SPLIT
|
||||
..[description].
|
||||
..[type]........Unsigned.Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTI_WORD_ACR_WITH_AUTO_SPLIT
|
||||
..[description].
|
||||
..[type]........Unsigned.Integer
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_SOMEPOINTER
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_SOMEPOINTERWITHDEFAULT
|
||||
..[description].foorbar.is.the.word
|
||||
..[type]........String
|
||||
..[default].....foo2baz
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_ALT
|
||||
..[description].what.alt
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_LOWER_CASE_ALT
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_SERVICE_HOST
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_DEFAULTVAR
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....foobar
|
||||
..[required]....
|
||||
ENV_CONFIG_REQUIREDVAR
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....true
|
||||
ENV_CONFIG_BROKER
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....127.0.0.1
|
||||
..[required]....
|
||||
ENV_CONFIG_REQUIREDDEFAULT
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....foo2bar
|
||||
..[required]....true
|
||||
ENV_CONFIG_OUTER_INNER
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_OUTER_PROPERTYWITHDEFAULT
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....fuzzybydefault
|
||||
..[required]....
|
||||
ENV_CONFIG_AFTERNESTED
|
||||
..[description].
|
||||
..[type]........String
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_HONOR
|
||||
..[description].
|
||||
..[type]........HonorDecodeInStruct
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_DATETIME
|
||||
..[description].
|
||||
..[type]........Time
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_MAPFIELD
|
||||
..[description].
|
||||
..[type]........Comma-separated.list.of.String:String.pairs
|
||||
..[default].....one:two,three:four
|
||||
..[required]....
|
||||
ENV_CONFIG_URLVALUE
|
||||
..[description].
|
||||
..[type]........CustomURL
|
||||
..[default].....
|
||||
..[required]....
|
||||
ENV_CONFIG_URLPOINTER
|
||||
..[description].
|
||||
..[type]........CustomURL
|
||||
..[default].....
|
||||
..[required]....
|
||||
40
internal/config/envconfig/testdata/default_table.txt
vendored
Normal file
40
internal/config/envconfig/testdata/default_table.txt
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
This.application.is.configured.via.the.environment..The.following.environment
|
||||
variables.can.be.used:
|
||||
|
||||
KEY..............................................TYPE............................................DEFAULT...............REQUIRED....DESCRIPTION
|
||||
ENV_CONFIG_ENABLED...............................True.or.False.....................................................................some.embedded.value
|
||||
ENV_CONFIG_EMBEDDEDPORT..........................Integer...........................................................................
|
||||
ENV_CONFIG_MULTIWORDVAR..........................String............................................................................
|
||||
ENV_CONFIG_MULTI_WITH_DIFFERENT_ALT..............String............................................................................
|
||||
ENV_CONFIG_EMBEDDED_WITH_ALT.....................String............................................................................
|
||||
ENV_CONFIG_DEBUG.................................True.or.False.....................................................................
|
||||
ENV_CONFIG_PORT..................................Integer...........................................................................
|
||||
ENV_CONFIG_RATE..................................Float.............................................................................
|
||||
ENV_CONFIG_USER..................................String............................................................................
|
||||
ENV_CONFIG_TTL...................................Unsigned.Integer..................................................................
|
||||
ENV_CONFIG_TIMEOUT...............................Duration..........................................................................
|
||||
ENV_CONFIG_ADMINUSERS............................Comma-separated.list.of.String....................................................
|
||||
ENV_CONFIG_MAGICNUMBERS..........................Comma-separated.list.of.Integer...................................................
|
||||
ENV_CONFIG_EMPTYNUMBERS..........................Comma-separated.list.of.Integer...................................................
|
||||
ENV_CONFIG_BYTESLICE.............................String............................................................................
|
||||
ENV_CONFIG_COLORCODES............................Comma-separated.list.of.String:Integer.pairs......................................
|
||||
ENV_CONFIG_MULTIWORDVAR..........................String............................................................................
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_AUTO_SPLIT........Unsigned.Integer..................................................................
|
||||
ENV_CONFIG_MULTI_WORD_ACR_WITH_AUTO_SPLIT........Unsigned.Integer..................................................................
|
||||
ENV_CONFIG_SOMEPOINTER...........................String............................................................................
|
||||
ENV_CONFIG_SOMEPOINTERWITHDEFAULT................String..........................................foo2baz...........................foorbar.is.the.word
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_ALT...............String............................................................................what.alt
|
||||
ENV_CONFIG_MULTI_WORD_VAR_WITH_LOWER_CASE_ALT....String............................................................................
|
||||
ENV_CONFIG_SERVICE_HOST..........................String............................................................................
|
||||
ENV_CONFIG_DEFAULTVAR............................String..........................................foobar............................
|
||||
ENV_CONFIG_REQUIREDVAR...........................String................................................................true........
|
||||
ENV_CONFIG_BROKER................................String..........................................127.0.0.1.........................
|
||||
ENV_CONFIG_REQUIREDDEFAULT.......................String..........................................foo2bar...............true........
|
||||
ENV_CONFIG_OUTER_INNER...........................String............................................................................
|
||||
ENV_CONFIG_OUTER_PROPERTYWITHDEFAULT.............String..........................................fuzzybydefault....................
|
||||
ENV_CONFIG_AFTERNESTED...........................String............................................................................
|
||||
ENV_CONFIG_HONOR.................................HonorDecodeInStruct...............................................................
|
||||
ENV_CONFIG_DATETIME..............................Time..............................................................................
|
||||
ENV_CONFIG_MAPFIELD..............................Comma-separated.list.of.String:String.pairs.....one:two,three:four................
|
||||
ENV_CONFIG_URLVALUE..............................CustomURL.........................................................................
|
||||
ENV_CONFIG_URLPOINTER............................CustomURL.........................................................................
|
||||
36
internal/config/envconfig/testdata/fault.txt
vendored
Normal file
36
internal/config/envconfig/testdata/fault.txt
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
{.Key}
|
||||
Reference in New Issue
Block a user