Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2416 from hashicorp/dynamic-config-files
Browse files Browse the repository at this point in the history
Enabling dynamic config files
  • Loading branch information
izaaklauer authored Oct 6, 2021
2 parents 8452b5d + 322b190 commit a1bb7cc
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 18 deletions.
4 changes: 4 additions & 0 deletions .changelog/2416.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```release-note:bug
config: Fix dynamic config vars targeting files.
```

9 changes: 8 additions & 1 deletion builtin/vault/config_sourcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package vault

import (
"context"
"fmt"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -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

Expand Down
16 changes: 12 additions & 4 deletions internal/appconfig/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
49 changes: 36 additions & 13 deletions internal/appconfig/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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()
Expand All @@ -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()
Expand Down

0 comments on commit a1bb7cc

Please sign in to comment.