Skip to content

Commit

Permalink
Merge pull request #34 from deveeztech/bugfix/await-correctly-for-reg…
Browse files Browse the repository at this point in the history
…ex-sequence

fix: await correctly for regex sequence
  • Loading branch information
turkenh authored Dec 10, 2024
2 parents 2625649 + e471b03 commit f57be1b
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 25 deletions.
4 changes: 2 additions & 2 deletions example/observed-regex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
annotations:
crossplane.io/external-name: foo
crossplane.io/composition-resource-name: first-subresource-2
name: first
name: first-subresource-2
spec:
forProvider:
conditionAfter:
Expand Down Expand Up @@ -32,7 +32,7 @@ metadata:
annotations:
crossplane.io/external-name: foo
crossplane.io/composition-resource-name: first-subresource-1
name: first
name: first-subresource-1
spec:
forProvider:
conditionAfter:
Expand Down
35 changes: 22 additions & 13 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,14 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
continue
}
for _, before := range sequence[:i] {
strictPattern := string(before)
if !strings.HasPrefix(strictPattern, START) && !strings.HasSuffix(strictPattern, END) {
// if the user provides a delimited regex, we'll use it as is
// if not, add the regex with ^ & $ to match the entire string
// possibly avoid using regex for matching literal strings
strictPattern = fmt.Sprintf("%s%s%s", START, string(before), END)
}
re, err := regexp.Compile(strictPattern)
beforeRegex, err := getStrictRegex(string(before))
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot compile regex %s", strictPattern))
response.Fatal(rsp, errors.Wrapf(err, "cannot compile regex %s", before))
return rsp, nil
}
keys := []resource.Name{}
for k := range desiredComposed {
if re.MatchString(string(k)) {
if beforeRegex.MatchString(string(k)) {
keys = append(keys, k)
}
}
Expand All @@ -103,11 +96,11 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ

if desired == 0 || desired != readyResources {
// no resource created
msg := fmt.Sprintf("Delaying creation of resource %q because %q does not exist yet", r, before)
msg := fmt.Sprintf("Delaying creation of resource(s) matching %q because %q does not exist yet", r, before)
if desired > 0 {
// provide a nicer message if there are resources.
msg = fmt.Sprintf(
"Delaying creation of resource %q because %q is not fully ready (%d of %d)",
"Delaying creation of resource(s) matching %q because %q is not fully ready (%d of %d)",
r,
before,
readyResources,
Expand All @@ -116,7 +109,13 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
}
response.Normal(rsp, msg)
f.log.Info(msg)
delete(desiredComposed, r)
// find all objects that match the regex and delete them from the desiredComposed map
currentRegex, _ := getStrictRegex(string(r))
for k := range desiredComposed {
if currentRegex.MatchString(string(k)) {
delete(desiredComposed, k)
}
}
break
}
}
Expand All @@ -126,3 +125,13 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
rsp.Desired.Resources = nil
return rsp, response.SetDesiredComposedResources(rsp, desiredComposed)
}

func getStrictRegex(pattern string) (*regexp.Regexp, error) {
if !strings.HasPrefix(pattern, START) && !strings.HasSuffix(pattern, END) {
// if the user provides a delimited regex, we'll use it as is
// if not, add the regex with ^ & $ to match the entire string
// possibly avoid using regex for matching literal strings
pattern = fmt.Sprintf("%s%s%s", START, pattern, END)
}
return regexp.Compile(pattern)
}
98 changes: 88 additions & 10 deletions fn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"third\" because \"first\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"third\" because \"first\" is not fully ready (0 of 1)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -142,7 +142,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"second\" because \"first\" does not exist yet",
Message: "Delaying creation of resource(s) matching \"second\" because \"first\" does not exist yet",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -197,7 +197,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"second\" because \"first\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"second\" because \"first\" is not fully ready (0 of 1)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -383,11 +383,11 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"second\" because \"first\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"second\" because \"first\" is not fully ready (0 of 1)",
},
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"fourth\" because \"third\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"fourth\" because \"third\" is not fully ready (0 of 1)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -528,7 +528,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"second\" because \"first\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"second\" because \"first\" is not fully ready (0 of 1)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -597,7 +597,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"second\" because \"first-.*\" is not fully ready (2 of 3)",
Message: "Delaying creation of resource(s) matching \"second\" because \"first-.*\" is not fully ready (2 of 3)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -679,7 +679,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"third\" because \"second-.*\" is not fully ready (1 of 2)",
Message: "Delaying creation of resource(s) matching \"third\" because \"second-.*\" is not fully ready (1 of 2)",
},
},
Desired: &fnv1beta1.State{
Expand Down Expand Up @@ -761,7 +761,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"third\" because \"second-.*\" is not fully ready (1 of 2)",
Message: "Delaying creation of resource(s) matching \"third\" because \"second-.*\" is not fully ready (1 of 2)",
},
},
Desired: &fnv1beta1.State{
Expand All @@ -785,6 +785,84 @@ func TestRunFunction(t *testing.T) {
},
},
},
"SequenceRegexWaitComplex": {
reason: "The function should not modify the sequence regex, since it's already prefixed",
args: args{
req: &fnv1beta1.RunFunctionRequest{
Input: resource.MustStructObject(&v1beta1.Input{
Rules: []v1beta1.SequencingRule{
{
Sequence: []resource.Name{
"first-.*",
"second$",
"third-resource",
},
},
},
}),
Observed: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xr),
},
Resources: map[string]*fnv1beta1.Resource{},
},
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xr),
},
Resources: map[string]*fnv1beta1.Resource{
"first-0": {
Resource: resource.MustStructJSON(mr),
Ready: fnv1beta1.Ready_READY_TRUE,
},
"first-1": {
Resource: resource.MustStructJSON(mr),
Ready: fnv1beta1.Ready_READY_FALSE,
},
"0-second": {
Resource: resource.MustStructJSON(mr),
},
"1-second": {
Resource: resource.MustStructJSON(mr),
},
"third-resource": {
Resource: resource.MustStructJSON(mr),
},
},
},
},
},
want: want{
rsp: &fnv1beta1.RunFunctionResponse{
Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)},
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource(s) matching \"second$\" because \"first-.*\" is not fully ready (1 of 2)",
},
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource(s) matching \"third-resource\" because \"first-.*\" is not fully ready (1 of 2)",
},
},
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xr),
},
Resources: map[string]*fnv1beta1.Resource{
"first-0": {
Resource: resource.MustStructJSON(mr),
Ready: fnv1beta1.Ready_READY_TRUE,
},
"first-1": {
Resource: resource.MustStructJSON(mr),
Ready: fnv1beta1.Ready_READY_FALSE,
},
},
},
},
},
},
"SequenceRegexAlreadyPrefixed": {
reason: "The function should not modify the sequence regex, since it's already prefixed",
args: args{
Expand Down Expand Up @@ -837,7 +915,7 @@ func TestRunFunction(t *testing.T) {
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "Delaying creation of resource \"fourth\" because \"third-.*$\" is not fully ready (0 of 1)",
Message: "Delaying creation of resource(s) matching \"fourth\" because \"third-.*$\" is not fully ready (0 of 1)",
},
},
Desired: &fnv1beta1.State{
Expand Down

0 comments on commit f57be1b

Please sign in to comment.