-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(builtins): add a new builtin function strings.render_template to…
… render templated strings This adds support for rendering of templated strings utilizing Golang's text/template library. For a given templated string and key/value mapping of template var inputs, this builtin will inject the values into the template where they are referenced by key. Fixes #6371 Signed-off-by: Rohan Vasavada <rohanvasavada@gmail.com>
- Loading branch information
1 parent
31b1633
commit d46bc9d
Showing
5 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
cases: | ||
- note: rendertemplate/simple | ||
query: data.test.p = x | ||
modules: | ||
- | | ||
package test | ||
template_string = `{{.test}}` | ||
template_vars = {`test`: `hello world`} | ||
p = strings.render_template(template_string, template_vars) | ||
want_result: | ||
- x: 'hello world' | ||
|
||
- note: rendertemplate/simpleint | ||
query: data.test.p = x | ||
modules: | ||
- | | ||
package test | ||
template_string = `{{.test}}` | ||
template_vars = {`test`: 2023} | ||
p = strings.render_template(template_string, template_vars) | ||
want_result: | ||
- x: '2023' | ||
|
||
- note: rendertemplate/complex | ||
query: data.test.p = x | ||
modules: | ||
- | | ||
package test | ||
template_string = `{{range $i, $name := .hellonames}}{{if $i}},{{end}}hello {{$name}}{{end}}` | ||
template_vars = {`hellonames`: [`rohan`, `john doe`]} | ||
p = strings.render_template(template_string, template_vars) | ||
want_result: | ||
- x: 'hello rohan,hello john doe' | ||
|
||
- note: rendertemplate/missingkey | ||
query: data.test.p = x | ||
modules: | ||
- | | ||
package test | ||
template_string = `{{.testvarnotprovided}}` | ||
template_vars = {`test`: `hello world`} | ||
p = strings.render_template(template_string, template_vars) | ||
want_error_code: eval_builtin_error | ||
strict_error: true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package topdown | ||
|
||
import ( | ||
"bytes" | ||
"text/template" | ||
|
||
"github.com/open-policy-agent/opa/ast" | ||
"github.com/open-policy-agent/opa/topdown/builtins" | ||
) | ||
|
||
func renderTemplate(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { | ||
preContentTerm, err := builtins.StringOperand(operands[0].Value, 1) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
templateVariablesTerm, err := builtins.ObjectOperand(operands[1].Value, 2) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var templateVariables map[string]interface{} | ||
|
||
if err := ast.As(templateVariablesTerm, &templateVariables); err != nil { | ||
return err | ||
} | ||
|
||
tmpl, err := template.New("template").Parse(string(preContentTerm)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Do not attempt to render if template variable keys are missing | ||
tmpl.Option("missingkey=error") | ||
var buf bytes.Buffer | ||
if err := tmpl.Execute(&buf, templateVariables); err != nil { | ||
return err | ||
} | ||
|
||
return iter(ast.StringTerm(buf.String())) | ||
} | ||
|
||
func init() { | ||
RegisterBuiltinFunc(ast.RenderTemplate.Name, renderTemplate) | ||
} |