-
Notifications
You must be signed in to change notification settings - Fork 549
CNTRLPLANE-3532: migrate CPO status patches to statuspatching helpers #8966
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,6 +88,7 @@ import ( | |
| "github.com/openshift/hypershift/support/metrics" | ||
| "github.com/openshift/hypershift/support/netutil" | ||
| "github.com/openshift/hypershift/support/releaseinfo" | ||
| "github.com/openshift/hypershift/support/statuspatching" | ||
| "github.com/openshift/hypershift/support/upsert" | ||
| "github.com/openshift/hypershift/support/util" | ||
| "github.com/openshift/hypershift/support/validations" | ||
|
|
@@ -382,8 +383,8 @@ func (r *HostedControlPlaneReconciler) eventHandlers(scheme *runtime.Scheme, res | |
| return handlers | ||
| } | ||
|
|
||
| func (r *HostedControlPlaneReconciler) reconcileDeletion(ctx context.Context, hostedControlPlane *hyperv1.HostedControlPlane, originalHostedControlPlane *hyperv1.HostedControlPlane) (ctrl.Result, error) { | ||
| condition := &metav1.Condition{ | ||
| func (r *HostedControlPlaneReconciler) reconcileDeletion(ctx context.Context, hostedControlPlane *hyperv1.HostedControlPlane) (ctrl.Result, error) { | ||
| condition := metav1.Condition{ | ||
| Type: string(hyperv1.AWSDefaultSecurityGroupDeleted), | ||
| } | ||
| if shouldCleanupCloudResources(r.Log, hostedControlPlane) { | ||
|
|
@@ -394,9 +395,7 @@ func (r *HostedControlPlaneReconciler) reconcileDeletion(ctx context.Context, ho | |
| } | ||
| condition.Reason = hyperv1.AWSErrorReason | ||
| condition.Status = metav1.ConditionFalse | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, *condition) | ||
|
|
||
| if err := r.Client.Status().Patch(ctx, hostedControlPlane, client.MergeFromWithOptions(originalHostedControlPlane, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| if err := statuspatching.PatchStatusCondition(ctx, r.Client, hostedControlPlane, &hostedControlPlane.Status.Conditions, condition); err != nil { | ||
| return ctrl.Result{}, fmt.Errorf("failed to update status on hcp for security group deletion: %w. Condition error message: %v", err, condition.Message) | ||
| } | ||
|
|
||
|
|
@@ -414,9 +413,7 @@ func (r *HostedControlPlaneReconciler) reconcileDeletion(ctx context.Context, ho | |
| condition.Message = hyperv1.AllIsWellMessage | ||
| condition.Reason = hyperv1.AsExpectedReason | ||
| condition.Status = metav1.ConditionTrue | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, *condition) | ||
|
|
||
| if err := r.Client.Status().Patch(ctx, hostedControlPlane, client.MergeFromWithOptions(originalHostedControlPlane, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| if err := statuspatching.PatchStatusCondition(ctx, r.Client, hostedControlPlane, &hostedControlPlane.Status.Conditions, condition); err != nil { | ||
| return ctrl.Result{}, fmt.Errorf("failed to update status on hcp for security group deletion: %w. Condition message: %v", err, condition.Message) | ||
| } | ||
| } | ||
|
|
@@ -601,7 +598,7 @@ func (r *HostedControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R | |
| originalHostedControlPlane := hostedControlPlane.DeepCopy() | ||
|
|
||
| if !hostedControlPlane.DeletionTimestamp.IsZero() { | ||
| return r.reconcileDeletion(ctx, hostedControlPlane, originalHostedControlPlane) | ||
| return r.reconcileDeletion(ctx, hostedControlPlane) | ||
| } | ||
|
|
||
| if !controllerutil.ContainsFinalizer(hostedControlPlane, finalizer) { | ||
|
|
@@ -1168,32 +1165,27 @@ func (r *HostedControlPlaneReconciler) update(ctx context.Context, hostedControl | |
| errs = append(errs, err) | ||
| } | ||
|
|
||
| // Get the latest HCP in memory before we patch the status | ||
| if err = r.Client.Get(ctx, client.ObjectKeyFromObject(hostedControlPlane), hostedControlPlane); err != nil { | ||
| return reconcile.Result{}, err | ||
| } | ||
|
|
||
| originalHostedControlPlane := hostedControlPlane.DeepCopy() | ||
| missingImages := sets.New(releaseImageProvider.GetMissingImages()...).Insert(userReleaseImageProvider.GetMissingImages()...) | ||
| if missingImages.Len() == 0 { | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.ValidReleaseInfo), | ||
| Status: metav1.ConditionTrue, | ||
| Reason: hyperv1.AsExpectedReason, | ||
| Message: hyperv1.AllIsWellMessage, | ||
| ObservedGeneration: hostedControlPlane.Generation, | ||
| }) | ||
| } else { | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.ValidReleaseInfo), | ||
| Status: metav1.ConditionFalse, | ||
| Reason: hyperv1.MissingReleaseImagesReason, | ||
| Message: strings.Join(missingImages.UnsortedList(), ", "), | ||
| ObservedGeneration: hostedControlPlane.Generation, | ||
| }) | ||
| } | ||
|
|
||
| if err := r.Client.Status().Patch(ctx, hostedControlPlane, client.MergeFromWithOptions(originalHostedControlPlane, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| if err := statuspatching.PatchStatus(ctx, r.Client, hostedControlPlane, func() error { | ||
| if missingImages.Len() == 0 { | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.ValidReleaseInfo), | ||
| Status: metav1.ConditionTrue, | ||
| Reason: hyperv1.AsExpectedReason, | ||
| Message: hyperv1.AllIsWellMessage, | ||
| ObservedGeneration: hostedControlPlane.Generation, | ||
| }) | ||
| } else { | ||
| meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.ValidReleaseInfo), | ||
| Status: metav1.ConditionFalse, | ||
| Reason: hyperv1.MissingReleaseImagesReason, | ||
| Message: strings.Join(sets.List(missingImages), ", "), | ||
| ObservedGeneration: hostedControlPlane.Generation, | ||
| }) | ||
| } | ||
| return nil | ||
| }); err != nil { | ||
| errs = append(errs, fmt.Errorf("failed to update status: %w", err)) | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
|
|
@@ -2120,12 +2112,8 @@ func (r *HostedControlPlaneReconciler) reconcileValidIDPConfigurationCondition(c | |
| Message: fmt.Sprintf("failed to initialize identity providers: %v", err), | ||
| } | ||
| } | ||
| // Patch the condition on the HCP if it has changed | ||
| originalHCP := hcp.DeepCopy() | ||
| if meta.SetStatusCondition(&hcp.Status.Conditions, new) { | ||
| if err := r.Status().Patch(ctx, hcp, client.MergeFromWithOptions(originalHCP, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| return fmt.Errorf("failed to patch valid IDP configuration condition: %w", err) | ||
| } | ||
| if err := statuspatching.PatchStatusCondition(ctx, r.Client, hcp, &hcp.Status.Conditions, new); err != nil { | ||
| return fmt.Errorf("failed to patch valid IDP configuration condition: %w", err) | ||
| } | ||
| return nil | ||
| } | ||
|
|
@@ -2617,14 +2605,12 @@ func (r *HostedControlPlaneReconciler) removeCloudResources(ctx context.Context, | |
| if resourcesDestroyedCond != nil && resourcesDestroyedCond.Message != "" { | ||
| message = fmt.Sprintf("%s (last status: %s)", message, resourcesDestroyedCond.Message) | ||
| } | ||
| originalHCP := hcp.DeepCopy() | ||
| meta.SetStatusCondition(&hcp.Status.Conditions, metav1.Condition{ | ||
| if err := statuspatching.PatchStatusCondition(ctx, r.Client, hcp, &hcp.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.CloudResourcesDestroyed), | ||
| Status: metav1.ConditionFalse, | ||
| Reason: string(hyperv1.CloudResourcesDeletionTimedOutReason), | ||
| Message: message, | ||
| }) | ||
| if err := r.Status().Patch(ctx, hcp, client.MergeFromWithOptions(originalHCP, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| }); err != nil { | ||
| return false, fmt.Errorf("failed to patch cloud resources destroyed condition: %w", err) | ||
| } | ||
| return true, nil | ||
|
|
@@ -2650,15 +2636,11 @@ func (r *HostedControlPlaneReconciler) removeCloudResources(ctx context.Context, | |
| return false, nil | ||
| } | ||
| if cvoScaledDownCond == nil || cvoScaledDownCond.Status != metav1.ConditionTrue { | ||
| originalHCP := hcp.DeepCopy() | ||
| cvoScaledDownCond = &metav1.Condition{ | ||
| Type: string(hyperv1.CVOScaledDown), | ||
| Status: metav1.ConditionTrue, | ||
| Reason: "CVOScaledDown", | ||
| LastTransitionTime: metav1.Now(), | ||
| } | ||
| meta.SetStatusCondition(&hcp.Status.Conditions, *cvoScaledDownCond) | ||
| if err := r.Status().Patch(ctx, hcp, client.MergeFromWithOptions(originalHCP, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| if err := statuspatching.PatchStatusCondition(ctx, r.Client, hcp, &hcp.Status.Conditions, metav1.Condition{ | ||
| Type: string(hyperv1.CVOScaledDown), | ||
| Status: metav1.ConditionTrue, | ||
| Reason: "CVOScaledDown", | ||
| }); err != nil { | ||
| return false, fmt.Errorf("failed to patch CVO scaled down condition: %w", err) | ||
| } | ||
| } | ||
|
|
@@ -2726,11 +2708,10 @@ func (r *HostedControlPlaneReconciler) reconcileDefaultSecurityGroup(ctx context | |
| return nil | ||
| } | ||
|
|
||
| originalHCP := hcp.DeepCopy() | ||
| var condition *metav1.Condition | ||
| var condition metav1.Condition | ||
| sgID, appliedTags, creationErr := createAWSDefaultSecurityGroup(ctx, r.ec2Client, hcp) | ||
| if creationErr != nil { | ||
| condition = &metav1.Condition{ | ||
| condition = metav1.Condition{ | ||
| Type: string(hyperv1.AWSDefaultSecurityGroupCreated), | ||
| Status: metav1.ConditionFalse, | ||
| Message: creationErr.Error(), | ||
|
|
@@ -2747,23 +2728,28 @@ func (r *HostedControlPlaneReconciler) reconcileDefaultSecurityGroup(ctx context | |
| }); err != nil { | ||
| return fmt.Errorf("failed to update HostedControlPlane object: %w", err) | ||
| } | ||
| originalHCP = hcp.DeepCopy() | ||
|
|
||
| condition = &metav1.Condition{ | ||
| condition = metav1.Condition{ | ||
| Type: string(hyperv1.AWSDefaultSecurityGroupCreated), | ||
| Status: metav1.ConditionTrue, | ||
| Message: hyperv1.AllIsWellMessage, | ||
| Reason: hyperv1.AsExpectedReason, | ||
| } | ||
| hcp.Status.Platform = &hyperv1.PlatformStatus{ | ||
| AWS: &hyperv1.AWSPlatformStatus{ | ||
| DefaultWorkerSecurityGroupID: sgID, | ||
| }, | ||
| } | ||
| } | ||
| meta.SetStatusCondition(&hcp.Status.Conditions, *condition) | ||
|
|
||
| if err := r.Client.Status().Patch(ctx, hcp, client.MergeFromWithOptions(originalHCP, client.MergeFromWithOptimisticLock{})); err != nil { | ||
| if err := statuspatching.PatchStatus(ctx, r.Client, hcp, func() error { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the most complex migration site in the PR — it combines a condition update with a Platform status field update in a single
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. Added |
||
| meta.SetStatusCondition(&hcp.Status.Conditions, condition) | ||
| if creationErr == nil { | ||
| if hcp.Status.Platform == nil { | ||
| hcp.Status.Platform = &hyperv1.PlatformStatus{} | ||
| } | ||
| if hcp.Status.Platform.AWS == nil { | ||
| hcp.Status.Platform.AWS = &hyperv1.AWSPlatformStatus{} | ||
| } | ||
| hcp.Status.Platform.AWS.DefaultWorkerSecurityGroupID = sgID | ||
| } | ||
| return nil | ||
| }); err != nil { | ||
| return fmt.Errorf("failed to update status: %w", err) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a regression (old code also re-fetched before referencing
Generation), butObservedGenerationinside the PatchStatus closure will reflect the re-fetched HCP's generation, which may be newer than the generation used to computemissingImages. If the spec changed between the original read and the re-fetch, the condition content won't match what that generation actually means. A follow-up reconcile self-corrects, so this is minor — just flagging in case you want to snapshot the generation before the PatchStatus call.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acknowledged. This is pre-existing — the old code also re-fetched before referencing
Generation. A follow-up reconcile self-corrects, so leaving as-is for now.AI-assisted response via Claude Code