Skip to content

Commit e3606fb

Browse files
Feat: Guarantee one-time actions emit as distinct events
Ensures create/update/delete/approve operations trigger an immediate, distinct condition/event emission to guarantee visibility. Signed-off-by: yiraeChristineKim <[email protected]> working well exept metrics things
1 parent e7778c7 commit e3606fb

File tree

3 files changed

+185
-135
lines changed

3 files changed

+185
-135
lines changed

controllers/operatorpolicy_controller.go

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ func (r *OperatorPolicyReconciler) handleResources(ctx context.Context, policy *
421421
return earlyComplianceEvents, condChanged, err
422422
}
423423

424-
changed, err = r.handleInstallPlan(ctx, policy, subscription)
424+
changed, earlyConds, err = r.handleInstallPlan(ctx, policy, subscription)
425+
earlyComplianceEvents = append(earlyComplianceEvents, earlyConds...)
425426
condChanged = condChanged || changed
426427

427428
if err != nil {
@@ -1118,7 +1119,9 @@ func (r *OperatorPolicyReconciler) musthaveOpGroup(
11181119
// Now the OperatorGroup should match, so report Compliance
11191120
updateStatus(policy, createdCond("OperatorGroup"), createdObj(desiredOpGroup))
11201121
// Emit a dedicated "created" event regardless of later status aggregation
1121-
earlyConds = append(earlyConds, createdCond("OperatorGroup"))
1122+
cond := createdCond("OperatorGroup")
1123+
cond.LastTransitionTime = metav1.Now()
1124+
earlyConds = append(earlyConds, cond)
11221125

11231126
return true, earlyConds, true, nil
11241127
case 1:
@@ -1203,6 +1206,10 @@ func (r *OperatorPolicyReconciler) musthaveOpGroup(
12031206
desiredOpGroup.SetGroupVersionKind(operatorGroupGVK) // Update stripped this information
12041207

12051208
updateStatus(policy, updatedCond("OperatorGroup"), updatedObj(desiredOpGroup))
1209+
// Emit a dedicated "updated" event
1210+
upd := updatedCond("OperatorGroup")
1211+
upd.LastTransitionTime = metav1.Now()
1212+
earlyConds = append(earlyConds, upd)
12061213

12071214
return true, earlyConds, true, nil
12081215
default:
@@ -1363,6 +1370,10 @@ func (r *OperatorPolicyReconciler) mustnothaveOpGroup(
13631370
desiredOpGroup.SetGroupVersionKind(operatorGroupGVK) // Delete stripped this information
13641371

13651372
updateStatus(policy, deletedCond("OperatorGroup"), deletedObj(desiredOpGroup))
1373+
// Emit a dedicated "deleted" event
1374+
del := deletedCond("OperatorGroup")
1375+
del.LastTransitionTime = metav1.Now()
1376+
earlyConds = append(earlyConds, del)
13661377

13671378
return earlyConds, true, nil
13681379
}
@@ -1416,7 +1427,6 @@ func (r *OperatorPolicyReconciler) musthaveSubscription(
14161427
earlyConds = append(earlyConds, calculateComplianceCondition(policy))
14171428
}
14181429

1419-
log.Info("!!!!!!!!!!!!!! create subscription!!!!!!!!!!!")
14201430
err := r.createWithNamespace(ctx, desiredSub)
14211431
if err != nil {
14221432
return nil, nil, changed, fmt.Errorf("error creating the Subscription: %w", err)
@@ -1533,6 +1543,10 @@ func (r *OperatorPolicyReconciler) musthaveSubscription(
15331543
mergedSub.SetGroupVersionKind(subscriptionGVK) // Update stripped this information
15341544

15351545
updateStatus(policy, updatedCond("Subscription"), updatedObj(mergedSub))
1546+
// Emit a dedicated "updated" event
1547+
upd := updatedCond("Subscription")
1548+
upd.LastTransitionTime = metav1.Now()
1549+
earlyConds = append(earlyConds, upd)
15361550

15371551
return mergedSub, earlyConds, true, nil
15381552
}
@@ -1856,6 +1870,10 @@ func (r *OperatorPolicyReconciler) mustnothaveSubscription(
18561870
}
18571871

18581872
updateStatus(policy, deletedCond("Subscription"), deletedObj(desiredSub))
1873+
// Emit a dedicated "deleted" event
1874+
del := deletedCond("Subscription")
1875+
del.LastTransitionTime = metav1.Now()
1876+
earlyConds = append(earlyConds, del)
18591877

18601878
return foundSub, earlyConds, true, nil
18611879
}
@@ -1887,14 +1905,14 @@ func messageIncludesSubscription(subscription *operatorv1alpha1.Subscription, me
18871905

18881906
func (r *OperatorPolicyReconciler) handleInstallPlan(
18891907
ctx context.Context, policy *policyv1beta1.OperatorPolicy, sub *operatorv1alpha1.Subscription,
1890-
) (bool, error) {
1908+
) (bool, []metav1.Condition, error) {
18911909
if sub == nil {
18921910
// Note: existing related objects will not be removed by this status update
1893-
return updateStatus(policy, invalidCausingUnknownCond("InstallPlan")), nil
1911+
return updateStatus(policy, invalidCausingUnknownCond("InstallPlan")), []metav1.Condition{}, nil
18941912
}
18951913

18961914
if sub.Status.CurrentCSV == "" && sub.Status.InstalledCSV == "" {
1897-
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), nil
1915+
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), []metav1.Condition{}, nil
18981916
}
18991917

19001918
watcher := opPolIdentifier(policy.Namespace, policy.Name)
@@ -1907,14 +1925,14 @@ func (r *OperatorPolicyReconciler) handleInstallPlan(
19071925
// potentially vulnerable operators.
19081926
installPlans, err := r.DynamicWatcher.List(watcher, installPlanGVK, sub.Namespace, labels.Everything())
19091927
if err != nil {
1910-
return false, fmt.Errorf("error listing InstallPlans: %w", err)
1928+
return false, []metav1.Condition{}, fmt.Errorf("error listing InstallPlans: %w", err)
19111929
}
19121930

19131931
// InstallPlans are generally kept in order to provide a history of actions on the cluster, but
19141932
// they can be deleted without impacting the installed operator. So, not finding any should not
19151933
// be considered a reason for NonCompliance, regardless of musthave or mustnothave.
19161934
if len(installPlans) == 0 {
1917-
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), nil
1935+
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), []metav1.Condition{}, nil
19181936
}
19191937

19201938
var latestInstallPlan *unstructured.Unstructured
@@ -1982,24 +2000,26 @@ func (r *OperatorPolicyReconciler) handleInstallPlan(
19822000
"subscription", sub.Name, "namespace", sub.Namespace,
19832001
)
19842002

1985-
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), nil
2003+
return updateStatus(policy, noInstallPlansCond, noInstallPlansObj(sub.Namespace)), []metav1.Condition{}, nil
19862004
}
19872005

19882006
if policy.Spec.ComplianceType.IsMustHave() {
1989-
changed, err := r.musthaveInstallPlan(ctx, policy, sub, latestInstallPlan)
2007+
changed, earlyConds, err := r.musthaveInstallPlan(ctx, policy, sub, latestInstallPlan)
19902008

1991-
return changed, err
2009+
return changed, earlyConds, err
19922010
}
19932011

1994-
return r.mustnothaveInstallPlan(policy, latestInstallPlan)
2012+
changed, err := r.mustnothaveInstallPlan(policy, latestInstallPlan)
2013+
2014+
return changed, []metav1.Condition{}, err
19952015
}
19962016

19972017
func (r *OperatorPolicyReconciler) musthaveInstallPlan(
19982018
ctx context.Context,
19992019
policy *policyv1beta1.OperatorPolicy,
20002020
sub *operatorv1alpha1.Subscription,
20012021
latestInstallPlanUnstruct *unstructured.Unstructured,
2002-
) (bool, error) {
2022+
) (bool, []metav1.Condition, error) {
20032023
opLog := ctrl.LoggerFrom(ctx)
20042024
complianceConfig := policy.Spec.ComplianceConfig.UpgradesAvailable
20052025
latestInstallPlan := operatorv1alpha1.InstallPlan{}
@@ -2009,7 +2029,7 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
20092029
opLog.Error(err, "Unable to determine the CSV names of the current InstallPlan",
20102030
"InstallPlan.Name", latestInstallPlanUnstruct.GetName())
20112031

2012-
return updateStatus(policy, installPlansNoApprovals), nil
2032+
return updateStatus(policy, installPlansNoApprovals), []metav1.Condition{}, nil
20132033
}
20142034

20152035
ipCSVs := latestInstallPlan.Spec.ClusterServiceVersionNames
@@ -2024,21 +2044,21 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
20242044
currentCSV := sub.Status.CurrentCSV
20252045

20262046
if installedCSV != "" && currentCSV != "" && installedCSV == currentCSV {
2027-
return updateStatus(policy, installPlansNoApprovals), nil
2047+
return updateStatus(policy, installPlansNoApprovals), []metav1.Condition{}, nil
20282048
}
20292049
case operatorv1alpha1.InstallPlanPhaseInstalling:
20302050
return updateStatus(
20312051
policy,
20322052
installPlanInstallingCond,
20332053
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2034-
), nil
2054+
), []metav1.Condition{}, nil
20352055
case operatorv1alpha1.InstallPlanFailed:
20362056
// Generally, a failed InstallPlan is not a reason for NonCompliance, because it could be from
20372057
// an old installation. But if the current InstallPlan is failed, we should alert the user.
20382058
if len(ipCSVs) == 1 {
20392059
return updateStatus(
20402060
policy, installPlanFailed, existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2041-
), nil
2061+
), []metav1.Condition{}, nil
20422062
}
20432063

20442064
// If there is more than one CSV in the InstallPlan, make sure this CSV failed before marking it as
@@ -2056,27 +2076,30 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
20562076
policy,
20572077
installPlanFailed,
20582078
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2059-
), nil
2079+
), []metav1.Condition{}, nil
20602080
}
20612081
}
20622082

20632083
// If no step for this CSV failed in the InstallPlan, treat it the same as no install plans requiring approval
2064-
return updateStatus(policy, installPlansNoApprovals), nil
2084+
return updateStatus(policy, installPlansNoApprovals), []metav1.Condition{}, nil
20652085
default:
20662086
return updateStatus(
20672087
policy,
20682088
installPlansNoApprovals, existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2069-
), nil
2089+
), []metav1.Condition{}, nil
20702090
}
20712091

20722092
// Check if it's already approved. This can happen if this OperatorPolicy or another managing the same InstallPlan
20732093
// performed the approval but it hasn't started installing yet.
20742094
if latestInstallPlan.Spec.Approved {
2095+
ipApproved := installPlanApprovedCond(sub.Status.CurrentCSV)
2096+
ipApproved.LastTransitionTime = metav1.Now()
2097+
20752098
return updateStatus(
20762099
policy,
20772100
installPlanApprovedCond(sub.Status.CurrentCSV),
20782101
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2079-
), nil
2102+
), []metav1.Condition{ipApproved}, nil
20802103
}
20812104

20822105
initialInstall := sub.Status.InstalledCSV == ""
@@ -2085,43 +2108,54 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
20852108
// Only report this status when not approving an InstallPlan, because otherwise it could easily
20862109
// oscillate between this and another condition.
20872110
if policy.Spec.RemediationAction.IsInform() || (!initialInstall && !autoUpgrade) {
2111+
// Emit an early event to record that an upgrade is available and requires approval
2112+
ipUpgrade := installPlanUpgradeCond(complianceConfig, ipCSVs, nil)
2113+
ipUpgrade.LastTransitionTime = metav1.Now()
2114+
20882115
return updateStatus(
20892116
policy,
2090-
installPlanUpgradeCond(complianceConfig, ipCSVs, nil),
2117+
ipUpgrade,
20912118
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2092-
), nil
2119+
), []metav1.Condition{ipUpgrade}, nil
20932120
}
20942121

20952122
remainingCSVsToApprove, err := r.getRemainingCSVApprovals(ctx, policy, sub, &latestInstallPlan)
20962123
if err != nil {
2097-
return false, fmt.Errorf("error finding the InstallPlan approvals: %w", err)
2124+
return false, []metav1.Condition{}, fmt.Errorf("error finding the InstallPlan approvals: %w", err)
20982125
}
20992126

21002127
if len(remainingCSVsToApprove) != 0 {
2128+
// Emit an early event that approval is required for the listed CSVs
2129+
ipUpgrade := installPlanUpgradeCond(complianceConfig, ipCSVs, remainingCSVsToApprove)
2130+
ipUpgrade.LastTransitionTime = metav1.Now()
2131+
21012132
return updateStatus(
21022133
policy,
2103-
installPlanUpgradeCond(complianceConfig, ipCSVs, remainingCSVsToApprove),
2134+
ipUpgrade,
21042135
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
2105-
), nil
2136+
), []metav1.Condition{ipUpgrade}, nil
21062137
}
21072138

21082139
opLog.Info("Approving InstallPlan", "InstallPlanName", latestInstallPlan.Name,
21092140
"InstallPlanNamespace", latestInstallPlan.Namespace)
21102141

21112142
if err := unstructured.SetNestedField(latestInstallPlanUnstruct.Object, true, "spec", "approved"); err != nil {
2112-
return false, fmt.Errorf("error approving InstallPlan: %w", err)
2143+
return false, []metav1.Condition{}, fmt.Errorf("error approving InstallPlan: %w", err)
21132144
}
21142145

21152146
if err := r.TargetClient.Update(ctx, latestInstallPlanUnstruct); err != nil {
2116-
return false, fmt.Errorf("error updating approved InstallPlan: %w", err)
2147+
return false, []metav1.Condition{}, fmt.Errorf("error updating approved InstallPlan: %w", err)
21172148
}
21182149

2150+
ipApproved := installPlanApprovedCond(sub.Status.CurrentCSV)
2151+
ipApproved.LastTransitionTime = metav1.Now()
2152+
21192153
return updateStatus(
21202154
policy,
21212155
installPlanApprovedCond(sub.Status.CurrentCSV),
21222156
existingInstallPlanObj(&latestInstallPlan, string(phase), complianceConfig),
21232157
),
2124-
nil
2158+
[]metav1.Condition{ipApproved}, nil
21252159
}
21262160

21272161
// getRemainingCSVApprovals will return all CSVs that can't be approved by an OperatorPolicy (currentPolicy and others).
@@ -2577,6 +2611,7 @@ func (r *OperatorPolicyReconciler) mustnothaveCSV(
25772611
}
25782612

25792613
updateStatus(policy, deletedCond("ClusterServiceVersion", csvNames...), relatedCSVs...)
2614+
earlyConds = append(earlyConds, deletedCond("ClusterServiceVersion", csvNames...))
25802615

25812616
return earlyConds, true, nil
25822617
}
@@ -2755,6 +2790,7 @@ func (r *OperatorPolicyReconciler) handleCRDs(
27552790
}
27562791

27572792
updateStatus(policy, deletedCond("CustomResourceDefinition"), relatedCRDs...)
2793+
earlyConds = append(earlyConds, deletedCond("CustomResourceDefinition"))
27582794

27592795
return earlyConds, true, nil
27602796
}

0 commit comments

Comments
 (0)