@@ -135,6 +135,7 @@ func generateAndApplyMachineConfigNodes(
135
135
136
136
// we use this array to see if the MCN has all of its conditions set
137
137
// if not we set a sane default
138
+ // TODO: decide if the image reg stuff should be added here too
138
139
allConditionTypes := []mcfgv1.StateProgress {
139
140
mcfgv1 .MachineConfigNodeUpdatePrepared ,
140
141
mcfgv1 .MachineConfigNodeUpdateExecuted ,
@@ -217,8 +218,20 @@ func generateAndApplyMachineConfigNodes(
217
218
218
219
case condition .Status != metav1 .ConditionFalse && reset :
219
220
condition .Status = metav1 .ConditionFalse
220
- condition .Message = fmt .Sprintf ("Action during update to %s: %s" , newMCNode .Spec .ConfigVersion .Desired , condition .Message )
221
221
condition .LastTransitionTime = metav1 .Now ()
222
+
223
+ // TODO: test this in the enable and disable case
224
+ // Set the update to annotation to the desired rendered MC version by default for the condition message
225
+ updateToMessage := fmt .Sprintf ("Action during update to %s: %s" , newMCNode .Spec .ConfigVersion .Desired , condition .Message )
226
+ // Handle OCL update cases differently
227
+ if newMCNode .Spec .ConfigImage .DesiredImage != newMCNode .Status .ConfigImage .CurrentImage {
228
+ if newMCNode .Spec .ConfigImage .DesiredImage != "" { // Handle case when desired image exists
229
+ updateToMessage = fmt .Sprintf ("Action during update to %s: %s" , newMCNode .Spec .ConfigImage .DesiredImage , condition .Message )
230
+ } else { // When the desired image is empty, it means OCL is being disabled; provide a more useful message in this case
231
+ updateToMessage = fmt .Sprintf ("Action during update to disable image mode: %s" , condition .Message )
232
+ }
233
+ }
234
+ condition .Message = updateToMessage
222
235
}
223
236
condition .DeepCopyInto (& newMCNode .Status .Conditions [i ])
224
237
}
@@ -250,6 +263,27 @@ func generateAndApplyMachineConfigNodes(
250
263
newMCNode .Status .ConfigVersion .Current = node .Annotations [daemonconsts .CurrentMachineConfigAnnotationKey ]
251
264
}
252
265
266
+ // Set current and desired image values in MCN.Status.ConfigImage
267
+ // This is only done when the ImageModeStatusReporting feature gate is enabled
268
+ if fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) {
269
+ // TODO: test if this flow accurately updates the current image annotaiton on OCL disable
270
+ newMCNStatusConfigImage := mcfgv1.MachineConfigNodeStatusConfigImage {}
271
+ currentImageAnnotation := node .Annotations [daemonconsts .CurrentImageAnnotationKey ]
272
+ desiredImageAnnotation := node .Annotations [daemonconsts .DesiredImageAnnotationKey ]
273
+
274
+ // Set current image if annotation exists
275
+ if currentImageAnnotation != "" {
276
+ newMCNStatusConfigImage .CurrentImage = mcfgv1 .ImageDigestFormat (currentImageAnnotation )
277
+ }
278
+
279
+ // Set desired image if annotation exists
280
+ if desiredImageAnnotation != "" {
281
+ newMCNStatusConfigImage .DesiredImage = mcfgv1 .ImageDigestFormat (desiredImageAnnotation )
282
+ }
283
+
284
+ newMCNode .Status .ConfigImage = newMCNStatusConfigImage
285
+ }
286
+
253
287
// if we do not need a new MCN, generate the apply configurations for this object
254
288
if ! needNewMCNode {
255
289
statusconfigVersionApplyConfig := machineconfigurationv1 .MachineConfigNodeStatusMachineConfigVersion ().WithDesired (newMCNode .Status .ConfigVersion .Desired )
@@ -262,6 +296,23 @@ func generateAndApplyMachineConfigNodes(
262
296
WithObservedGeneration (newMCNode .Generation + 1 ).
263
297
WithConfigVersion (statusconfigVersionApplyConfig )
264
298
299
+ // Add ConfigImage to apply configuration if feature gate is enabled and image annotations exist
300
+ if fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) && (newMCNode .Status .ConfigImage .CurrentImage != "" || newMCNode .Status .ConfigImage .DesiredImage != "" ) {
301
+ configImageApplyConfig := machineconfigurationv1 .MachineConfigNodeStatusConfigImage ()
302
+
303
+ // Set current image if it exists
304
+ if newMCNode .Status .ConfigImage .CurrentImage != "" {
305
+ configImageApplyConfig = configImageApplyConfig .WithCurrentImage (newMCNode .Status .ConfigImage .CurrentImage )
306
+ }
307
+
308
+ // Set desired image if it exists
309
+ if newMCNode .Status .ConfigImage .DesiredImage != "" {
310
+ configImageApplyConfig = configImageApplyConfig .WithDesiredImage (newMCNode .Status .ConfigImage .DesiredImage )
311
+ }
312
+
313
+ statusApplyConfig = statusApplyConfig .WithConfigImage (configImageApplyConfig )
314
+ }
315
+
265
316
if fgHandler .Enabled (features .FeatureGatePinnedImages ) {
266
317
if imageSetApplyConfig == nil {
267
318
for _ , imageSet := range newMCNode .Status .PinnedImageSets {
@@ -335,6 +386,51 @@ func isSingletonCondition(singletonConditionTypes []mcfgv1.StateProgress, condit
335
386
return false
336
387
}
337
388
389
+ // UpdateMachineConfigNodeSpecDesiredAnnotations sets the desired config version and image
390
+ // annotation values in the `Spec` of an existing MachineConfigNode resource
391
+ func UpdateMachineConfigNodeSpecDesiredAnnotations (fgHandler ctrlcommon.FeatureGatesHandler , mcfgClient mcfgclientset.Interface , nodeName string , desiredConfig string , desiredImage string ) error {
392
+ if fgHandler == nil {
393
+ return nil
394
+ }
395
+
396
+ // Check that the MachineConfigNode and ImageModeStatusReporting feature gates are enabled
397
+ if ! fgHandler .Enabled (features .FeatureGateMachineConfigNodes ) || ! fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) {
398
+ klog .Infof ("MachineConfigNode or ImageModeStatusReporting FeatureGate is not enabled. Please enable the TechPreviewNoUpgrade FeatureSet to use ImageModeStatusReporting." )
399
+ return nil
400
+ }
401
+
402
+ // Get the existing MCN
403
+ mcn , mcnErr := mcfgClient .MachineconfigurationV1 ().MachineConfigNodes ().Get (context .TODO (), nodeName , metav1.GetOptions {})
404
+ // TODO: check if we need to make an MCN at this point instead then or if we get to this point that we should have an MCN
405
+ if mcnErr != nil {
406
+ // no existing MCN found since no resource found
407
+ if apierrors .IsNotFound (mcnErr ) {
408
+ return fmt .Errorf ("MCN for %s node does not exits. Skipping MCN spec update." , nodeName )
409
+ }
410
+ return mcnErr
411
+ }
412
+
413
+ // Set the desired config annotation
414
+ mcn .Spec .ConfigVersion .Desired = NotYetSet
415
+ if desiredConfig != "" {
416
+ mcn .Spec .ConfigVersion .Desired = desiredConfig
417
+ }
418
+
419
+ // Set the desired image annotation
420
+ mcn .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {}
421
+ if desiredImage != "" {
422
+ mcn .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {
423
+ DesiredImage : mcfgv1 .ImageDigestFormat (desiredImage ),
424
+ }
425
+ }
426
+
427
+ // Update the MCN resource
428
+ if _ , err := mcfgClient .MachineconfigurationV1 ().MachineConfigNodes ().Update (context .TODO (), mcn , metav1.UpdateOptions {FieldManager : "machine-config-operator" }); err != nil {
429
+ return fmt .Errorf ("failed to update the %s mcn spec with the new desired config and image value: %w" , nodeName , err )
430
+ }
431
+ return nil
432
+ }
433
+
338
434
// GenerateAndApplyMachineConfigNodeSpec generates and applies a new MCN spec based off the node state
339
435
func GenerateAndApplyMachineConfigNodeSpec (fgHandler ctrlcommon.FeatureGatesHandler , pool string , node * corev1.Node , mcfgClient mcfgclientset.Interface ) error {
340
436
if fgHandler == nil || node == nil {
@@ -345,10 +441,11 @@ func GenerateAndApplyMachineConfigNodeSpec(fgHandler ctrlcommon.FeatureGatesHand
345
441
klog .Infof ("MCN Featuregate is not enabled. Please enable the TechPreviewNoUpgrade featureset to use MachineConfigNodes" )
346
442
return nil
347
443
}
444
+
348
445
// get the existing MCN, or if it DNE create one below
349
446
mcNode , needNewMCNode := createOrGetMachineConfigNode (mcfgClient , node )
350
447
newMCNode := mcNode .DeepCopy ()
351
- // set the spec config version
448
+ // Set the MCN owner references
352
449
newMCNode .ObjectMeta .OwnerReferences = []metav1.OwnerReference {
353
450
{
354
451
APIVersion : "v1" ,
@@ -358,14 +455,25 @@ func GenerateAndApplyMachineConfigNodeSpec(fgHandler ctrlcommon.FeatureGatesHand
358
455
},
359
456
}
360
457
458
+ // Set the desired config version in the MCN
361
459
newMCNode .Spec .ConfigVersion = mcfgv1.MachineConfigNodeSpecMachineConfigVersion {
362
460
Desired : node .Annotations [daemonconsts .DesiredMachineConfigAnnotationKey ],
363
461
}
364
- // Set desired config to NotYetSet if the annotation is empty to satisfy API validation
462
+ // If the desired config does not yet exist for the node, the desired config should be set to NotYetSet
365
463
if newMCNode .Spec .ConfigVersion .Desired == "" {
366
464
newMCNode .Spec .ConfigVersion .Desired = NotYetSet
367
465
}
368
466
467
+ // Check that the ImageModeStatusReporting feature gate is enabled
468
+ if fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) {
469
+ // Set the desired image in the MCN if it exists
470
+ newMCNode .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {}
471
+ if node .Annotations [daemonconsts .DesiredImageAnnotationKey ] != "" {
472
+ newMCNode .Spec .ConfigImage .DesiredImage = mcfgv1 .ImageDigestFormat (node .Annotations [daemonconsts .DesiredImageAnnotationKey ])
473
+ }
474
+ }
475
+
476
+ // Set the MCN pool and node names
369
477
newMCNode .Spec .Pool = mcfgv1.MCOObjectReference {
370
478
Name : pool ,
371
479
}
0 commit comments