Skip to content

Commit

Permalink
Merge pull request #135 from gschei/add-transform-replace
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanduplessis authored Jul 30, 2024
2 parents 4476a5b + b60d228 commit 3ad61a0
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 1 deletion.
14 changes: 14 additions & 0 deletions input/v1beta1/resources_transforms.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ const (
StringTransformTypeTrimPrefix StringTransformType = "TrimPrefix"
StringTransformTypeTrimSuffix StringTransformType = "TrimSuffix"
StringTransformTypeRegexp StringTransformType = "Regexp"
StringTransformTypeReplace StringTransformType = "Replace"
)

// StringConversionType converts a string.
Expand Down Expand Up @@ -257,6 +258,10 @@ type StringTransform struct {
// Extract a match from the input using a regular expression.
// +optional
Regexp *StringTransformRegexp `json:"regexp,omitempty"`

// Search/Replace applied to the input string.
// +optional
Replace *StringTransformReplace `json:"replace,omitempty"`
}

// A StringTransformRegexp extracts a match from the input using a regular
Expand All @@ -271,6 +276,15 @@ type StringTransformRegexp struct {
Group *int `json:"group,omitempty"`
}

// A StringTransformReplace replaces the search string with the replacement string.
type StringTransformReplace struct {
// The Search string to match.
Search string `json:"search"`

// The Replace string replaces all occurrences of the search string.
Replace string `json:"replace"`
}

// TransformIOType defines the type of a ConvertTransform.
type TransformIOType string

Expand Down
20 changes: 20 additions & 0 deletions input/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions package/input/pt.fn.crossplane.io_resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,20 @@ spec:
required:
- match
type: object
replace:
description: Search/Replace applied to the input string.
properties:
replace:
description: The Replace string replaces all occurrences
of the search string.
type: string
search:
description: The Search string to match.
type: string
required:
- replace
- search
type: object
trim:
description: Trim the prefix or suffix from the input
type: string
Expand Down Expand Up @@ -690,6 +704,21 @@ spec:
required:
- match
type: object
replace:
description: Search/Replace applied to the input
string.
properties:
replace:
description: The Replace string replaces all
occurrences of the search string.
type: string
search:
description: The Search string to match.
type: string
required:
- replace
- search
type: object
trim:
description: Trim the prefix or suffix from the
input
Expand Down Expand Up @@ -1108,6 +1137,21 @@ spec:
required:
- match
type: object
replace:
description: Search/Replace applied to the input
string.
properties:
replace:
description: The Replace string replaces all
occurrences of the search string.
type: string
search:
description: The Search string to match.
type: string
required:
- replace
- search
type: object
trim:
description: Trim the prefix or suffix from the
input
Expand Down
13 changes: 12 additions & 1 deletion transforms.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const (
errStringTransformTypeRegexp = "string transform of type %s regexp is not set"
errStringTransformTypeRegexpFailed = "could not compile regexp"
errStringTransformTypeRegexpNoMatch = "regexp %q had no matches for group %d"
errStringTransformTypeReplace = "string transform of type %s replace is not set"
errStringConvertTypeFailed = "type %s is not supported for string convert"

errDecodeString = "string is not valid base64"
Expand Down Expand Up @@ -265,7 +266,7 @@ func unmarshalJSON(j extv1.JSON, output *any) error {
}

// ResolveString resolves a String transform.
func ResolveString(t *v1beta1.StringTransform, input any) (string, error) {
func ResolveString(t *v1beta1.StringTransform, input any) (string, error) { //nolint:gocyclo // This is a long but simple switch.
switch t.Type {
case v1beta1.StringTransformTypeFormat:
if t.Format == nil {
Expand All @@ -287,6 +288,11 @@ func ResolveString(t *v1beta1.StringTransform, input any) (string, error) {
return "", errors.Errorf(errStringTransformTypeRegexp, string(t.Type))
}
return stringRegexpTransform(input, *t.Regexp)
case v1beta1.StringTransformTypeReplace:
if t.Replace == nil {
return "", errors.Errorf(errStringTransformTypeReplace, string(t.Type))
}
return stringReplaceTransform(input, *t.Replace), nil
default:
return "", errors.Errorf(errStringTransformTypeFailed, string(t.Type))
}
Expand Down Expand Up @@ -368,6 +374,11 @@ func stringRegexpTransform(input any, r v1beta1.StringTransformRegexp) (string,
return groups[g], nil
}

func stringReplaceTransform(input any, r v1beta1.StringTransformReplace) string {
str := fmt.Sprintf("%v", input)
return strings.ReplaceAll(str, r.Search, r.Replace)
}

// ResolveConvert resolves a Convert transform by looking up the appropriate
// conversion function for the given input type and invoking it.
func ResolveConvert(t *v1beta1.ConvertTransform, input any) (any, error) {
Expand Down
41 changes: 41 additions & 0 deletions transforms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ func TestStringResolve(t *testing.T) {
convert *v1beta1.StringConversionType
trim *string
regexp *v1beta1.StringTransformRegexp
replace *v1beta1.StringTransformReplace
i any
}
type want struct {
Expand Down Expand Up @@ -1003,6 +1004,45 @@ func TestStringResolve(t *testing.T) {
err: errors.Wrap(errors.New("json: unsupported type: func()"), errMarshalJSON),
},
},
"ReplaceFound": {
args: args{
stype: v1beta1.StringTransformTypeReplace,
replace: &v1beta1.StringTransformReplace{
Search: "Cr",
Replace: "B",
},
i: "Crossplane",
},
want: want{
o: "Bossplane",
},
},
"ReplaceNotFound": {
args: args{
stype: v1beta1.StringTransformTypeReplace,
replace: &v1beta1.StringTransformReplace{
Search: "xx",
Replace: "zz",
},
i: "Crossplane",
},
want: want{
o: "Crossplane",
},
},
"ReplaceRemove": {
args: args{
stype: v1beta1.StringTransformTypeReplace,
replace: &v1beta1.StringTransformReplace{
Search: "ss",
Replace: "",
},
i: "Crossplane",
},
want: want{
o: "Croplane",
},
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
Expand All @@ -1012,6 +1052,7 @@ func TestStringResolve(t *testing.T) {
Convert: tc.convert,
Trim: tc.trim,
Regexp: tc.regexp,
Replace: tc.replace,
}

got, err := ResolveString(tr, tc.i)
Expand Down
7 changes: 7 additions & 0 deletions validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,13 @@ func ValidateStringTransform(s *v1beta1.StringTransform) *field.Error { //nolint
if _, err := regexp.Compile(s.Regexp.Match); err != nil {
return field.Invalid(field.NewPath("regexp", "match"), s.Regexp.Match, "invalid regexp")
}
case v1beta1.StringTransformTypeReplace:
if s.Replace == nil {
return field.Required(field.NewPath("replace"), "replace transform requires a replace")
}
if s.Replace.Search == "" {
return field.Required(field.NewPath("replace", "search"), "replace transform requires a search")
}
default:
return field.Invalid(field.NewPath("type"), s.Type, "unknown string transform type")
}
Expand Down

0 comments on commit 3ad61a0

Please sign in to comment.