diff --git a/cli/cli.go b/cli/cli.go index 1d51b230e..53b7df9fe 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap/zapcore" ) -const Version = "0.5.4" +const Version = "0.5.5" const defaultConfigFile = "load" const stdinConfigSelector = "-" diff --git a/core/import/import.go b/core/import/import.go index 87f88255c..044f4745e 100644 --- a/core/import/import.go +++ b/core/import/import.go @@ -96,6 +96,7 @@ func Import(fs afero.Fs) { confutil.RegisterTagResolver("", confutil.EnvTagResolver) confutil.RegisterTagResolver("ENV", confutil.EnvTagResolver) + confutil.RegisterTagResolver("PROPERTY", confutil.PropertyTagResolver) // Required for decoding plugins. Need to be added after Composite Schedule hacky hook. pluginconfig.AddHooks() diff --git a/lib/confutil/property_var_resolver.go b/lib/confutil/property_var_resolver.go new file mode 100644 index 000000000..0baa84215 --- /dev/null +++ b/lib/confutil/property_var_resolver.go @@ -0,0 +1,35 @@ +package confutil + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +// Resolve custom tag token with property variable value. Allow read from properties file +// for example: secret: '${property: /etc/datasources/secret.properties#tvm_secret}' +var PropertyTagResolver TagResolver = propertyTokenResolver + +func propertyTokenResolver(in string) (string, error) { + split := strings.SplitN(in, "#", 2) + filename, property := split[0], split[1] + file, err := os.Open(filename) + if err != nil { + return "", fmt.Errorf("cannot open file: '%v'", filename) + } + + defer file.Close() + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "=") { + kv := strings.SplitN(line, "=", 2) + if kv[0] == property { + return kv[1], nil + } + } + } + + return "", fmt.Errorf("no such property '%v', in file '%v'", property, filename) +} diff --git a/lib/confutil/property_var_resolver_test.go b/lib/confutil/property_var_resolver_test.go new file mode 100644 index 000000000..86a46324d --- /dev/null +++ b/lib/confutil/property_var_resolver_test.go @@ -0,0 +1,64 @@ +package confutil + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPropertyTokenResolver(t *testing.T) { + fileContent := []byte(`name=John Doe +age=25 +email=johndoe@example.com`) + tmpFile, err := ioutil.TempFile("", "testfile*.txt") + assert.NoError(t, err) + defer os.Remove(tmpFile.Name()) + defer tmpFile.Close() + _, err = tmpFile.Write(fileContent) + assert.NoError(t, err) + + testCases := []struct { + input string + expectedResult string + expectedError string + }{ + { + input: tmpFile.Name() + "#name", + expectedResult: "John Doe", + expectedError: "", + }, + { + input: tmpFile.Name() + "#age", + expectedResult: "25", + expectedError: "", + }, + { + input: tmpFile.Name() + "#email", + expectedResult: "johndoe@example.com", + expectedError: "", + }, + { + input: tmpFile.Name() + "#address", + expectedResult: "", + expectedError: "no such property 'address', in file '" + tmpFile.Name() + "'", + }, + { + input: "nonexistent.txt#property", + expectedResult: "", + expectedError: "cannot open file: 'nonexistent.txt'", + }, + } + + for _, testCase := range testCases { + result, err := propertyTokenResolver(testCase.input) + + assert.Equal(t, testCase.expectedResult, result) + if testCase.expectedError != "" { + assert.EqualError(t, err, testCase.expectedError) + } else { + assert.NoError(t, err) + } + } +}