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

Fix: Do not substitute strings without brackets #23

Merged
merged 1 commit into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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