From 3f0065c874eaba8e1ca2a9b977842df589d44542 Mon Sep 17 00:00:00 2001 From: Izaak Lauer <8404559+izaaklauer@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:13:15 -0400 Subject: [PATCH 1/3] Enabling dynamic config files Prior to this, it appears that dynamic config targeting files did not work. Also includes some better error messages for the vault plugin. --- builtin/vault/config_sourcer.go | 9 ++++++++- internal/appconfig/watcher.go | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/builtin/vault/config_sourcer.go b/builtin/vault/config_sourcer.go index b2762c51135..f0ae9fe9741 100644 --- a/builtin/vault/config_sourcer.go +++ b/builtin/vault/config_sourcer.go @@ -2,6 +2,7 @@ package vault import ( "context" + "fmt" "strings" "sync" "time" @@ -148,11 +149,17 @@ func (cs *ConfigSourcer) read( secret, err := client.Logical().Read(vaultReq.Path) if err != nil { result.Result = &pb.ConfigSource_Value_Error{ - Error: status.New(codes.Aborted, err.Error()).Proto(), + Error: status.New(codes.Aborted, fmt.Sprintf("Failed to read from vault. Path: %q, err: %q", vaultReq.Path, err)).Proto(), } continue } + if secret == nil { + result.Result = &pb.ConfigSource_Value_Error{ + Error: status.New(codes.Aborted, fmt.Sprintf("path %q is missing", vaultReq.Path)).Proto(), + } + continue + } cachedSecretVal = &cachedSecret{Secret: secret} cs.secretCache[vaultReq.Path] = cachedSecretVal diff --git a/internal/appconfig/watcher.go b/internal/appconfig/watcher.go index 964607a85d7..4f040d02fd3 100644 --- a/internal/appconfig/watcher.go +++ b/internal/appconfig/watcher.go @@ -766,6 +766,8 @@ func buildAppConfig( // Ininitialize our result with the static values var envVars []string + var dynamicFiles []*FileContent + // Go through each and read our configurations. Note that ConfigSourcers // are documented to note that Read will be called frequently so caching // is expected within the sourcer itself. @@ -833,9 +835,15 @@ func buildAppConfig( if req.cv.Internal { internal[req.req.Name] = cty.StringVal(r.Value) } else { - envVars = append(envVars, req.req.Name+"="+r.Value) - - env[req.req.Name] = cty.StringVal(r.Value) + if req.cv.NameIsPath { + dynamicFiles = append(dynamicFiles, &FileContent{ + Path: req.req.Name, + Data: []byte(r.Value), + }) + } else { + envVars = append(envVars, req.req.Name+"="+r.Value) + env[req.req.Name] = cty.StringVal(r.Value) + } } case *sdkpb.ConfigSource_Value_Error: @@ -869,7 +877,7 @@ func buildAppConfig( staticEnv, staticFiles := expandStaticVars(log, &ectx, staticVars) - return append(envVars, staticEnv...), staticFiles + return append(envVars, staticEnv...), append(staticFiles, dynamicFiles...) } // expandStaticVars will parse any value that appears to be a HCL template as one and then From 2a7e6cf57975fa10fe5337b42b77c4ec5e875c52 Mon Sep 17 00:00:00 2001 From: Izaak Lauer <8404559+izaaklauer@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:17:50 -0400 Subject: [PATCH 2/3] Changelog --- .changelog/2416.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changelog/2416.txt diff --git a/.changelog/2416.txt b/.changelog/2416.txt new file mode 100644 index 00000000000..5a7c808106b --- /dev/null +++ b/.changelog/2416.txt @@ -0,0 +1,4 @@ +```release-note:bug +config: Fix dynamic config vars targeting files. +``` + From 322b1900ceb4420f78f520b0e64c6326484c1cb6 Mon Sep 17 00:00:00 2001 From: Izaak Lauer <8404559+izaaklauer@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:26:25 -0400 Subject: [PATCH 3/3] Add a test for writing dynamic config as files --- internal/appconfig/watcher_test.go | 49 ++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/internal/appconfig/watcher_test.go b/internal/appconfig/watcher_test.go index 2f8686787f8..33225b6fad0 100644 --- a/internal/appconfig/watcher_test.go +++ b/internal/appconfig/watcher_test.go @@ -175,7 +175,10 @@ func TestWatcher_dynamicSuccess(t *testing.T) { // Create our test config source testSource := &testConfigSourcer{ - readValue: map[string]string{"key": "hello"}, + readValue: map[string]string{ + "envVarKey": "helloEnv", + "fileKey": "helloFile", + }, } w, err := NewWatcher( @@ -193,27 +196,46 @@ func TestWatcher_dynamicSuccess(t *testing.T) { Dynamic: &pb.ConfigVar_DynamicVal{ From: "cloud", Config: map[string]string{ - "key": "key", + "key": "envVarKey", + }, + }, + }, + }, + { + Name: "/tmp/test_file.txt", + NameIsPath: true, + Value: &pb.ConfigVar_Dynamic{ + Dynamic: &pb.ConfigVar_DynamicVal{ + From: "cloud", + Config: map[string]string{ + "key": "fileKey", }, }, }, }, }) - // We should get the static vars back - env, iter, err := w.Next(ctx, 0) + // We should get the static vars and files back + cfg, iter, err := w.Next(ctx, 0) require.NoError(err) - require.Equal(env.EnvVars, []string{"TEST_VALUE=hello"}) + require.Equal(cfg.EnvVars, []string{"TEST_VALUE=helloEnv"}) + require.Equal(cfg.Files, []*FileContent{{ + Path: "/tmp/test_file.txt", Data: []byte("helloFile"), + }}) - // Change the value and make sure we get it + // Change the values and make sure we get them testSource.Lock() - testSource.readValue["key"] = "goodbye" + testSource.readValue["envVarKey"] = "goodbyeEnv" + testSource.readValue["fileKey"] = "goodbyeFile" testSource.Unlock() - // We should get the static vars back - env, iter, err = w.Next(ctx, iter) + // We should get the static vars and files back + cfg, iter, err = w.Next(ctx, iter) require.NoError(err) - require.Equal(env.EnvVars, []string{"TEST_VALUE=goodbye"}) + require.Equal(cfg.EnvVars, []string{"TEST_VALUE=goodbyeEnv"}) + require.Equal(cfg.Files, []*FileContent{{ + Path: "/tmp/test_file.txt", Data: []byte("goodbyeFile"), + }}) // We should've called Stop once: exactly for the first read testSource.Lock() @@ -224,10 +246,11 @@ func TestWatcher_dynamicSuccess(t *testing.T) { // Unset our dynamic config w.UpdateVars(ctx, []*pb.ConfigVar{}) - // We should get the static vars back - env, iter, err = w.Next(ctx, iter) + // We should get the static vars and files back + cfg, iter, err = w.Next(ctx, iter) require.NoError(err) - require.Empty(env.EnvVars) + require.Empty(cfg.EnvVars) + require.Empty(cfg.Files) // We should call stop once more to end the previous run testSource.Lock()