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

Commit

Permalink
Fix: Do not substitute strings without brackets
Browse files Browse the repository at this point in the history
Signed-off-by: Eugene Yarshevich <yarshevich@gmail.com>
  • Loading branch information
ghen committed Jul 24, 2023
1 parent 1ec922c commit edd5b26
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 12 deletions.
36 changes: 24 additions & 12 deletions internal/helm/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ package helm
import (
"fmt"
"log"
"os"
"regexp"
"strings"

"github.com/mitchellh/mapstructure"

score "github.com/score-spec/score-go/types"
)

var (
placeholderRegEx = regexp.MustCompile(`\$(\$|{([a-zA-Z0-9.\-_\[\]"'#]+)})`)
)

// templatesContext ia an utility type that provides a context for '${...}' templates substitution
type templatesContext struct {
meta map[string]interface{}
Expand Down Expand Up @@ -46,22 +50,30 @@ func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, v

// Substitute replaces all matching '${...}' templates in a source string
func (ctx *templatesContext) Substitute(src string) string {
return os.Expand(src, ctx.mapVar)
return placeholderRegEx.ReplaceAllStringFunc(src, func(str string) string {
// WORKAROUND: ReplaceAllStringFunc(..) does not provide match details
// https://github.com/golang/go/issues/5690
var matches = placeholderRegEx.FindStringSubmatch(str)

// SANITY CHECK
if len(matches) != 3 {
log.Printf("Error: could not find a proper match in previously captured string fragment")
return src
}

// EDGE CASE: Captures "$$" sequences and empty templates "${}"
if matches[2] == "" {
return matches[1]
}

return ctx.mapVar(matches[2])
})
}

// MapVar replaces objects and properties references with corresponding values
// Returns an empty string if the reference can't be resolved
func (ctx *templatesContext) mapVar(ref string) string {
if ref == "" {
return ""
}

// NOTE: os.Expand(..) would invoke a callback function with "$" as an argument for escaped sequences.
// "$${abc}" is treated as "$$" pattern and "{abc}" static text.
// The first segment (pattern) would trigger a callback function call.
// By returning "$" value we would ensure that escaped sequences would remain in the source text.
// For example "$${abc}" would result in "${abc}" after os.Expand(..) call.
if ref == "$" {
if ref == "" || ref == "$" {
return ref
}

Expand Down
1 change: 1 addition & 0 deletions internal/helm/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func TestSubstitute(t *testing.T) {

assert.Equal(t, "", context.Substitute(""))
assert.Equal(t, "abc", context.Substitute("abc"))
assert.Equal(t, "$abc", context.Substitute("$abc"))
assert.Equal(t, "abc $ abc", context.Substitute("abc $$ abc"))
assert.Equal(t, "${abc}", context.Substitute("$${abc}"))

Expand Down

0 comments on commit edd5b26

Please sign in to comment.