@@ -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,8 +386,64 @@ func isSingletonCondition(singletonConditionTypes []mcfgv1.StateProgress, condit
335
386
return false
336
387
}
337
388
389
+ // func UpdateMachineConfigNodeSpecDesiredImage(fgHandler ctrlcommon.FeatureGatesHandler, node *corev1.Node, mcfgClient mcfgclientset.Interface) error {
390
+ func UpdateMachineConfigNodeSpecDesiredAnnotations (fgHandler ctrlcommon.FeatureGatesHandler , mcfgClient mcfgclientset.Interface , nodeName string , desiredConfig string , desiredImage string ) error {
391
+ if fgHandler == nil {
392
+ return nil
393
+ }
394
+
395
+ // Check that the MachineConfigNode and ImageModeStatusReporting feature gates are enabled
396
+ if ! fgHandler .Enabled (features .FeatureGateMachineConfigNodes ) || ! fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) {
397
+ klog .Infof ("MachineConfigNode FeatureGate is not enabled." )
398
+ return nil
399
+ }
400
+
401
+ if ! fgHandler .Enabled (features .FeatureGateImageModeStatusReporting ) {
402
+ klog .Infof ("ImageModeStatusReporting FeatureGate is not enabled. Please enable the TechPreviewNoUpgrade FeatureSet to use ImageModeStatusReporting." )
403
+ return nil
404
+ }
405
+
406
+ // get the existing MCN
407
+ mcn , mcnErr := mcfgClient .MachineconfigurationV1 ().
408
+ MachineConfigNodes ().
409
+ Get (context .TODO (), nodeName , metav1.GetOptions {})
410
+ // // TODO: figure out the need of this check
411
+ // if needNewMCNode {
412
+ // return fmt.Errorf("No MachineConfigNode exists yet for node %v. Use `GenerateAndApplyMachineConfigNodeSpec` instead.", node)
413
+ // }
414
+ if mcnErr != nil {
415
+ // no existing MCN found since no resource found
416
+ if apierrors .IsNotFound (mcnErr ) {
417
+ return fmt .Errorf ("MCN for %s node does not exits. Skipping MCN spec update." , nodeName )
418
+ }
419
+ return mcnErr
420
+ }
421
+
422
+ // Set the desired config annotation
423
+ mcn .Spec .ConfigVersion .Desired = NotYetSet
424
+ if desiredConfig != "" {
425
+ mcn .Spec .ConfigVersion .Desired = desiredConfig
426
+ }
427
+
428
+ // Set the desired image annotation
429
+ // TODO: figure out if this actually handles the removal of the field
430
+ mcn .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {}
431
+ if desiredImage != "" {
432
+ mcn .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {
433
+ DesiredImage : mcfgv1 .ImageDigestFormat (desiredImage ),
434
+ }
435
+ }
436
+
437
+ if _ , err := mcfgClient .MachineconfigurationV1 ().MachineConfigNodes ().Update (context .TODO (), mcn , metav1.UpdateOptions {FieldManager : "machine-config-operator" }); err != nil {
438
+ return fmt .Errorf ("failed to update the %s mcn spec with the new desired config and image value: %w" ,
439
+ nodeName , err )
440
+ }
441
+ return nil
442
+ }
443
+
338
444
// GenerateAndApplyMachineConfigNodeSpec generates and applies a new MCN spec based off the node state
339
445
func GenerateAndApplyMachineConfigNodeSpec (fgHandler ctrlcommon.FeatureGatesHandler , pool string , node * corev1.Node , mcfgClient mcfgclientset.Interface ) error {
446
+ // TODO: add in this function something to handle addig the desired image annotation if it exists
340
447
if fgHandler == nil || node == nil {
341
448
return nil
342
449
}
@@ -348,7 +455,7 @@ func GenerateAndApplyMachineConfigNodeSpec(fgHandler ctrlcommon.FeatureGatesHand
348
455
// get the existing MCN, or if it DNE create one below
349
456
mcNode , needNewMCNode := createOrGetMachineConfigNode (mcfgClient , node )
350
457
newMCNode := mcNode .DeepCopy ()
351
- // set the spec config version
458
+ // Set the MCN owner references
352
459
newMCNode .ObjectMeta .OwnerReferences = []metav1.OwnerReference {
353
460
{
354
461
APIVersion : "v1" ,
@@ -358,14 +465,22 @@ func GenerateAndApplyMachineConfigNodeSpec(fgHandler ctrlcommon.FeatureGatesHand
358
465
},
359
466
}
360
467
468
+ // Set the desired config version in the MCN
361
469
newMCNode .Spec .ConfigVersion = mcfgv1.MachineConfigNodeSpecMachineConfigVersion {
362
470
Desired : node .Annotations [daemonconsts .DesiredMachineConfigAnnotationKey ],
363
471
}
364
- // Set desired config to NotYetSet if the annotation is empty to satisfy API validation
472
+ // If the desired config does not yet exist for the node, the desired config should be set to NotYetSet
365
473
if newMCNode .Spec .ConfigVersion .Desired == "" {
366
474
newMCNode .Spec .ConfigVersion .Desired = NotYetSet
367
475
}
368
476
477
+ // Set the desired image in the MCN if it exists
478
+ newMCNode .Spec .ConfigImage = mcfgv1.MachineConfigNodeSpecConfigImage {}
479
+ if node .Annotations [daemonconsts .DesiredImageAnnotationKey ] != "" {
480
+ newMCNode .Spec .ConfigImage .DesiredImage = mcfgv1 .ImageDigestFormat (node .Annotations [daemonconsts .DesiredImageAnnotationKey ])
481
+ }
482
+
483
+ // Set the MCN pool and node names
369
484
newMCNode .Spec .Pool = mcfgv1.MCOObjectReference {
370
485
Name : pool ,
371
486
}
0 commit comments