Skip to content

Commit 3a67702

Browse files
authored
Merge pull request crossplane#6224 from dalton-hill-0/preserving-custom-conditions-ssa
Preserves custom status conditions on the claim when using claim ssa
2 parents a7b495c + cba2656 commit 3a67702

File tree

2 files changed

+167
-7
lines changed

2 files changed

+167
-7
lines changed

internal/controller/apiextensions/claim/syncer_ssa.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
2727
"github.com/crossplane/crossplane-runtime/pkg/errors"
28+
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
2829
"github.com/crossplane/crossplane-runtime/pkg/meta"
2930
"github.com/crossplane/crossplane-runtime/pkg/resource"
3031
"github.com/crossplane/crossplane-runtime/pkg/resource/unstructured/claim"
@@ -313,18 +314,15 @@ func (s *ServerSideCompositeSyncer) Sync(ctx context.Context, cm *claim.Unstruct
313314
}
314315

315316
// Preserve Crossplane machinery, like status conditions.
316-
synced := cm.GetCondition(xpv1.TypeSynced)
317-
ready := cm.GetCondition(xpv1.TypeReady)
317+
cmcs := xpv1.ConditionedStatus{}
318+
_ = fieldpath.Pave(cm.Object).GetValueInto("status", &cmcs)
318319
pub := cm.GetConnectionDetailsLastPublishedTime()
319320

320321
// Update the claim's user-defined status fields to match the XRs.
321322
cm.Object["status"] = withoutKeys(xrStatus, xcrd.GetPropFields(xcrd.CompositeResourceStatusProps())...)
322323

323-
if !synced.Equal(xpv1.Condition{}) {
324-
cm.SetConditions(synced)
325-
}
326-
if !ready.Equal(xpv1.Condition{}) {
327-
cm.SetConditions(ready)
324+
if cmcs.Conditions != nil {
325+
cm.SetConditions(cmcs.Conditions...)
328326
}
329327
if pub != nil {
330328
cm.SetConnectionDetailsLastPublishedTime(pub)

internal/controller/apiextensions/claim/syncer_ssa_test.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,168 @@ func TestServerSideSync(t *testing.T) {
427427
}),
428428
},
429429
},
430+
"XRExists": {
431+
reason: "When the XR already exists, we should ensure we preserve any custom status conditions.",
432+
params: params{
433+
c: &test.MockClient{
434+
// Update the claim.
435+
MockUpdate: test.NewMockUpdateFn(nil),
436+
437+
// The XR already exists and has custom conditions.
438+
MockPatch: test.NewMockPatchFn(nil, func(obj client.Object) error {
439+
*obj.(*composite.Unstructured) = *NewComposite(func(xr *composite.Unstructured) {
440+
xr.SetGenerateName("cool-claim-")
441+
xr.SetName("cool-claim-random")
442+
meta.SetExternalName(xr, "external-name")
443+
xr.SetLabels(map[string]string{
444+
xcrd.LabelKeyClaimNamespace: "default",
445+
xcrd.LabelKeyClaimName: "cool-claim",
446+
})
447+
xr.SetAnnotations(map[string]string{
448+
"example.org/propagate-me": "true",
449+
})
450+
xr.Object["spec"] = map[string]any{
451+
"userDefinedField": "spec",
452+
}
453+
xr.SetClaimReference(&reference.Claim{
454+
Namespace: "default",
455+
Name: "cool-claim",
456+
})
457+
xr.Object["status"] = map[string]any{
458+
"userDefinedField": "status",
459+
// Types of custom conditions that were copied from the
460+
// Composite to the Claim.
461+
"claimConditionTypes": []string{"ExampleCustomStatus"},
462+
"conditions": []xpv1.Condition{
463+
{
464+
Type: "ExampleCustomStatus",
465+
Status: "True",
466+
Reason: "SomeReason",
467+
Message: "Example message.",
468+
ObservedGeneration: 20,
469+
},
470+
},
471+
}
472+
})
473+
return nil
474+
}),
475+
476+
// Update the claim's status.
477+
MockStatusUpdate: test.NewMockSubResourceUpdateFn(nil),
478+
},
479+
ng: names.NameGeneratorFn(func(_ context.Context, cd resource.Object) error {
480+
// Generate a name for the XR.
481+
cd.SetName("cool-claim-random")
482+
return nil
483+
}),
484+
},
485+
args: args{
486+
cm: NewClaim(func(cm *claim.Unstructured) {
487+
cm.SetNamespace("default")
488+
cm.SetName("cool-claim")
489+
meta.SetExternalName(cm, "external-name")
490+
491+
// Kube stuff should not be propagated to the XR.
492+
cm.SetLabels(map[string]string{
493+
"k8s.io/some-label": "filter-me-out",
494+
})
495+
cm.SetAnnotations(map[string]string{
496+
"kubernetes.io/some-anno": "filter-me-out",
497+
"example.org/propagate-me": "true",
498+
})
499+
500+
// Make sure user-defined fields are propagated to the XR.
501+
cm.Object["spec"] = map[string]any{
502+
"userDefinedField": "spec",
503+
}
504+
505+
// Make sure these don't get lost when we propagate status
506+
// from the XR.
507+
cm.SetConditions(
508+
// Crossplane system conditions.
509+
xpv1.ReconcileSuccess(),
510+
Waiting(),
511+
// User custom conditions from the Composite.
512+
xpv1.Condition{
513+
Type: "ExampleCustomStatus",
514+
Status: "True",
515+
Reason: "SomeReason",
516+
Message: "Example message.",
517+
ObservedGeneration: 20,
518+
},
519+
)
520+
cm.SetConnectionDetailsLastPublishedTime(&now)
521+
}),
522+
xr: NewComposite(),
523+
},
524+
want: want{
525+
cm: NewClaim(func(cm *claim.Unstructured) {
526+
cm.SetNamespace("default")
527+
cm.SetName("cool-claim")
528+
meta.SetExternalName(cm, "external-name")
529+
cm.SetLabels(map[string]string{
530+
"k8s.io/some-label": "filter-me-out",
531+
})
532+
cm.SetAnnotations(map[string]string{
533+
"kubernetes.io/some-anno": "filter-me-out",
534+
"example.org/propagate-me": "true",
535+
})
536+
cm.Object["spec"] = map[string]any{
537+
"userDefinedField": "spec",
538+
}
539+
cm.SetResourceReference(&reference.Composite{
540+
Name: "cool-claim-random",
541+
})
542+
cm.Object["status"] = map[string]any{
543+
"userDefinedField": "status",
544+
}
545+
cm.SetConditions(
546+
xpv1.ReconcileSuccess(),
547+
Waiting(),
548+
xpv1.Condition{
549+
Type: "ExampleCustomStatus",
550+
Status: "True",
551+
Reason: "SomeReason",
552+
Message: "Example message.",
553+
ObservedGeneration: 20,
554+
},
555+
)
556+
cm.SetConnectionDetailsLastPublishedTime(&now)
557+
}),
558+
xr: NewComposite(func(xr *composite.Unstructured) {
559+
xr.SetGenerateName("cool-claim-")
560+
xr.SetName("cool-claim-random")
561+
meta.SetExternalName(xr, "external-name")
562+
xr.SetLabels(map[string]string{
563+
xcrd.LabelKeyClaimNamespace: "default",
564+
xcrd.LabelKeyClaimName: "cool-claim",
565+
})
566+
xr.SetAnnotations(map[string]string{
567+
"example.org/propagate-me": "true",
568+
})
569+
xr.Object["spec"] = map[string]any{
570+
"userDefinedField": "spec",
571+
}
572+
xr.SetClaimReference(&reference.Claim{
573+
Namespace: "default",
574+
Name: "cool-claim",
575+
})
576+
xr.Object["status"] = map[string]any{
577+
"userDefinedField": "status",
578+
"claimConditionTypes": []string{"ExampleCustomStatus"},
579+
"conditions": []xpv1.Condition{
580+
{
581+
Type: "ExampleCustomStatus",
582+
Status: "True",
583+
Reason: "SomeReason",
584+
Message: "Example message.",
585+
ObservedGeneration: 20,
586+
},
587+
},
588+
}
589+
}),
590+
},
591+
},
430592
}
431593

432594
for name, tc := range cases {

0 commit comments

Comments
 (0)