Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added string transform replace #135

Merged
merged 1 commit into from
Jul 30, 2024
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
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