feat(ansible): add regex_replace filter support
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
6c1c7d9bd4
commit
b3f2cc3fc6
3 changed files with 86 additions and 0 deletions
73
executor.go
73
executor.go
|
|
@ -2654,6 +2654,20 @@ func (e *Executor) applyFilter(value, filter string) string {
|
|||
return corexTrimSpace(value)
|
||||
}
|
||||
|
||||
// Handle regex_replace
|
||||
if corexHasPrefix(filter, "regex_replace(") {
|
||||
pattern, replacement, ok := parseRegexReplaceFilter(filter)
|
||||
if !ok {
|
||||
return value
|
||||
}
|
||||
|
||||
compiled, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return value
|
||||
}
|
||||
return compiled.ReplaceAllString(value, replacement)
|
||||
}
|
||||
|
||||
// Handle b64decode
|
||||
if filter == "b64decode" {
|
||||
decoded, err := base64.StdEncoding.DecodeString(value)
|
||||
|
|
@ -2669,6 +2683,65 @@ func (e *Executor) applyFilter(value, filter string) string {
|
|||
return value
|
||||
}
|
||||
|
||||
func parseRegexReplaceFilter(filter string) (string, string, bool) {
|
||||
if !corexHasPrefix(filter, "regex_replace(") || !corexHasSuffix(filter, ")") {
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
args := strings.TrimSpace(filter[len("regex_replace(") : len(filter)-1])
|
||||
parts := splitFilterArgs(args)
|
||||
if len(parts) < 2 {
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
return trimCutset(parts[0], "'\""), trimCutset(parts[1], "'\""), true
|
||||
}
|
||||
|
||||
func splitFilterArgs(args string) []string {
|
||||
if args == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
parts []string
|
||||
current strings.Builder
|
||||
inSingle bool
|
||||
inDouble bool
|
||||
escaped bool
|
||||
)
|
||||
|
||||
for _, r := range args {
|
||||
switch {
|
||||
case escaped:
|
||||
current.WriteRune(r)
|
||||
escaped = false
|
||||
case r == '\\' && (inSingle || inDouble):
|
||||
current.WriteRune(r)
|
||||
escaped = true
|
||||
case r == '\'' && !inDouble:
|
||||
current.WriteRune(r)
|
||||
inSingle = !inSingle
|
||||
case r == '"' && !inSingle:
|
||||
current.WriteRune(r)
|
||||
inDouble = !inDouble
|
||||
case r == ',' && !inSingle && !inDouble:
|
||||
part := strings.TrimSpace(current.String())
|
||||
if part != "" {
|
||||
parts = append(parts, part)
|
||||
}
|
||||
current.Reset()
|
||||
default:
|
||||
current.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
if tail := strings.TrimSpace(current.String()); tail != "" {
|
||||
parts = append(parts, tail)
|
||||
}
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
func isUnresolvedTemplateValue(value string) bool {
|
||||
return corexHasPrefix(value, "{{ ") && corexHasSuffix(value, " }}")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1707,6 +1707,13 @@ func TestExecutor_ApplyFilter_Good_Trim(t *testing.T) {
|
|||
assert.Equal(t, "hello", e.applyFilter(" hello ", "trim"))
|
||||
}
|
||||
|
||||
func TestExecutor_ApplyFilter_Good_RegexReplace(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
|
||||
assert.Equal(t, "web-01", e.applyFilter("web_01", "regex_replace('_', '-')"))
|
||||
assert.Equal(t, "123", e.applyFilter("abc123", `regex_replace("\D+", "")`))
|
||||
}
|
||||
|
||||
// --- resolveLoop ---
|
||||
|
||||
func TestExecutor_ResolveLoop_Good_SliceAny(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -499,6 +499,12 @@ func TestModulesInfra_ApplyFilter_Good_TrimFilter(t *testing.T) {
|
|||
assert.Equal(t, "", e.applyFilter(" ", "trim"))
|
||||
}
|
||||
|
||||
func TestModulesInfra_ApplyFilter_Good_RegexReplaceFilter(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
assert.Equal(t, "app-01", e.applyFilter("app_01", "regex_replace('_', '-')"))
|
||||
assert.Equal(t, "42", e.applyFilter("v42", `regex_replace("^v", "")`))
|
||||
}
|
||||
|
||||
func TestModulesInfra_ApplyFilter_Good_B64Decode(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
assert.Equal(t, "test", e.applyFilter("dGVzdA==", "b64decode"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue