Skip to content

Commit d8f2679

Browse files
Paused condition for machine
This change sets the paused condition false when the machine status has the AuthoritativeAPI set to MachineAPI, otherwise it sets it to true and stops reconciliation.
1 parent 2befcec commit d8f2679

File tree

5 files changed

+353
-97
lines changed

5 files changed

+353
-97
lines changed

pkg/controller/machine/controller.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"reflect"
2424
"time"
2525

26+
openshiftfeatures "github.com/openshift/api/features"
2627
machinev1 "github.com/openshift/api/machine/v1beta1"
2728
"github.com/openshift/machine-api-operator/pkg/metrics"
2829
"github.com/openshift/machine-api-operator/pkg/util"
@@ -74,6 +75,16 @@ const (
7475
skipWaitForDeleteTimeoutSeconds = 1
7576
)
7677

78+
// We export the PausedCondition and reasons as they're shared
79+
// across the Machine and MachineSet controllers.
80+
const (
81+
PausedCondition machinev1.ConditionType = "Paused"
82+
83+
PausedConditionReason = "AuthoritativeAPINotMachineAPI"
84+
85+
NotPausedConditionReason = "AuthoritativeAPIMachineAPI"
86+
)
87+
7788
var DefaultActuator Actuator
7889

7990
func AddWithActuator(mgr manager.Manager, actuator Actuator, gate featuregate.MutableFeatureGate) error {
@@ -97,6 +108,7 @@ func AddWithActuatorOpts(mgr manager.Manager, actuator Actuator, opts controller
97108
return nil
98109
}
99110

111+
// newReconciler returns a new reconcile.Reconciler
100112
func newReconciler(mgr manager.Manager, actuator Actuator, gate featuregate.MutableFeatureGate) reconcile.Reconciler {
101113
r := &ReconcileMachine{
102114
Client: mgr.GetClient(),
@@ -163,12 +175,45 @@ func (r *ReconcileMachine) Reconcile(ctx context.Context, request reconcile.Requ
163175

164176
// Implement controller logic here
165177
machineName := m.GetName()
166-
klog.Infof("%q: reconciling Machine", machineName)
178+
klog.Infof("%v: reconciling Machine", machineName)
167179

168180
// Get the original state of conditions now so that they can be used to calculate the patch later.
169181
// This must be a copy otherwise the referenced slice will be modified by later machine conditions changes.
170182
originalConditions := conditions.DeepCopyConditions(m.Status.Conditions)
171183

184+
if r.gate.Enabled(featuregate.Feature(openshiftfeatures.FeatureGateMachineAPIMigration)) {
185+
// Check Status.AuthoritativeAPI
186+
// If not MachineAPI. Set the paused condition true and return early.
187+
//
188+
// Once we have a webhook, we want to remove the check that the AuthoritativeAPI
189+
// field is populated.
190+
if m.Status.AuthoritativeAPI != "" &&
191+
m.Status.AuthoritativeAPI != machinev1.MachineAuthorityMachineAPI {
192+
conditions.Set(m, conditions.TrueConditionWithReason(
193+
PausedCondition,
194+
PausedConditionReason,
195+
"The AuthoritativeAPI is set to %s", m.Status.AuthoritativeAPI,
196+
))
197+
if patchErr := r.updateStatus(ctx, m, ptr.Deref(m.Status.Phase, ""), nil, originalConditions); patchErr != nil {
198+
klog.Errorf("%v: error patching status: %v", machineName, patchErr)
199+
}
200+
201+
klog.Infof("%v: machine is paused, taking no further action", machineName)
202+
return reconcile.Result{}, nil
203+
}
204+
205+
// Set the paused condition to false, continue reconciliation
206+
conditions.Set(m, conditions.FalseCondition(
207+
PausedCondition,
208+
NotPausedConditionReason,
209+
machinev1.ConditionSeverityInfo,
210+
"The AuthoritativeAPI is set to %s", m.Status.AuthoritativeAPI,
211+
))
212+
if patchErr := r.updateStatus(ctx, m, ptr.Deref(m.Status.Phase, ""), nil, originalConditions); patchErr != nil {
213+
klog.Errorf("%v: error patching status: %v", machineName, patchErr)
214+
}
215+
}
216+
172217
if errList := validateMachine(m); len(errList) > 0 {
173218
err := fmt.Errorf("%v: machine validation failed: %v", machineName, errList.ToAggregate().Error())
174219
klog.Error(err)
@@ -231,14 +276,14 @@ func (r *ReconcileMachine) Reconcile(ctx context.Context, request reconcile.Requ
231276
// we can loose instances, e.g. right after request to create one
232277
// was sent and before a list of node addresses was set.
233278
if len(m.Status.Addresses) > 0 || !isInvalidMachineConfigurationError(err) {
234-
klog.Errorf("%q: failed to delete machine: %v", machineName, err)
279+
klog.Errorf("%v: failed to delete machine: %v", machineName, err)
235280
return delayIfRequeueAfterError(err)
236281
}
237282
}
238283

239284
instanceExists, err := r.actuator.Exists(ctx, m)
240285
if err != nil {
241-
klog.Errorf("%q: failed to check if machine exists: %v", machineName, err)
286+
klog.Errorf("%v: failed to check if machine exists: %v", machineName, err)
242287
return reconcile.Result{}, err
243288
}
244289

@@ -273,7 +318,7 @@ func (r *ReconcileMachine) Reconcile(ctx context.Context, request reconcile.Requ
273318

274319
instanceExists, err := r.actuator.Exists(ctx, m)
275320
if err != nil {
276-
klog.Errorf("%q: failed to check if machine exists: %v", machineName, err)
321+
klog.Errorf("%v: failed to check if machine exists: %v", machineName, err)
277322

278323
conditions.Set(m, conditions.UnknownCondition(
279324
machinev1.InstanceExistsCondition,
@@ -291,7 +336,7 @@ func (r *ReconcileMachine) Reconcile(ctx context.Context, request reconcile.Requ
291336
if instanceExists {
292337
klog.Infof("%v: reconciling machine triggers idempotent update", machineName)
293338
if err := r.actuator.Update(ctx, m); err != nil {
294-
klog.Errorf("%q: error updating machine: %v, retrying in %s seconds", machineName, err, requeueAfter.String())
339+
klog.Errorf("%v: error updating machine: %v, retrying in %v seconds", machineName, err, requeueAfter)
295340

296341
if patchErr := r.updateStatus(ctx, m, ptr.Deref(m.Status.Phase, ""), nil, originalConditions); patchErr != nil {
297342
klog.Errorf("%v: error patching status: %v", machineName, patchErr)
@@ -358,7 +403,7 @@ func (r *ReconcileMachine) Reconcile(ctx context.Context, request reconcile.Requ
358403

359404
klog.Infof("%v: reconciling machine triggers idempotent create", machineName)
360405
if err := r.actuator.Create(ctx, m); err != nil {
361-
klog.Warningf("%q: failed to create machine: %v", machineName, err)
406+
klog.Warningf("%v: failed to create machine: %v", machineName, err)
362407
if isInvalidMachineConfigurationError(err) {
363408
if err := r.updateStatus(ctx, m, machinev1.PhaseFailed, err, originalConditions); err != nil {
364409
return reconcile.Result{}, err

pkg/controller/machine/controller_test.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,16 @@ func TestReconcileRequest(t *testing.T) {
5757
},
5858
},
5959
Spec: machinev1.MachineSpec{
60+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
6061
ProviderSpec: machinev1.ProviderSpec{
6162
Value: &runtime.RawExtension{
6263
Raw: []byte("{}"),
6364
},
6465
},
6566
},
67+
Status: machinev1.MachineStatus{
68+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
69+
},
6670
}
6771
machineProvisioning := machinev1.Machine{
6872
TypeMeta: metav1.TypeMeta{
@@ -78,14 +82,16 @@ func TestReconcileRequest(t *testing.T) {
7882
},
7983
},
8084
Spec: machinev1.MachineSpec{
85+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
8186
ProviderSpec: machinev1.ProviderSpec{
8287
Value: &runtime.RawExtension{
8388
Raw: []byte("{}"),
8489
},
8590
},
8691
},
8792
Status: machinev1.MachineStatus{
88-
Phase: ptr.To[string](machinev1.PhaseProvisioning),
93+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
94+
Phase: ptr.To[string](machinev1.PhaseProvisioning),
8995
},
9096
}
9197
machineProvisioned := machinev1.Machine{
@@ -102,13 +108,15 @@ func TestReconcileRequest(t *testing.T) {
102108
},
103109
},
104110
Spec: machinev1.MachineSpec{
111+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
105112
ProviderSpec: machinev1.ProviderSpec{
106113
Value: &runtime.RawExtension{
107114
Raw: []byte("{}"),
108115
},
109116
},
110117
},
111118
Status: machinev1.MachineStatus{
119+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
112120
Addresses: []corev1.NodeAddress{
113121
{
114122
Type: corev1.NodeInternalIP,
@@ -133,12 +141,16 @@ func TestReconcileRequest(t *testing.T) {
133141
},
134142
},
135143
Spec: machinev1.MachineSpec{
144+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
136145
ProviderSpec: machinev1.ProviderSpec{
137146
Value: &runtime.RawExtension{
138147
Raw: []byte("{}"),
139148
},
140149
},
141150
},
151+
Status: machinev1.MachineStatus{
152+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
153+
},
142154
}
143155
machineDeletingPreDrainHook := machinev1.Machine{
144156
TypeMeta: metav1.TypeMeta{
@@ -155,6 +167,7 @@ func TestReconcileRequest(t *testing.T) {
155167
},
156168
},
157169
Spec: machinev1.MachineSpec{
170+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
158171
LifecycleHooks: machinev1.LifecycleHooks{
159172
PreDrain: []machinev1.LifecycleHook{
160173
{
@@ -170,6 +183,7 @@ func TestReconcileRequest(t *testing.T) {
170183
},
171184
},
172185
Status: machinev1.MachineStatus{
186+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
173187
NodeRef: &corev1.ObjectReference{
174188
Name: "a node",
175189
},
@@ -190,6 +204,7 @@ func TestReconcileRequest(t *testing.T) {
190204
},
191205
},
192206
Spec: machinev1.MachineSpec{
207+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
193208
LifecycleHooks: machinev1.LifecycleHooks{
194209
PreDrain: []machinev1.LifecycleHook{
195210
{
@@ -204,6 +219,9 @@ func TestReconcileRequest(t *testing.T) {
204219
},
205220
},
206221
},
222+
Status: machinev1.MachineStatus{
223+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
224+
},
207225
}
208226
machineDeletingPreTerminateHook := machinev1.Machine{
209227
TypeMeta: metav1.TypeMeta{
@@ -220,6 +238,7 @@ func TestReconcileRequest(t *testing.T) {
220238
},
221239
},
222240
Spec: machinev1.MachineSpec{
241+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
223242
LifecycleHooks: machinev1.LifecycleHooks{
224243
PreTerminate: []machinev1.LifecycleHook{
225244
{
@@ -234,6 +253,9 @@ func TestReconcileRequest(t *testing.T) {
234253
},
235254
},
236255
},
256+
Status: machinev1.MachineStatus{
257+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
258+
},
237259
}
238260
machineFailed := machinev1.Machine{
239261
TypeMeta: metav1.TypeMeta{
@@ -249,14 +271,16 @@ func TestReconcileRequest(t *testing.T) {
249271
},
250272
},
251273
Spec: machinev1.MachineSpec{
252-
ProviderID: ptr.To[string]("providerID"),
274+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
275+
ProviderID: ptr.To[string]("providerID"),
253276
ProviderSpec: machinev1.ProviderSpec{
254277
Value: &runtime.RawExtension{
255278
Raw: []byte("{}"),
256279
},
257280
},
258281
},
259282
Status: machinev1.MachineStatus{
283+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
260284
Addresses: []corev1.NodeAddress{
261285
{
262286
Type: corev1.NodeInternalIP,
@@ -279,14 +303,16 @@ func TestReconcileRequest(t *testing.T) {
279303
},
280304
},
281305
Spec: machinev1.MachineSpec{
282-
ProviderID: ptr.To[string]("providerID"),
306+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
307+
ProviderID: ptr.To[string]("providerID"),
283308
ProviderSpec: machinev1.ProviderSpec{
284309
Value: &runtime.RawExtension{
285310
Raw: []byte("{}"),
286311
},
287312
},
288313
},
289314
Status: machinev1.MachineStatus{
315+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
290316
Addresses: []corev1.NodeAddress{
291317
{
292318
Type: corev1.NodeInternalIP,
@@ -313,6 +339,7 @@ func TestReconcileRequest(t *testing.T) {
313339
},
314340
},
315341
Spec: machinev1.MachineSpec{
342+
AuthoritativeAPI: machinev1.MachineAuthorityMachineAPI,
316343
LifecycleHooks: machinev1.LifecycleHooks{
317344
PreDrain: []machinev1.LifecycleHook{
318345
{
@@ -569,6 +596,9 @@ func TestReconcileRequest(t *testing.T) {
569596
}
570597

571598
func TestUpdateStatus(t *testing.T) {
599+
cleanupFn := StartEnvTest(t)
600+
defer cleanupFn(t)
601+
572602
drainableTrue := conditions.TrueCondition(machinev1.MachineDrainable)
573603
terminableTrue := conditions.TrueCondition(machinev1.MachineTerminable)
574604
defaultLifecycleConditions := []machinev1.Condition{*drainableTrue, *terminableTrue}

0 commit comments

Comments
 (0)