Skip to content

Commit

Permalink
fix: Load array env
Browse files Browse the repository at this point in the history
  • Loading branch information
luanxuechao committed May 22, 2024
1 parent 5eb6fdf commit b1d1ef5
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 3 deletions.
53 changes: 50 additions & 3 deletions cmd/relayproxy/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -91,10 +92,14 @@ func New(flagSet *pflag.FlagSet, log *zap.Logger, version string) (*Config, erro
log.Error("error loading file", zap.Error(errBindFile))
}
}

configMap := k.Raw()
// Map environment variables
_ = k.Load(env.Provider("", ".", func(s string) string {
return strings.ReplaceAll(strings.ToLower(s), "_", ".")
_ = k.Load(env.ProviderWithValue("", ".", func(s string, v string) (string, interface{}) {
if strings.HasPrefix(s, "RETRIEVERS") || strings.HasPrefix(s, "NOTIFIERS") {
_ = loadArrayEnv(s, v, configMap)
return s, v
}
return strings.ReplaceAll(strings.ToLower(s), "_", "."), v
}), nil)

_ = k.Set("version", version)
Expand Down Expand Up @@ -322,3 +327,45 @@ func locateConfigFile(inputFilePath string) (string, error) {
return "", fmt.Errorf(
"impossible to find config file in the default locations [%s]", strings.Join(defaultLocations, ","))
}

// Load the ENV Like:RETRIEVERS_0_HEADERS_AUTHORIZATION
func loadArrayEnv(s string, v string, configMap map[string]interface{}) error {
paths := strings.Split(s, "_")
for i, str := range paths {
paths[i] = strings.ToLower(str)
}
prefixKey := paths[0]
if configArray, ok := configMap[prefixKey].([]interface{}); ok {
index, err := strconv.Atoi(paths[1])
if err != nil {
return err

Check warning on line 341 in cmd/relayproxy/config/config.go

View check run for this annotation

Codecov / codecov/patch

cmd/relayproxy/config/config.go#L341

Added line #L341 was not covered by tests
}
configItem := configArray[index].(map[string]interface{})
keys := paths[2:]
currentMap := configItem
for i, key := range keys {
hasKey := false
lowerKey := key
for y := range currentMap {
if y != lowerKey {
continue
}
if nextMap, ok := currentMap[y].(map[string]interface{}); ok {
currentMap = nextMap
hasKey = true
break

Check warning on line 356 in cmd/relayproxy/config/config.go

View check run for this annotation

Codecov / codecov/patch

cmd/relayproxy/config/config.go#L353-L356

Added lines #L353 - L356 were not covered by tests
}
}
if !hasKey && i != len(keys)-1 {
newMap := make(map[string]interface{})
currentMap[lowerKey] = newMap
currentMap = newMap
}
}
lastKey := keys[len(keys)-1]
currentMap[lastKey] = v
configArray[index] = configItem
_ = k.Set(prefixKey, configArray)
}
return nil
}
72 changes: 72 additions & 0 deletions cmd/relayproxy/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,3 +692,75 @@ func TestConfig_APIAdminKeyExists(t *testing.T) {
})
}
}

func TestMergeConfig_FromOSEnv(t *testing.T) {
tests := []struct {
name string
want *config.Config
fileLocation string
wantErr assert.ErrorAssertionFunc
disableDefaultFileCreation bool
}{
{
name: "Valid file",
fileLocation: "../testdata/config/validate-array-env-file.yaml",
want: &config.Config{
ListenPort: 1031,
PollingInterval: 1000,
FileFormat: "yaml",
Host: "localhost",
Retrievers: &[]config.RetrieverConf{
config.RetrieverConf{
Kind: "http",
URL: "https://github.com/thomaspoignant/go-feature-flag/main/examples/retriever_file/flags.goff.yaml",
HTTPHeaders: map[string][]string{
"authorization": []string{
"test",
},
},
},
},
Exporter: &config.ExporterConf{
Kind: "log",
},
StartWithRetrieverError: false,
RestAPITimeout: 5000,
Version: "1.X.X",
EnableSwagger: true,
AuthorizedKeys: config.APIKeys{
Admin: []string{
"apikey3",
},
Evaluation: []string{
"apikey1",
"apikey2",
},
},
},
wantErr: assert.NoError,
},
}
for _, tt := range tests {
os.Setenv("RETRIEVERS_0_HEADERS_AUTHORIZATION", "test")
t.Run(tt.name, func(t *testing.T) {
_ = os.Remove("./goff-proxy.yaml")
if !tt.disableDefaultFileCreation {
source, _ := os.Open(tt.fileLocation)
destination, _ := os.Create("./goff-proxy.yaml")
defer destination.Close()
defer source.Close()
defer os.Remove("./goff-proxy.yaml")
_, _ = io.Copy(destination, source)
}

f := pflag.NewFlagSet("config", pflag.ContinueOnError)
f.String("config", "", "Location of your config file")
_ = f.Parse([]string{fmt.Sprintf("--config=%s", tt.fileLocation)})
got, err := config.New(f, zap.L(), "1.X.X")
if !tt.wantErr(t, err) {
return
}
assert.Equal(t, tt.want, got, "Config not matching")
})
}
}
15 changes: 15 additions & 0 deletions cmd/relayproxy/testdata/config/validate-array-env-file.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
listen: 1031
pollingInterval: 1000
startWithRetrieverError: false
retrievers:
- kind: http
url: https://github.com/thomaspoignant/go-feature-flag/main/examples/retriever_file/flags.goff.yaml
exporter:
kind: log
enableSwagger: true
authorizedKeys:
evaluation:
- apikey1 # owner: userID1
- apikey2 # owner: userID2
admin:
- apikey3

0 comments on commit b1d1ef5

Please sign in to comment.