diff --git a/README.md b/README.md index c860ee0..2ab37d3 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Confita is a library that loads configuration from multiple backends and stores ## Install ```sh -go get -u github.com/heetch/confita +go get -u github.com/karantin2020/confita ``` ## Usage @@ -95,7 +95,10 @@ A loader can take other configured backends as parameters. ```go loader := confita.NewLoader( - env.NewBackend(), + env.NewBackend( + env.WithPrefix("PREFIX"), + env.ToUpper(), + ), file.NewBackend("/path/to/config.json"), file.NewBackend("/path/to/config.yaml"), flags.NewBackend(), @@ -124,7 +127,6 @@ err := loader.Load(ctx, &cfg) If a key is not found, Confita won't change the respective struct field. With that in mind, default values can simply be implemented by filling the structure before passing it to Confita. ```go - type Config struct { Host string `config:"host"` Port uint32 `config:"port"` diff --git a/backend/env/env.go b/backend/env/env.go index 94b024f..28ed6bf 100644 --- a/backend/env/env.go +++ b/backend/env/env.go @@ -11,20 +11,43 @@ import ( // NewBackend creates a configuration loader that loads from the environment. // If the key is not found, this backend tries again by turning any kebabcase key to snakecase and // lowercase letters to uppercase. -func NewBackend() backend.Backend { +func NewBackend(fns ...opt) backend.Backend { return backend.Func("env", func(ctx context.Context, key string) ([]byte, error) { - val, ok := os.LookupEnv(key) + key = strings.Replace(key, "-", "_", -1) + val, ok := os.LookupEnv(opts(key, fns...)) if ok { return []byte(val), nil } - - key = strings.Replace(strings.ToUpper(key), "-", "_", -1) - - val, ok = os.LookupEnv(key) + val, ok = os.LookupEnv(opts(strings.ToUpper(key), fns...)) if ok { return []byte(val), nil } - return nil, backend.ErrNotFound }) } + +// WithPrefix adds preffix for searching env variable +func WithPrefix(preffix string) opt { + if !strings.HasSuffix(preffix, "_") { + preffix = preffix + "_" + } + return func(key string) string { + return preffix + key + } +} + +// ToUpper uppercases searching env variable +func ToUpper() opt { + return func(key string) string { + return strings.ToUpper(key) + } +} + +type opt func(key string) string + +func opts(key string, fns ...opt) string { + for i := range fns { + key = fns[i](key) + } + return key +} diff --git a/backend/env/env_test.go b/backend/env/env_test.go index 904f8b7..85720b3 100644 --- a/backend/env/env_test.go +++ b/backend/env/env_test.go @@ -3,6 +3,7 @@ package env import ( "context" "os" + "reflect" "testing" "github.com/heetch/confita/backend" @@ -35,3 +36,99 @@ func TestEnvBackend(t *testing.T) { require.Equal(t, "ok", string(val)) }) } + +func TestOpts(t *testing.T) { + type args struct { + fns []opt + key string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "Test opts positive", + args: args{ + fns: []opt{ + ToUpper(), + WithPrefix("TEST_"), + }, + key: "var", + }, + want: "TEST_VAR", + }, + { + name: "Test upper after prefix with lower key", + args: args{ + fns: []opt{ + WithPrefix("test"), + ToUpper(), + }, + key: "var", + }, + want: "TEST_VAR", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := opts(tt.args.key, tt.args.fns...); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewBackend() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestWithPrefix(t *testing.T) { + type args struct { + preffix string + key string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "Test add preffix positive", + args: args{ + preffix: "TEST", + key: "VAR", + }, + want: "TEST_VAR", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := WithPrefix(tt.args.preffix)(tt.args.key); !reflect.DeepEqual(got, tt.want) { + t.Errorf("WithPrefix() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestToUpper(t *testing.T) { + type args struct { + key string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "Test add preffix positive", + args: args{ + "test", + }, + want: "TEST", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ToUpper()(tt.args.key); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ToUpper() = %v, want %v", got, tt.want) + } + }) + } +}