@@ -21,11 +21,14 @@ import (
21
21
"strings"
22
22
23
23
"github.com/pkg/errors"
24
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24
25
25
26
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
26
27
"sigs.k8s.io/cluster-api/exp/topology/scope"
27
28
"sigs.k8s.io/cluster-api/internal/contract"
29
+ "sigs.k8s.io/cluster-api/util/annotations"
28
30
"sigs.k8s.io/cluster-api/util/conditions"
31
+ v1beta2conditions "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
29
32
)
30
33
31
34
func (r * Reconciler ) reconcileConditions (s * scope.Scope , cluster * clusterv1.Cluster , reconcileErr error ) error {
@@ -36,32 +39,62 @@ func (r *Reconciler) reconcileConditions(s *scope.Scope, cluster *clusterv1.Clus
36
39
// The TopologyReconciled condition is considered true if spec of all the objects associated with the
37
40
// cluster are in sync with the topology defined in the cluster.
38
41
// The condition is false under the following conditions:
42
+ // - The cluster is paused.
39
43
// - An error occurred during the reconcile process of the cluster topology.
40
44
// - The ClusterClass has not been successfully reconciled with its current spec.
41
45
// - The cluster upgrade has not yet propagated to all the components of the cluster.
42
46
// - For a managed topology cluster the version upgrade is propagated one component at a time.
43
47
// In such a case, since some of the component's spec would be adrift from the topology the
44
48
// topology cannot be considered fully reconciled.
45
49
func (r * Reconciler ) reconcileTopologyReconciledCondition (s * scope.Scope , cluster * clusterv1.Cluster , reconcileErr error ) error {
50
+ // Mark TopologyReconciled as false if the Cluster is paused.
51
+ if cluster .Spec .Paused || annotations .HasPaused (cluster ) {
52
+ var messages []string
53
+ if cluster .Spec .Paused {
54
+ messages = append (messages , "Cluster spec.paused is set to true" )
55
+ }
56
+ if annotations .HasPaused (cluster ) {
57
+ messages = append (messages , "Cluster has the cluster.x-k8s.io/paused annotation" )
58
+ }
59
+ conditions .Set (cluster ,
60
+ conditions .FalseCondition (
61
+ clusterv1 .TopologyReconciledCondition ,
62
+ clusterv1 .TopologyReconciledPausedReason ,
63
+ clusterv1 .ConditionSeverityInfo ,
64
+ strings .Join (messages , ", " ),
65
+ ),
66
+ )
67
+ v1beta2conditions .Set (cluster , metav1.Condition {
68
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
69
+ Status : metav1 .ConditionFalse ,
70
+ Reason : clusterv1 .ClusterTopologyReconcilePausedV1Beta2Reason ,
71
+ Message : strings .Join (messages , ", " ),
72
+ })
73
+ return nil
74
+ }
75
+
46
76
// Mark TopologyReconciled as false due to cluster deletion.
47
77
if ! cluster .ObjectMeta .DeletionTimestamp .IsZero () {
48
- conditions .Set (
49
- cluster ,
78
+ conditions .Set (cluster ,
50
79
conditions .FalseCondition (
51
80
clusterv1 .TopologyReconciledCondition ,
52
81
clusterv1 .DeletedReason ,
53
82
clusterv1 .ConditionSeverityInfo ,
54
83
"" ,
55
84
),
56
85
)
86
+ v1beta2conditions .Set (cluster , metav1.Condition {
87
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
88
+ Status : metav1 .ConditionFalse ,
89
+ Reason : clusterv1 .ClusterTopologyReconciledDeletionTimestampSetV1Beta2Reason ,
90
+ })
57
91
return nil
58
92
}
59
93
60
94
// If an error occurred during reconciliation set the TopologyReconciled condition to false.
61
95
// Add the error message from the reconcile function to the message of the condition.
62
96
if reconcileErr != nil {
63
- conditions .Set (
64
- cluster ,
97
+ conditions .Set (cluster ,
65
98
conditions .FalseCondition (
66
99
clusterv1 .TopologyReconciledCondition ,
67
100
clusterv1 .TopologyReconcileFailedReason ,
@@ -70,15 +103,21 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
70
103
reconcileErr .Error (),
71
104
),
72
105
)
106
+ v1beta2conditions .Set (cluster , metav1.Condition {
107
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
108
+ Status : metav1 .ConditionFalse ,
109
+ Reason : clusterv1 .ClusterTopologyReconciledFailedV1Beta2Reason ,
110
+ // TODO: Add a protection for messages continuously changing leading to Cluster object changes/reconcile.
111
+ Message : reconcileErr .Error (),
112
+ })
73
113
return nil
74
114
}
75
115
76
116
// If the ClusterClass `metadata.Generation` doesn't match the `status.ObservedGeneration` requeue as the ClusterClass
77
117
// is not up to date.
78
118
if s .Blueprint != nil && s .Blueprint .ClusterClass != nil &&
79
119
s .Blueprint .ClusterClass .GetGeneration () != s .Blueprint .ClusterClass .Status .ObservedGeneration {
80
- conditions .Set (
81
- cluster ,
120
+ conditions .Set (cluster ,
82
121
conditions .FalseCondition (
83
122
clusterv1 .TopologyReconciledCondition ,
84
123
clusterv1 .TopologyReconciledClusterClassNotReconciledReason ,
@@ -87,14 +126,20 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
87
126
".status.observedGeneration == .metadata.generation is true. If this is not the case either ClusterClass reconciliation failed or the ClusterClass is paused" ,
88
127
),
89
128
)
129
+ v1beta2conditions .Set (cluster , metav1.Condition {
130
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
131
+ Status : metav1 .ConditionFalse ,
132
+ Reason : clusterv1 .ClusterTopologyReconciledClusterClassNotReconciledV1Beta2Reason ,
133
+ Message : "ClusterClass not reconciled. If this condition persists please check ClusterClass status. A ClusterClass is reconciled if" +
134
+ ".status.observedGeneration == .metadata.generation is true. If this is not the case either ClusterClass reconciliation failed or the ClusterClass is paused" ,
135
+ })
90
136
return nil
91
137
}
92
138
93
139
// If any of the lifecycle hooks are blocking any part of the reconciliation then topology
94
140
// is not considered as fully reconciled.
95
141
if s .HookResponseTracker .AggregateRetryAfter () != 0 {
96
- conditions .Set (
97
- cluster ,
142
+ conditions .Set (cluster ,
98
143
conditions .FalseCondition (
99
144
clusterv1 .TopologyReconciledCondition ,
100
145
clusterv1 .TopologyReconciledHookBlockingReason ,
@@ -103,6 +148,13 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
103
148
s .HookResponseTracker .AggregateMessage (),
104
149
),
105
150
)
151
+ v1beta2conditions .Set (cluster , metav1.Condition {
152
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
153
+ Status : metav1 .ConditionFalse ,
154
+ Reason : clusterv1 .ClusterTopologyReconciledHookBlockingV1Beta2Reason ,
155
+ // TODO: Add a protection for messages continuously changing leading to Cluster object changes/reconcile.
156
+ Message : s .HookResponseTracker .AggregateMessage (),
157
+ })
106
158
return nil
107
159
}
108
160
@@ -121,6 +173,7 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
121
173
s .UpgradeTracker .MachinePools .DeferredUpgrade () {
122
174
msgBuilder := & strings.Builder {}
123
175
var reason string
176
+ var v1beta2Reason string
124
177
125
178
// TODO(ykakarap): Evaluate potential improvements to building the condition. Multiple causes can trigger the
126
179
// condition to be false at the same time (Example: ControlPlane.IsPendingUpgrade and MachineDeployments.IsAnyPendingCreate can
@@ -130,40 +183,47 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
130
183
case s .UpgradeTracker .ControlPlane .IsPendingUpgrade :
131
184
fmt .Fprintf (msgBuilder , "Control plane rollout and upgrade to version %s on hold." , s .Blueprint .Topology .Version )
132
185
reason = clusterv1 .TopologyReconciledControlPlaneUpgradePendingReason
186
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledControlPlaneUpgradePendingV1Beta2Reason
133
187
case s .UpgradeTracker .MachineDeployments .IsAnyPendingUpgrade ():
134
188
fmt .Fprintf (msgBuilder , "MachineDeployment(s) %s rollout and upgrade to version %s on hold." ,
135
189
computeNameList (s .UpgradeTracker .MachineDeployments .PendingUpgradeNames ()),
136
190
s .Blueprint .Topology .Version ,
137
191
)
138
192
reason = clusterv1 .TopologyReconciledMachineDeploymentsUpgradePendingReason
193
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachineDeploymentsUpgradePendingV1Beta2Reason
139
194
case s .UpgradeTracker .MachineDeployments .IsAnyPendingCreate ():
140
195
fmt .Fprintf (msgBuilder , "MachineDeployment(s) for Topologies %s creation on hold." ,
141
196
computeNameList (s .UpgradeTracker .MachineDeployments .PendingCreateTopologyNames ()),
142
197
)
143
198
reason = clusterv1 .TopologyReconciledMachineDeploymentsCreatePendingReason
199
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachineDeploymentsCreatePendingV1Beta2Reason
144
200
case s .UpgradeTracker .MachineDeployments .DeferredUpgrade ():
145
201
fmt .Fprintf (msgBuilder , "MachineDeployment(s) %s rollout and upgrade to version %s deferred." ,
146
202
computeNameList (s .UpgradeTracker .MachineDeployments .DeferredUpgradeNames ()),
147
203
s .Blueprint .Topology .Version ,
148
204
)
149
205
reason = clusterv1 .TopologyReconciledMachineDeploymentsUpgradeDeferredReason
206
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachineDeploymentsUpgradeDeferredV1Beta2Reason
150
207
case s .UpgradeTracker .MachinePools .IsAnyPendingUpgrade ():
151
208
fmt .Fprintf (msgBuilder , "MachinePool(s) %s rollout and upgrade to version %s on hold." ,
152
209
computeNameList (s .UpgradeTracker .MachinePools .PendingUpgradeNames ()),
153
210
s .Blueprint .Topology .Version ,
154
211
)
155
212
reason = clusterv1 .TopologyReconciledMachinePoolsUpgradePendingReason
213
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachinePoolsUpgradePendingV1Beta2Reason
156
214
case s .UpgradeTracker .MachinePools .IsAnyPendingCreate ():
157
215
fmt .Fprintf (msgBuilder , "MachinePool(s) for Topologies %s creation on hold." ,
158
216
computeNameList (s .UpgradeTracker .MachinePools .PendingCreateTopologyNames ()),
159
217
)
160
218
reason = clusterv1 .TopologyReconciledMachinePoolsCreatePendingReason
219
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachinePoolsCreatePendingV1Beta2Reason
161
220
case s .UpgradeTracker .MachinePools .DeferredUpgrade ():
162
221
fmt .Fprintf (msgBuilder , "MachinePool(s) %s rollout and upgrade to version %s deferred." ,
163
222
computeNameList (s .UpgradeTracker .MachinePools .DeferredUpgradeNames ()),
164
223
s .Blueprint .Topology .Version ,
165
224
)
166
225
reason = clusterv1 .TopologyReconciledMachinePoolsUpgradeDeferredReason
226
+ v1beta2Reason = clusterv1 .ClusterTopologyReconciledMachinePoolsUpgradeDeferredV1Beta2Reason
167
227
}
168
228
169
229
switch {
@@ -191,26 +251,34 @@ func (r *Reconciler) reconcileTopologyReconciledCondition(s *scope.Scope, cluste
191
251
)
192
252
}
193
253
194
- conditions .Set (
195
- cluster ,
254
+ conditions .Set (cluster ,
196
255
conditions .FalseCondition (
197
256
clusterv1 .TopologyReconciledCondition ,
198
257
reason ,
199
258
clusterv1 .ConditionSeverityInfo ,
200
259
msgBuilder .String (),
201
260
),
202
261
)
262
+ v1beta2conditions .Set (cluster , metav1.Condition {
263
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
264
+ Status : metav1 .ConditionFalse ,
265
+ Reason : v1beta2Reason ,
266
+ Message : msgBuilder .String (),
267
+ })
203
268
return nil
204
269
}
205
270
206
271
// If there are no errors while reconciling and if the topology is not holding out changes
207
272
// we can consider that spec of all the objects is reconciled to match the topology. Set the
208
273
// TopologyReconciled condition to true.
209
- conditions .Set (
210
- cluster ,
274
+ conditions .Set (cluster ,
211
275
conditions .TrueCondition (clusterv1 .TopologyReconciledCondition ),
212
276
)
213
-
277
+ v1beta2conditions .Set (cluster , metav1.Condition {
278
+ Type : clusterv1 .ClusterTopologyReconciledV1Beta2Condition ,
279
+ Status : metav1 .ConditionTrue ,
280
+ Reason : clusterv1 .ClusterTopologyReconcileSucceededV1Beta2Reason ,
281
+ })
214
282
return nil
215
283
}
216
284
0 commit comments