Skip to content

Commit 03cff23

Browse files
authored
Merge pull request #3136 from fabriziopandini/add-conditions-to-machine
🌱 Add conditions to the Machine object
2 parents 0801817 + 5113f80 commit 03cff23

18 files changed

+254
-64
lines changed

api/v1alpha2/conversion.go

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ func (src *Machine) ConvertTo(dstRaw conversion.Hub) error {
118118
}
119119
restoreMachineSpec(&restored.Spec, &dst.Spec)
120120
dst.Status.ObservedGeneration = restored.Status.ObservedGeneration
121+
dst.Status.Conditions = restored.Status.Conditions
121122

122123
return nil
123124
}

api/v1alpha2/zz_generated.conversion.go

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

api/v1alpha3/condition_consts.go

+31
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,34 @@ const (
2525
)
2626

2727
// ANCHOR_END: CommonConditions
28+
29+
// Conditions and condition Reasons for the Machine object
30+
31+
// MachineSummaryConditionsCount defines the total number of conditions on the Machine object.
32+
const MachineSummaryConditionsCount = 2
33+
34+
const (
35+
// BootstrapReadyCondition reports a summary of current status of the bootstrap object defined for this machine.
36+
// This condition is mirrored from the Ready condition in the bootstrap ref object, and
37+
// the absence of this condition might signal problems in the reconcile external loops or the fact that
38+
// the bootstrap provider does not not implements the Ready condition yet.
39+
BootstrapReadyCondition ConditionType = "BootstrapReady"
40+
41+
// WaitingForDataSecretFallbackReason (Severity=Info) documents a machine waiting for the bootstrap data secret
42+
// to be available.
43+
// NOTE: This reason is used only as a fallback when the bootstrap object is not reporting its own ready condition.
44+
WaitingForDataSecretFallbackReason = "WaitingForDataSecret"
45+
)
46+
47+
const (
48+
// InfrastructureReadyCondition reports a summary of current status of the infrastructure object defined for this machine.
49+
// This condition is mirrored from the Ready condition in the infrastructure ref object, and
50+
// the absence of this condition might signal problems in the reconcile external loops or the fact that
51+
// the infrastructure provider does not not implements the Ready condition yet.
52+
InfrastructureReadyCondition ConditionType = "InfrastructureReady"
53+
54+
// WaitingForInfrastructureFallbackReason (Severity=Info) documents a machine waiting for the machine infrastructure
55+
// to be available.
56+
// NOTE: This reason is used only as a fallback when the infrastructure object is not reporting its own ready condition.
57+
WaitingForInfrastructureFallbackReason = "WaitingForInfrastructure"
58+
)

api/v1alpha3/machine_types.go

+12
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ type MachineStatus struct {
159159
// ObservedGeneration is the latest generation observed by the controller.
160160
// +optional
161161
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
162+
163+
// Conditions defines current service state of the Machine.
164+
// +optional
165+
Conditions Conditions `json:"conditions,omitempty"`
162166
}
163167

164168
// ANCHOR_END: MachineStatus
@@ -231,6 +235,14 @@ type Machine struct {
231235
Status MachineStatus `json:"status,omitempty"`
232236
}
233237

238+
func (m *Machine) GetConditions() Conditions {
239+
return m.Status.Conditions
240+
}
241+
242+
func (m *Machine) SetConditions(conditions Conditions) {
243+
m.Status.Conditions = conditions
244+
}
245+
234246
// +kubebuilder:object:root=true
235247

236248
// MachineList contains a list of Machine

api/v1alpha3/zz_generated.deepcopy.go

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

config/crd/bases/cluster.x-k8s.io_machines.yaml

+44
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,50 @@ spec:
560560
bootstrapReady:
561561
description: BootstrapReady is the state of the bootstrap provider.
562562
type: boolean
563+
conditions:
564+
description: Conditions defines current service state of the Machine.
565+
items:
566+
description: Condition defines an observation of a Cluster API resource
567+
operational state.
568+
properties:
569+
lastTransitionTime:
570+
description: Last time the condition transitioned from one status
571+
to another. This should be when the underlying condition changed.
572+
If that is not known, then using the time when the API field
573+
changed is acceptable.
574+
format: date-time
575+
type: string
576+
message:
577+
description: A human readable message indicating details about
578+
the transition. This field may be empty.
579+
type: string
580+
reason:
581+
description: The reason for the condition's last transition
582+
in CamelCase. The specific API may choose whether or not this
583+
field is considered a guaranteed API. This field may not be
584+
empty.
585+
type: string
586+
severity:
587+
description: Severity provides an explicit classification of
588+
Reason code, so the users or machines can immediately understand
589+
the current situation and act accordingly. The Severity field
590+
MUST be set only when Status=False.
591+
type: string
592+
status:
593+
description: Status of the condition, one of True, False, Unknown.
594+
type: string
595+
type:
596+
description: Type of condition in CamelCase or in foo.example.com/CamelCase.
597+
Many .condition.type values are consistent across resources
598+
like Available, but because arbitrary conditions can be useful
599+
(see .node.status.conditions), the ability to deconflict is
600+
important.
601+
type: string
602+
required:
603+
- status
604+
- type
605+
type: object
606+
type: array
563607
failureMessage:
564608
description: "FailureMessage will be set in the event that there is
565609
a terminal problem reconciling the Machine and will contain a more

controllers/cluster_controller_phases_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ func TestClusterReconcilePhases(t *testing.T) {
130130
var c client.Client
131131
if tt.infraRef != nil {
132132
infraConfig := &unstructured.Unstructured{Object: tt.infraRef}
133-
c = fake.NewFakeClientWithScheme(scheme.Scheme, external.TestGenericInfrastructureCRD, tt.cluster, infraConfig)
133+
c = fake.NewFakeClientWithScheme(scheme.Scheme, external.TestGenericInfrastructureCRD.DeepCopy(), tt.cluster, infraConfig)
134134
} else {
135-
c = fake.NewFakeClientWithScheme(scheme.Scheme, external.TestGenericInfrastructureCRD, tt.cluster)
135+
c = fake.NewFakeClientWithScheme(scheme.Scheme, external.TestGenericInfrastructureCRD.DeepCopy(), tt.cluster)
136136
}
137137
r := &ClusterReconciler{
138138
Client: c,

controllers/machine_controller.go

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import (
4343
kubedrain "sigs.k8s.io/cluster-api/third_party/kubernetes-drain"
4444
"sigs.k8s.io/cluster-api/util"
4545
"sigs.k8s.io/cluster-api/util/annotations"
46+
"sigs.k8s.io/cluster-api/util/conditions"
4647
"sigs.k8s.io/cluster-api/util/patch"
4748
"sigs.k8s.io/cluster-api/util/predicates"
4849
ctrl "sigs.k8s.io/controller-runtime"
@@ -166,6 +167,13 @@ func (r *MachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
166167
}
167168

168169
defer func() {
170+
// always update the readyCondition with the summary of the machine conditions.
171+
conditions.SetSummary(m,
172+
// we want to surface infrastructure problems first, then the others.
173+
conditions.WithConditionOrder(clusterv1.InfrastructureReadyCondition),
174+
conditions.WithStepCounter(clusterv1.MachineSummaryConditionsCount),
175+
)
176+
169177
r.reconcilePhase(ctx, m)
170178
r.reconcileMetrics(ctx, m)
171179

controllers/machine_controller_phases.go

+27-7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3030
"k8s.io/utils/pointer"
3131
"sigs.k8s.io/cluster-api/util/annotations"
32+
"sigs.k8s.io/cluster-api/util/conditions"
3233
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
3334
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3435
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -158,6 +159,14 @@ func (r *MachineReconciler) reconcileExternal(ctx context.Context, cluster *clus
158159

159160
// reconcileBootstrap reconciles the Spec.Bootstrap.ConfigRef object on a Machine.
160161
func (r *MachineReconciler) reconcileBootstrap(ctx context.Context, cluster *clusterv1.Cluster, m *clusterv1.Machine) error {
162+
// If the bootstrap data is populated, set ready and return.
163+
if m.Spec.Bootstrap.DataSecretName != nil {
164+
m.Status.BootstrapReady = true
165+
conditions.MarkTrue(m, clusterv1.BootstrapReadyCondition)
166+
return nil
167+
}
168+
169+
// If the Boostrap ref is nil (and so the machine should use user generated data secret), return.
161170
if m.Spec.Bootstrap.ConfigRef == nil {
162171
return nil
163172
}
@@ -172,12 +181,6 @@ func (r *MachineReconciler) reconcileBootstrap(ctx context.Context, cluster *clu
172181
}
173182
bootstrapConfig := externalResult.Result
174183

175-
// If the bootstrap data is populated, set ready and return.
176-
if m.Spec.Bootstrap.DataSecretName != nil {
177-
m.Status.BootstrapReady = true
178-
return nil
179-
}
180-
181184
// If the bootstrap config is being deleted, return early.
182185
if !bootstrapConfig.GetDeletionTimestamp().IsZero() {
183186
return nil
@@ -187,7 +190,16 @@ func (r *MachineReconciler) reconcileBootstrap(ctx context.Context, cluster *clu
187190
ready, err := external.IsReady(bootstrapConfig)
188191
if err != nil {
189192
return err
190-
} else if !ready {
193+
}
194+
195+
// Report a summary of current status of the bootstrap object defined for this machine.
196+
conditions.SetMirror(m, clusterv1.BootstrapReadyCondition,
197+
conditions.UnstructuredGetter(bootstrapConfig),
198+
conditions.WithFallbackValue(ready, clusterv1.WaitingForDataSecretFallbackReason, clusterv1.ConditionSeverityInfo, ""),
199+
)
200+
201+
// If the bootstrap provider is not ready, requeue.
202+
if !ready {
191203
return errors.Wrapf(&capierrors.RequeueAfterError{RequeueAfter: externalReadyWait},
192204
"Bootstrap provider for Machine %q in namespace %q is not ready, requeuing", m.Name, m.Namespace)
193205
}
@@ -236,6 +248,14 @@ func (r *MachineReconciler) reconcileInfrastructure(ctx context.Context, cluster
236248
return err
237249
}
238250
m.Status.InfrastructureReady = ready
251+
252+
// Report a summary of current status of the infrastructure object defined for this machine.
253+
conditions.SetMirror(m, clusterv1.InfrastructureReadyCondition,
254+
conditions.UnstructuredGetter(infraConfig),
255+
conditions.WithFallbackValue(ready, clusterv1.WaitingForInfrastructureFallbackReason, clusterv1.ConditionSeverityInfo, ""),
256+
)
257+
258+
// If the infrastructure provider is not ready, return early.
239259
if !ready {
240260
return errors.Wrapf(&capierrors.RequeueAfterError{RequeueAfter: externalReadyWait},
241261
"Infrastructure provider for Machine %q in namespace %q is not ready, requeuing", m.Name, m.Namespace,

controllers/machine_controller_phases_test.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
118118
defaultCluster,
119119
defaultKubeconfigSecret,
120120
machine,
121-
external.TestGenericBootstrapCRD,
122-
external.TestGenericInfrastructureCRD,
121+
external.TestGenericBootstrapCRD.DeepCopy(),
122+
external.TestGenericInfrastructureCRD.DeepCopy(),
123123
bootstrapConfig,
124124
infraConfig,
125125
),
@@ -154,8 +154,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
154154
defaultCluster,
155155
defaultKubeconfigSecret,
156156
machine,
157-
external.TestGenericBootstrapCRD,
158-
external.TestGenericInfrastructureCRD,
157+
external.TestGenericBootstrapCRD.DeepCopy(),
158+
external.TestGenericInfrastructureCRD.DeepCopy(),
159159
bootstrapConfig,
160160
infraConfig,
161161
),
@@ -195,8 +195,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
195195
defaultCluster,
196196
defaultKubeconfigSecret,
197197
machine,
198-
external.TestGenericBootstrapCRD,
199-
external.TestGenericInfrastructureCRD,
198+
external.TestGenericBootstrapCRD.DeepCopy(),
199+
external.TestGenericInfrastructureCRD.DeepCopy(),
200200
bootstrapConfig,
201201
infraConfig,
202202
),
@@ -262,8 +262,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
262262
defaultCluster,
263263
defaultKubeconfigSecret,
264264
machine,
265-
external.TestGenericBootstrapCRD,
266-
external.TestGenericInfrastructureCRD,
265+
external.TestGenericBootstrapCRD.DeepCopy(),
266+
external.TestGenericInfrastructureCRD.DeepCopy(),
267267
bootstrapConfig,
268268
infraConfig,
269269
),
@@ -316,8 +316,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
316316
defaultCluster,
317317
defaultKubeconfigSecret,
318318
machine,
319-
external.TestGenericBootstrapCRD,
320-
external.TestGenericInfrastructureCRD,
319+
external.TestGenericBootstrapCRD.DeepCopy(),
320+
external.TestGenericInfrastructureCRD.DeepCopy(),
321321
bootstrapConfig,
322322
infraConfig,
323323
),
@@ -381,8 +381,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
381381
defaultCluster,
382382
defaultKubeconfigSecret,
383383
machine,
384-
external.TestGenericBootstrapCRD,
385-
external.TestGenericInfrastructureCRD,
384+
external.TestGenericBootstrapCRD.DeepCopy(),
385+
external.TestGenericInfrastructureCRD.DeepCopy(),
386386
bootstrapConfig,
387387
infraConfig,
388388
),
@@ -426,8 +426,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
426426
defaultCluster,
427427
defaultKubeconfigSecret,
428428
machine,
429-
external.TestGenericBootstrapCRD,
430-
external.TestGenericInfrastructureCRD,
429+
external.TestGenericBootstrapCRD.DeepCopy(),
430+
external.TestGenericInfrastructureCRD.DeepCopy(),
431431
bootstrapConfig,
432432
infraConfig,
433433
),
@@ -493,8 +493,8 @@ var _ = Describe("Reconcile Machine Phases", func() {
493493
defaultCluster,
494494
defaultKubeconfigSecret,
495495
machine,
496-
external.TestGenericBootstrapCRD,
497-
external.TestGenericInfrastructureCRD,
496+
external.TestGenericBootstrapCRD.DeepCopy(),
497+
external.TestGenericInfrastructureCRD.DeepCopy(),
498498
bootstrapConfig,
499499
infraConfig,
500500
),
@@ -730,8 +730,8 @@ func TestReconcileBootstrap(t *testing.T) {
730730
r := &MachineReconciler{
731731
Client: fake.NewFakeClientWithScheme(scheme.Scheme,
732732
tc.machine,
733-
external.TestGenericBootstrapCRD,
734-
external.TestGenericInfrastructureCRD,
733+
external.TestGenericBootstrapCRD.DeepCopy(),
734+
external.TestGenericInfrastructureCRD.DeepCopy(),
735735
bootstrapConfig,
736736
),
737737
Log: log.Log,
@@ -931,8 +931,8 @@ func TestReconcileInfrastructure(t *testing.T) {
931931
r := &MachineReconciler{
932932
Client: fake.NewFakeClientWithScheme(scheme.Scheme,
933933
tc.machine,
934-
external.TestGenericBootstrapCRD,
935-
external.TestGenericInfrastructureCRD,
934+
external.TestGenericBootstrapCRD.DeepCopy(),
935+
external.TestGenericInfrastructureCRD.DeepCopy(),
936936
infraConfig,
937937
),
938938
Log: log.Log,

0 commit comments

Comments
 (0)