Skip to content

Commit b60d228

Browse files
committed
added string transform replace
Signed-off-by: Gilbert Scheiblhofer <gilbert.scheiblhofer@gmx.at>
1 parent 4476a5b commit b60d228

File tree

6 files changed

+138
-1
lines changed

6 files changed

+138
-1
lines changed

input/v1beta1/resources_transforms.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ const (
208208
StringTransformTypeTrimPrefix StringTransformType = "TrimPrefix"
209209
StringTransformTypeTrimSuffix StringTransformType = "TrimSuffix"
210210
StringTransformTypeRegexp StringTransformType = "Regexp"
211+
StringTransformTypeReplace StringTransformType = "Replace"
211212
)
212213

213214
// StringConversionType converts a string.
@@ -257,6 +258,10 @@ type StringTransform struct {
257258
// Extract a match from the input using a regular expression.
258259
// +optional
259260
Regexp *StringTransformRegexp `json:"regexp,omitempty"`
261+
262+
// Search/Replace applied to the input string.
263+
// +optional
264+
Replace *StringTransformReplace `json:"replace,omitempty"`
260265
}
261266

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

279+
// A StringTransformReplace replaces the search string with the replacement string.
280+
type StringTransformReplace struct {
281+
// The Search string to match.
282+
Search string `json:"search"`
283+
284+
// The Replace string replaces all occurrences of the search string.
285+
Replace string `json:"replace"`
286+
}
287+
274288
// TransformIOType defines the type of a ConvertTransform.
275289
type TransformIOType string
276290

input/v1beta1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package/input/pt.fn.crossplane.io_resources.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,20 @@ spec:
334334
required:
335335
- match
336336
type: object
337+
replace:
338+
description: Search/Replace applied to the input string.
339+
properties:
340+
replace:
341+
description: The Replace string replaces all occurrences
342+
of the search string.
343+
type: string
344+
search:
345+
description: The Search string to match.
346+
type: string
347+
required:
348+
- replace
349+
- search
350+
type: object
337351
trim:
338352
description: Trim the prefix or suffix from the input
339353
type: string
@@ -690,6 +704,21 @@ spec:
690704
required:
691705
- match
692706
type: object
707+
replace:
708+
description: Search/Replace applied to the input
709+
string.
710+
properties:
711+
replace:
712+
description: The Replace string replaces all
713+
occurrences of the search string.
714+
type: string
715+
search:
716+
description: The Search string to match.
717+
type: string
718+
required:
719+
- replace
720+
- search
721+
type: object
693722
trim:
694723
description: Trim the prefix or suffix from the
695724
input
@@ -1108,6 +1137,21 @@ spec:
11081137
required:
11091138
- match
11101139
type: object
1140+
replace:
1141+
description: Search/Replace applied to the input
1142+
string.
1143+
properties:
1144+
replace:
1145+
description: The Replace string replaces all
1146+
occurrences of the search string.
1147+
type: string
1148+
search:
1149+
description: The Search string to match.
1150+
type: string
1151+
required:
1152+
- replace
1153+
- search
1154+
type: object
11111155
trim:
11121156
description: Trim the prefix or suffix from the
11131157
input

transforms.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const (
5252
errStringTransformTypeRegexp = "string transform of type %s regexp is not set"
5353
errStringTransformTypeRegexpFailed = "could not compile regexp"
5454
errStringTransformTypeRegexpNoMatch = "regexp %q had no matches for group %d"
55+
errStringTransformTypeReplace = "string transform of type %s replace is not set"
5556
errStringConvertTypeFailed = "type %s is not supported for string convert"
5657

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

267268
// ResolveString resolves a String transform.
268-
func ResolveString(t *v1beta1.StringTransform, input any) (string, error) {
269+
func ResolveString(t *v1beta1.StringTransform, input any) (string, error) { //nolint:gocyclo // This is a long but simple switch.
269270
switch t.Type {
270271
case v1beta1.StringTransformTypeFormat:
271272
if t.Format == nil {
@@ -287,6 +288,11 @@ func ResolveString(t *v1beta1.StringTransform, input any) (string, error) {
287288
return "", errors.Errorf(errStringTransformTypeRegexp, string(t.Type))
288289
}
289290
return stringRegexpTransform(input, *t.Regexp)
291+
case v1beta1.StringTransformTypeReplace:
292+
if t.Replace == nil {
293+
return "", errors.Errorf(errStringTransformTypeReplace, string(t.Type))
294+
}
295+
return stringReplaceTransform(input, *t.Replace), nil
290296
default:
291297
return "", errors.Errorf(errStringTransformTypeFailed, string(t.Type))
292298
}
@@ -368,6 +374,11 @@ func stringRegexpTransform(input any, r v1beta1.StringTransformRegexp) (string,
368374
return groups[g], nil
369375
}
370376

377+
func stringReplaceTransform(input any, r v1beta1.StringTransformReplace) string {
378+
str := fmt.Sprintf("%v", input)
379+
return strings.ReplaceAll(str, r.Search, r.Replace)
380+
}
381+
371382
// ResolveConvert resolves a Convert transform by looking up the appropriate
372383
// conversion function for the given input type and invoking it.
373384
func ResolveConvert(t *v1beta1.ConvertTransform, input any) (any, error) {

transforms_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ func TestStringResolve(t *testing.T) {
639639
convert *v1beta1.StringConversionType
640640
trim *string
641641
regexp *v1beta1.StringTransformRegexp
642+
replace *v1beta1.StringTransformReplace
642643
i any
643644
}
644645
type want struct {
@@ -1003,6 +1004,45 @@ func TestStringResolve(t *testing.T) {
10031004
err: errors.Wrap(errors.New("json: unsupported type: func()"), errMarshalJSON),
10041005
},
10051006
},
1007+
"ReplaceFound": {
1008+
args: args{
1009+
stype: v1beta1.StringTransformTypeReplace,
1010+
replace: &v1beta1.StringTransformReplace{
1011+
Search: "Cr",
1012+
Replace: "B",
1013+
},
1014+
i: "Crossplane",
1015+
},
1016+
want: want{
1017+
o: "Bossplane",
1018+
},
1019+
},
1020+
"ReplaceNotFound": {
1021+
args: args{
1022+
stype: v1beta1.StringTransformTypeReplace,
1023+
replace: &v1beta1.StringTransformReplace{
1024+
Search: "xx",
1025+
Replace: "zz",
1026+
},
1027+
i: "Crossplane",
1028+
},
1029+
want: want{
1030+
o: "Crossplane",
1031+
},
1032+
},
1033+
"ReplaceRemove": {
1034+
args: args{
1035+
stype: v1beta1.StringTransformTypeReplace,
1036+
replace: &v1beta1.StringTransformReplace{
1037+
Search: "ss",
1038+
Replace: "",
1039+
},
1040+
i: "Crossplane",
1041+
},
1042+
want: want{
1043+
o: "Croplane",
1044+
},
1045+
},
10061046
}
10071047
for name, tc := range cases {
10081048
t.Run(name, func(t *testing.T) {
@@ -1012,6 +1052,7 @@ func TestStringResolve(t *testing.T) {
10121052
Convert: tc.convert,
10131053
Trim: tc.trim,
10141054
Regexp: tc.regexp,
1055+
Replace: tc.replace,
10151056
}
10161057

10171058
got, err := ResolveString(tr, tc.i)

validate.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,13 @@ func ValidateStringTransform(s *v1beta1.StringTransform) *field.Error { //nolint
382382
if _, err := regexp.Compile(s.Regexp.Match); err != nil {
383383
return field.Invalid(field.NewPath("regexp", "match"), s.Regexp.Match, "invalid regexp")
384384
}
385+
case v1beta1.StringTransformTypeReplace:
386+
if s.Replace == nil {
387+
return field.Required(field.NewPath("replace"), "replace transform requires a replace")
388+
}
389+
if s.Replace.Search == "" {
390+
return field.Required(field.NewPath("replace", "search"), "replace transform requires a search")
391+
}
385392
default:
386393
return field.Invalid(field.NewPath("type"), s.Type, "unknown string transform type")
387394
}

0 commit comments

Comments
 (0)