Skip to content

Commit

Permalink
Add support for replace filter and new pongo2 version
Browse files Browse the repository at this point in the history
Update to master branch pongo2 to allow multi-parameter functions
to be powered by the new inline "set" functionality.
  • Loading branch information
wrouesnel committed Oct 23, 2023
1 parent a3ec87a commit 56c4165
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/p2
/p2-*
/tests/*.test
**/tests/*.test
*.orig
/cover.out
/cover.*.out
Expand All @@ -12,4 +12,5 @@
/.bin
/.junit
/bin
/.coverage

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ It is inspired (and pretty much a copy of) the j2cli utility for Python, but
leveraging Golang's static compilation for easier use in Docker and other
minimal environments.

Note: We are currently updated to https://github.com/flosch/pongo2/commit/c84aecb5fa79a9c0feec284a7bf4f0536c6a6e99
on the pongo2 main branch. This version notably introduces a new set variable
functionality which allows implementing multi-parameter filters (used for
`replace`). Check out the docs over there for more info.

## Usage
p2 defaults to using the local environment variables as a data source.

Expand Down Expand Up @@ -47,6 +52,8 @@ Render a template using values from Kubernetes
#### Extra Built-In Filters

* `indent` - output data with the given indent. Can be given either a string or number of spaces.
* `replace` - replace strings. Usage: `{{ value | replace:["match", "replacement"] }}`. A third
parameter can also be supplied to set the number of replacements.
* `to_json` - outputs structured data as JSON. Supplying a parameter sets the indent.
* `to_yaml` - outputs structured data as YAML.
* `to_toml` - outputs structured data as TOML. Must be supplied a map.
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (

require (
github.com/alecthomas/kong v0.7.0
github.com/flosch/pongo2/v6 v6.0.0
github.com/flosch/pongo2/v6 v6.0.1-0.20230411124213-c84aecb5fa79
github.com/integralist/go-findroot v0.0.0-20160518114804-ac90681525dc
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/magefile/mage v1.15.0
Expand All @@ -24,6 +24,7 @@ require (

require (
github.com/dsnet/compress v0.0.1 // indirect
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 // indirect
github.com/frankban/quicktest v1.14.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/kr/pretty v0.3.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu48jqMdaOR/IZ4vdtJFuaFV8MpIE=
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM=
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
github.com/flosch/pongo2/v6 v6.0.1-0.20230411124213-c84aecb5fa79 h1:t8V7Vr867xLh3FDoEmcqRhVeKn+mRXC0dS4AhIbNxko=
github.com/flosch/pongo2/v6 v6.0.1-0.20230411124213-c84aecb5fa79/go.mod h1:hdFHt6Ygfap9bzf5cKFNw8q8nsuzjh0ONdE1texQckU=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
Expand All @@ -37,6 +41,7 @@ github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
Expand Down Expand Up @@ -72,6 +77,7 @@ golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnL
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
Expand Down
1 change: 1 addition & 0 deletions pkg/entrypoint/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ func Entrypoint(args LaunchArgs) int {

// Standard suite of custom helpers
_ = pongo2.RegisterFilter("indent", filterSet.FilterIndent)
_ = pongo2.RegisterFilter("replace", filterSet.FilterReplace)

_ = pongo2.RegisterFilter("to_json", filterSet.FilterToJSON)
_ = pongo2.RegisterFilter("to_yaml", filterSet.FilterToYAML)
Expand Down
23 changes: 23 additions & 0 deletions pkg/entrypoint/entrypoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,29 @@ func (s *p2Integration) TestIndentFilter(c *C) {
}
}

func (s *p2Integration) TestReplaceFilter(c *C) {
{
const templateFile string = "tests/data.replace.p2"
const emptyData string = "tests/data.replace.json"

// This test uses the write_file filter to produce its output.
const outputFile string = "tests/data.replace.test"
const expectedFile string = "tests/data.replace.out"

entrypointArgs := entrypoint.LaunchArgs{
StdIn: os.Stdin,
StdOut: os.Stdout,
StdErr: os.Stderr,
Env: lo.Must(envutil.FromEnvironment(os.Environ())),
Args: []string{"-t", templateFile, "-i", emptyData, "-o", outputFile},
}

exit := entrypoint.Entrypoint(entrypointArgs)
c.Assert(exit, Equals, 0, Commentf("Exit code for input %s != 0", emptyData))
c.Check(string(MustReadFile(outputFile)), DeepEquals, string(MustReadFile(expectedFile)))
}
}

func (s *p2Integration) TestStructuredFilters(c *C) {
const templateFile string = "tests/data.structured.p2"
const emptyData string = "tests/data.structured.json"
Expand Down
6 changes: 6 additions & 0 deletions pkg/entrypoint/tests/data.replace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"value": "This will have the spaces removed",
"match": "This",
"replace": "Hello",
"count": 1
}
5 changes: 5 additions & 0 deletions pkg/entrypoint/tests/data.replace.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
String Replace
Thiswillhavethespacesremoved

String Replace with count
Thiswill have the spaces removed
5 changes: 5 additions & 0 deletions pkg/entrypoint/tests/data.replace.p2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
String Replace
{{ value | replace:[" ", ""] }}

String Replace with count
{{ value | replace:[" ", "", 1] }}
84 changes: 84 additions & 0 deletions pkg/templating/templating.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,90 @@ func (fs *FilterSet) FilterIndent(in *pongo2.Value, param *pongo2.Value) (*pongo
return pongo2.AsValue(strings.Join(splitStr, "\n")), nil
}

//nolint:funlen,gomnd
func (fs *FilterSet) FilterReplace(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
if !in.IsString() {
return nil, &pongo2.Error{
Sender: "filter:Replace",
OrigError: FilterError{Reason: "filter input must be of type 'string'."},
}
}

if !param.CanSlice() {
return nil, &pongo2.Error{
Sender: "filter:Replace",
OrigError: FilterError{Reason: "filter param must be of type 'slice'."},
}
}

if param.Len() != 2 && param.Len() != 3 {
return nil, &pongo2.Error{
Sender: "filter:Replace",
OrigError: FilterError{Reason: "filter param must be of type 'slice' containing 2 strings or 2 strings and int."},
}
}

var matchParam *pongo2.Value
var replaceParam *pongo2.Value
var countParam *pongo2.Value

matchParam = param.Index(0)
replaceParam = param.Index(1)

if param.Len() == 3 {
countParam = param.Index(2)
}

// For some reason, IsString fails with our set args. But it's probably
// fine to ignore that for now.
//if !matchParam.IsString() {
// return nil, &pongo2.Error{
// Sender: "filter:Replace",
// OrigError: FilterError{Reason: "element 0 of filter param must be a string"},
// }
//}
//
//if !replaceParam.IsString() {
// return nil, &pongo2.Error{
// Sender: "filter:Replace",
// OrigError: FilterError{Reason: "element 1 of filter param must be a string"},
// }
//}
//
//if countParam != nil {
// if !countParam.IsInteger() {
// return nil, &pongo2.Error{
// Sender: "filter:Replace",
// OrigError: FilterError{Reason: "element 2 of filter param must be an integer"},
// }
// }
//}

match := matchParam.String()
replace := replaceParam.String()

input := in.String()

var result string
if countParam == nil {
result = strings.ReplaceAll(input, match, replace)
} else {
// Set notation returns strings
countStr := countParam.String()
count, err := strconv.ParseInt(countStr, 10, 64)
if err != nil {
return nil, &pongo2.Error{
Sender: "filter:Replace",
OrigError: FilterError{Reason: "element 2 of filter param must be an integer"},
}
}

result = strings.Replace(input, match, replace, int(count))
}

return pongo2.AsValue(result), nil
}

func (fs *FilterSet) FilterToJSON(in *pongo2.Value, param *pongo2.Value) (*pongo2.Value, *pongo2.Error) {
intf := in.Interface()

Expand Down

0 comments on commit 56c4165

Please sign in to comment.