Skip to content

Commit 047bf1a

Browse files
🌱 Add v1beta2 conditions to ExtensionConfig (#11848)
* Add v1beta2 conditions to ExtensionConfig * Address comments
1 parent 654516b commit 047bf1a

File tree

5 files changed

+198
-12
lines changed

5 files changed

+198
-12
lines changed

config/crd/bases/runtime.cluster.x-k8s.io_extensionconfigs.yaml

+69
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exp/runtime/api/v1alpha1/extensionconfig_types.go

+44
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ type ExtensionConfigStatus struct {
112112
// conditions define the current service state of the ExtensionConfig.
113113
// +optional
114114
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
115+
116+
// v1beta2 groups all the fields that will be added or modified in ExtensionConfig's status with the V1Beta2 version.
117+
// +optional
118+
V1Beta2 *ExtensionConfigV1Beta2Status `json:"v1beta2,omitempty"`
119+
}
120+
121+
// ExtensionConfigV1Beta2Status groups all the fields that will be added or modified in ExtensionConfig with the V1Beta2 version.
122+
// See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.
123+
type ExtensionConfigV1Beta2Status struct {
124+
// conditions represents the observations of a ExtensionConfig's current state.
125+
// Known condition types are Discovered, Paused.
126+
// +optional
127+
// +listType=map
128+
// +listMapKey=type
129+
// +kubebuilder:validation:MaxItems=32
130+
Conditions []metav1.Condition `json:"conditions,omitempty"`
115131
}
116132

117133
// ExtensionHandler specifies the details of a handler for a particular runtime hook registered by an Extension server.
@@ -187,6 +203,22 @@ func (e *ExtensionConfig) SetConditions(conditions clusterv1.Conditions) {
187203
e.Status.Conditions = conditions
188204
}
189205

206+
// GetV1Beta2Conditions returns the set of conditions for this object.
207+
func (e *ExtensionConfig) GetV1Beta2Conditions() []metav1.Condition {
208+
if e.Status.V1Beta2 == nil {
209+
return nil
210+
}
211+
return e.Status.V1Beta2.Conditions
212+
}
213+
214+
// SetV1Beta2Conditions sets conditions for an API object.
215+
func (e *ExtensionConfig) SetV1Beta2Conditions(conditions []metav1.Condition) {
216+
if e.Status.V1Beta2 == nil {
217+
e.Status.V1Beta2 = &ExtensionConfigV1Beta2Status{}
218+
}
219+
e.Status.V1Beta2.Conditions = conditions
220+
}
221+
190222
// +kubebuilder:object:root=true
191223

192224
// ExtensionConfigList contains a list of ExtensionConfig.
@@ -200,6 +232,18 @@ func init() {
200232
objectTypes = append(objectTypes, &ExtensionConfig{}, &ExtensionConfigList{})
201233
}
202234

235+
// ExtensionConfig's Discovered conditions and corresponding reasons that will be used in v1Beta2 API version.
236+
const (
237+
// ExtensionConfigDiscoveredV1Beta2Condition is true if the runtime extension has been successfully discovered.
238+
ExtensionConfigDiscoveredV1Beta2Condition = "Discovered"
239+
240+
// ExtensionConfigDiscoveredV1Beta2Reason surfaces that the runtime extension has been successfully discovered.
241+
ExtensionConfigDiscoveredV1Beta2Reason = "Discovered"
242+
243+
// ExtensionConfigNotDiscoveredV1Beta2Reason surfaces that the runtime extension has not been successfully discovered.
244+
ExtensionConfigNotDiscoveredV1Beta2Reason = "NotDiscovered"
245+
)
246+
203247
const (
204248
// RuntimeExtensionDiscoveredCondition is a condition set on an ExtensionConfig object once it has been discovered by the Runtime SDK client.
205249
RuntimeExtensionDiscoveredCondition clusterv1.ConditionType = "Discovered"

exp/runtime/api/v1alpha1/zz_generated.deepcopy.go

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exp/runtime/internal/controllers/extensionconfig_controller.go

+25-10
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ import (
3939
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
4040
runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1"
4141
runtimeclient "sigs.k8s.io/cluster-api/exp/runtime/client"
42-
"sigs.k8s.io/cluster-api/util/annotations"
4342
"sigs.k8s.io/cluster-api/util/conditions"
43+
v1beta2conditions "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
4444
"sigs.k8s.io/cluster-api/util/patch"
45+
"sigs.k8s.io/cluster-api/util/paused"
4546
"sigs.k8s.io/cluster-api/util/predicates"
4647
)
4748

@@ -84,7 +85,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt
8485
predicates.TypedResourceIsChanged[*metav1.PartialObjectMetadata](mgr.GetScheme(), predicateLog),
8586
)).
8687
WithOptions(options).
87-
WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(mgr.GetScheme(), predicateLog, r.WatchFilterValue)).
88+
WithEventFilter(predicates.ResourceHasFilterLabel(mgr.GetScheme(), predicateLog, r.WatchFilterValue)).
8889
Complete(r)
8990
if err != nil {
9091
return errors.Wrap(err, "failed setting up with a controller manager")
@@ -131,10 +132,8 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
131132
return ctrl.Result{}, err
132133
}
133134

134-
// Return early if the ExtensionConfig is paused.
135-
if annotations.HasPaused(extensionConfig) {
136-
log.Info("Reconciliation is paused for this object")
137-
return ctrl.Result{}, nil
135+
if isPaused, conditionChanged, err := paused.EnsurePausedCondition(ctx, r.Client, nil, extensionConfig); err != nil || isPaused || conditionChanged {
136+
return ctrl.Result{}, err
138137
}
139138

140139
// Handle deletion reconciliation loop.
@@ -179,9 +178,14 @@ func patchExtensionConfig(ctx context.Context, client client.Client, original, m
179178
return err
180179
}
181180

182-
options = append(options, patch.WithOwnedConditions{Conditions: []clusterv1.ConditionType{
183-
runtimev1.RuntimeExtensionDiscoveredCondition,
184-
}})
181+
options = append(options,
182+
patch.WithOwnedConditions{Conditions: []clusterv1.ConditionType{
183+
runtimev1.RuntimeExtensionDiscoveredCondition,
184+
}},
185+
patch.WithOwnedV1Beta2Conditions{Conditions: []string{
186+
runtimev1.ExtensionConfigDiscoveredV1Beta2Condition,
187+
}},
188+
)
185189
return patchHelper.Patch(ctx, modified, options...)
186190
}
187191

@@ -226,11 +230,22 @@ func discoverExtensionConfig(ctx context.Context, runtimeClient runtimeclient.Cl
226230
discoveredExtension, err := runtimeClient.Discover(ctx, extensionConfig.DeepCopy())
227231
if err != nil {
228232
modifiedExtensionConfig := extensionConfig.DeepCopy()
229-
conditions.MarkFalse(modifiedExtensionConfig, runtimev1.RuntimeExtensionDiscoveredCondition, runtimev1.DiscoveryFailedReason, clusterv1.ConditionSeverityError, "error in discovery: %v", err)
233+
conditions.MarkFalse(modifiedExtensionConfig, runtimev1.RuntimeExtensionDiscoveredCondition, runtimev1.DiscoveryFailedReason, clusterv1.ConditionSeverityError, "Error in discovery: %v", err)
234+
v1beta2conditions.Set(modifiedExtensionConfig, metav1.Condition{
235+
Type: runtimev1.ExtensionConfigDiscoveredV1Beta2Condition,
236+
Status: metav1.ConditionFalse,
237+
Reason: runtimev1.ExtensionConfigNotDiscoveredV1Beta2Reason,
238+
Message: fmt.Sprintf("Error in discovery: %v", err),
239+
})
230240
return modifiedExtensionConfig, errors.Wrapf(err, "failed to discover ExtensionConfig %s", klog.KObj(extensionConfig))
231241
}
232242

233243
conditions.MarkTrue(discoveredExtension, runtimev1.RuntimeExtensionDiscoveredCondition)
244+
v1beta2conditions.Set(discoveredExtension, metav1.Condition{
245+
Type: runtimev1.ExtensionConfigDiscoveredV1Beta2Condition,
246+
Status: metav1.ConditionTrue,
247+
Reason: runtimev1.ExtensionConfigDiscoveredV1Beta2Reason,
248+
})
234249
return discoveredExtension, nil
235250
}
236251

exp/runtime/internal/controllers/extensionconfig_controller_test.go

+33-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ func TestExtensionReconciler_Reconcile(t *testing.T) {
106106
}
107107
g.Expect(warmup.Start(ctx)).To(Succeed())
108108

109-
// Reconcile the extension and assert discovery has succeeded.
109+
// Reconcile the extension and assert discovery has succeeded (the first reconcile adds Paused).
110+
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(extensionConfig)})
111+
g.Expect(err).ToNot(HaveOccurred())
112+
110113
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(extensionConfig)})
111114
g.Expect(err).ToNot(HaveOccurred())
112115

@@ -124,6 +127,13 @@ func TestExtensionReconciler_Reconcile(t *testing.T) {
124127
g.Expect(conditions).To(HaveLen(1))
125128
g.Expect(conditions[0].Status).To(Equal(corev1.ConditionTrue))
126129
g.Expect(conditions[0].Type).To(Equal(runtimev1.RuntimeExtensionDiscoveredCondition))
130+
131+
v1beta2Conditions := config.GetV1Beta2Conditions()
132+
g.Expect(v1beta2Conditions).To(HaveLen(2)) // Second condition is paused.
133+
g.Expect(v1beta2Conditions[0].Type).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Condition))
134+
g.Expect(v1beta2Conditions[0].Status).To(Equal(metav1.ConditionTrue))
135+
g.Expect(v1beta2Conditions[0].Reason).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Reason))
136+
127137
_, err = registry.Get("first.ext1")
128138
g.Expect(err).ToNot(HaveOccurred())
129139
_, err = registry.Get("second.ext1")
@@ -159,7 +169,10 @@ func TestExtensionReconciler_Reconcile(t *testing.T) {
159169
return nil
160170
}, 30*time.Second, 100*time.Millisecond).Should(Succeed())
161171

162-
// Reconcile the extension and assert discovery has succeeded.
172+
// Reconcile the extension and assert discovery has succeeded (the first reconcile adds Paused).
173+
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(extensionConfig)})
174+
g.Expect(err).ToNot(HaveOccurred())
175+
163176
_, err = r.Reconcile(ctx, ctrl.Request{NamespacedName: util.ObjectKey(extensionConfig)})
164177
g.Expect(err).ToNot(HaveOccurred())
165178

@@ -176,6 +189,12 @@ func TestExtensionReconciler_Reconcile(t *testing.T) {
176189
g.Expect(conditions[0].Status).To(Equal(corev1.ConditionTrue))
177190
g.Expect(conditions[0].Type).To(Equal(runtimev1.RuntimeExtensionDiscoveredCondition))
178191

192+
v1beta2Conditions := config.GetV1Beta2Conditions()
193+
g.Expect(v1beta2Conditions).To(HaveLen(2)) // Second condition is paused.
194+
g.Expect(v1beta2Conditions[0].Type).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Condition))
195+
g.Expect(v1beta2Conditions[0].Status).To(Equal(metav1.ConditionTrue))
196+
g.Expect(v1beta2Conditions[0].Reason).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Reason))
197+
179198
_, err = registry.Get("first.ext1")
180199
g.Expect(err).ToNot(HaveOccurred())
181200
_, err = registry.Get("third.ext1")
@@ -236,6 +255,12 @@ func TestExtensionReconciler_discoverExtensionConfig(t *testing.T) {
236255
g.Expect(conditions).To(HaveLen(1))
237256
g.Expect(conditions[0].Status).To(Equal(corev1.ConditionTrue))
238257
g.Expect(conditions[0].Type).To(Equal(runtimev1.RuntimeExtensionDiscoveredCondition))
258+
259+
v1beta2Conditions := discoveredExtensionConfig.GetV1Beta2Conditions()
260+
g.Expect(v1beta2Conditions).To(HaveLen(1))
261+
g.Expect(v1beta2Conditions[0].Type).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Condition))
262+
g.Expect(v1beta2Conditions[0].Status).To(Equal(metav1.ConditionTrue))
263+
g.Expect(v1beta2Conditions[0].Reason).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Reason))
239264
})
240265
t.Run("fail discovery for non-running extension", func(*testing.T) {
241266
cat := runtimecatalog.New()
@@ -269,6 +294,12 @@ func TestExtensionReconciler_discoverExtensionConfig(t *testing.T) {
269294
g.Expect(conditions).To(HaveLen(1))
270295
g.Expect(conditions[0].Status).To(Equal(corev1.ConditionFalse))
271296
g.Expect(conditions[0].Type).To(Equal(runtimev1.RuntimeExtensionDiscoveredCondition))
297+
298+
v1beta2Conditions := discoveredExtensionConfig.GetV1Beta2Conditions()
299+
g.Expect(v1beta2Conditions).To(HaveLen(1))
300+
g.Expect(v1beta2Conditions[0].Type).To(Equal(runtimev1.ExtensionConfigDiscoveredV1Beta2Condition))
301+
g.Expect(v1beta2Conditions[0].Status).To(Equal(metav1.ConditionFalse))
302+
g.Expect(v1beta2Conditions[0].Reason).To(Equal(runtimev1.ExtensionConfigNotDiscoveredV1Beta2Reason))
272303
})
273304
}
274305

0 commit comments

Comments
 (0)