diff --git a/cmd/veneur-proxy/main.go b/cmd/veneur-proxy/main.go index eeac7e21a..aa91ed2da 100644 --- a/cmd/veneur-proxy/main.go +++ b/cmd/veneur-proxy/main.go @@ -51,7 +51,7 @@ func main() { } config, err := - utilConfig.ReadConfig[proxy.Config](*configFile, "veneur_proxy") + utilConfig.ReadConfig[proxy.Config](*configFile, nil, "veneur_proxy") if err != nil { logger.WithError(err).Fatal("failed to load config file") } diff --git a/util/config/config.go b/util/config/config.go index e8d5e7029..c576ea140 100644 --- a/util/config/config.go +++ b/util/config/config.go @@ -3,16 +3,17 @@ package config import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" + "text/template" "github.com/kelseyhightower/envconfig" "gopkg.in/yaml.v2" ) func ReadConfig[Config interface{}]( - path string, envBase string, + path string, templateData interface{}, envBase string, ) (*Config, error) { file, err := os.Open(path) if err != nil { @@ -20,17 +21,38 @@ func ReadConfig[Config interface{}]( } defer file.Close() - fileData, err := ioutil.ReadAll(file) + fileData, err := io.ReadAll(file) if err != nil { return nil, fmt.Errorf("failed to read config file: %v", err) } + configTemplate, err := template.New("config").Parse(string(fileData)) + if err != nil { + return nil, err + } + + configReader, configWriter := io.Pipe() + templateErr := make(chan error) + go func() { + err := configTemplate.Execute(configWriter, templateData) + configWriter.Close() + templateErr <- err + }() + + decoder := yaml.NewDecoder(configReader) + decoder.SetStrict(true) + config := new(Config) - err = yaml.UnmarshalStrict(fileData, config) + err = decoder.Decode(config) if err != nil { return nil, fmt.Errorf("failed to unmarshal config file: %v", err) } + err = <-templateErr + if err != nil { + return nil, err + } + err = envconfig.Process(envBase, config) if err != nil { return nil, fmt.Errorf("failed to process environment variables: %v", err) diff --git a/util/config/config_test.go b/util/config/config_test.go new file mode 100644 index 000000000..b9070019d --- /dev/null +++ b/util/config/config_test.go @@ -0,0 +1,49 @@ +package config_test + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stripe/veneur/v14/util/config" +) + +type Config struct { + Key1 string +} + +func TestReadConfigWithoutTemplate(t *testing.T) { + file, err := ioutil.TempFile("", "config.yaml") + require.NoError(t, err) + defer os.Remove(file.Name()) + + file.Write([]byte("key1: value1")) + + parsedConfig, err := + config.ReadConfig[Config](file.Name(), nil, "") + require.NoError(t, err) + + assert.Equal(t, "value1", parsedConfig.Key1) +} + +type ConfigParams struct { + ConfigValue string +} + +func TestReadConfigWithTemplate(t *testing.T) { + file, err := ioutil.TempFile("", "config.yaml") + require.NoError(t, err) + defer os.Remove(file.Name()) + + file.Write([]byte("key1: {{.ConfigValue}}")) + + parsedConfig, err := + config.ReadConfig[Config](file.Name(), ConfigParams{ + ConfigValue: "value1", + }, "") + require.NoError(t, err) + + assert.Equal(t, "value1", parsedConfig.Key1) +}