diff --git a/libs/structs/structpath/path.go b/libs/structs/structpath/path.go index adf2be51331..8e608253e33 100644 --- a/libs/structs/structpath/path.go +++ b/libs/structs/structpath/path.go @@ -360,6 +360,37 @@ func NewPatternBracketStar(prev *PatternNode) *PatternNode { }) } +// wildcard is a NewPattern part that matches any key or element. +type wildcard int + +// Wildcards for [NewPattern]: AnyKey matches any map key or field (rendered ".*") and +// AnyIndex matches any sequence element (rendered "[*]"). +const ( + AnyKey wildcard = tagDotStar + AnyIndex wildcard = tagBracketStar +) + +// NewPattern appends parts to prev like [NewPath]; AnyKey and AnyIndex append wildcards. +func NewPattern(prev *PatternNode, parts ...any) *PatternNode { + for _, part := range parts { + switch v := part.(type) { + case string: + prev = NewPatternStringKey(prev, v) + case int: + prev = NewPatternIndex(prev, v) + case wildcard: + if v == AnyKey { + prev = NewPatternDotStar(prev) + } else { + prev = NewPatternBracketStar(prev) + } + default: + panic(fmt.Sprintf("structpath.NewPattern: unsupported part %#v", part)) + } + } + return prev +} + func NewPatternKeyValue(prev *PatternNode, key, value string) *PatternNode { return (*PatternNode)(NewKeyValue((*PathNode)(prev), key, value)) } diff --git a/libs/structs/structpath/path_test.go b/libs/structs/structpath/path_test.go index 40fc0282c2b..3b7b3d3c896 100644 --- a/libs/structs/structpath/path_test.go +++ b/libs/structs/structpath/path_test.go @@ -1297,3 +1297,13 @@ func TestNewPathSlice(t *testing.T) { assert.Equal(t, "resources.jobs['${var.env}_job']", paths[0].String()) assert.Equal(t, "sync.paths[3]", NewPathSlice("sync", "paths", 3)[0].String()) } + +func TestNewPattern(t *testing.T) { + p := NewPattern(nil, "resources", "jobs", AnyKey, "tasks", AnyIndex, "libraries") + assert.Equal(t, "resources.jobs.*.tasks[*].libraries", p.String()) + + ext := NewPattern(p, AnyIndex, "whl", 0) + assert.Equal(t, "resources.jobs.*.tasks[*].libraries[*].whl[0]", ext.String()) + + assert.Panics(t, func() { NewPattern(nil, 1.5) }) +}