@@ -13,6 +13,7 @@ import (
13
13
imagev1clientset "github.com/openshift/client-go/image/clientset/versioned"
14
14
mcfgclientset "github.com/openshift/client-go/machineconfiguration/clientset/versioned"
15
15
routeclientset "github.com/openshift/client-go/route/clientset/versioned"
16
+ "github.com/openshift/machine-config-operator/pkg/apihelpers"
16
17
"github.com/openshift/machine-config-operator/pkg/controller/build/buildrequest"
17
18
"github.com/openshift/machine-config-operator/pkg/controller/build/constants"
18
19
"github.com/openshift/machine-config-operator/pkg/controller/build/imagebuilder"
@@ -117,7 +118,7 @@ func (b *buildReconciler) updateMachineOSConfig(ctx context.Context, old, cur *m
117
118
118
119
// Whenever the MachineOSConfig spec has changed, create a new MachineOSBuild.
119
120
if ! equality .Semantic .DeepEqual (old .Spec , cur .Spec ) {
120
- klog .Infof ("Detected MachineOSConfig change for %s" , cur .Name )
121
+ klog .Infof ("[updateMachineOSConfig] Detected MachineOSConfig change and kicking off createNewMachineOSBuildOrReuseExisting for %s" , cur .Name )
121
122
return b .createNewMachineOSBuildOrReuseExisting (ctx , cur , false )
122
123
}
123
124
@@ -331,7 +332,7 @@ func (b *buildReconciler) updateMachineOSConfigStatus(ctx context.Context, mosc
331
332
332
333
// skip the status update if the current image pullspec equals the digest image pushspec.
333
334
if mosc .Status .CurrentImagePullSpec == mosb .Status .DigestedImagePushSpec {
334
- klog .Infof ("MachineOSConfig %q already has final image pushspec for MachineOSBuild %q" , mosc .Name , mosb .Name )
335
+ klog .Infof ("[updateMachineOSConfig] MachineOSConfig %q already has final image pushspec for MachineOSBuild %q" , mosc .Name , mosb .Name )
335
336
return nil
336
337
}
337
338
@@ -373,13 +374,11 @@ func (b *buildReconciler) UpdateMachineConfigPool(ctx context.Context, oldMCP, c
373
374
func (b * buildReconciler ) updateMachineConfigPool (ctx context.Context , oldMCP , curMCP * mcfgv1.MachineConfigPool ) error {
374
375
if oldMCP .Spec .Configuration .Name != curMCP .Spec .Configuration .Name {
375
376
klog .Infof ("Rendered config for pool %s changed from %s to %s" , curMCP .Name , oldMCP .Spec .Configuration .Name , curMCP .Spec .Configuration .Name )
376
- if err := b .createNewMachineOSBuildOrReuseExistingForPoolChange (ctx , curMCP ); err != nil {
377
+ if err := b .reconcilePoolChange (ctx , curMCP ); err != nil {
377
378
return fmt .Errorf ("could not create or reuse existing MachineOSBuild for MachineConfigPool %q change: %w" , curMCP .Name , err )
378
379
}
379
380
}
380
381
381
- // Not sure if we need to do this here yet or not.
382
- // TODO: Determine if we should call b.syncMachineConfigPools() here or not.
383
382
return b .syncAll (ctx )
384
383
}
385
384
@@ -556,8 +555,8 @@ func (b *buildReconciler) createNewMachineOSBuildOrReuseExisting(ctx context.Con
556
555
// In this situation, we've determined that the MachineOSBuild does not
557
556
// exist, so we need to create it.
558
557
if k8serrors .IsNotFound (err ) {
559
- _ , err := b .mcfgclient .MachineconfigurationV1 ().MachineOSBuilds ().Create (ctx , mosb , metav1.CreateOptions {})
560
- if err != nil && ! k8serrors . IsAlreadyExists ( err ) {
558
+ mosb , err := b .mcfgclient .MachineconfigurationV1 ().MachineOSBuilds ().Create (ctx , mosb , metav1.CreateOptions {})
559
+ if err != nil {
561
560
return fmt .Errorf ("could not create new MachineOSBuild %q: %w" , mosb .Name , err )
562
561
}
563
562
klog .Infof ("New MachineOSBuild created: %s" , mosb .Name )
@@ -1188,12 +1187,35 @@ func (b *buildReconciler) syncMachineOSBuild(ctx context.Context, mosb *mcfgv1.M
1188
1187
return fmt .Errorf ("could not get MachineConfigPool from MachineOSBuild %q: %w" , mosb .Name , err )
1189
1188
}
1190
1189
1191
- // An mosb which had previously been forgotten by the queue and is no longer desired by the mcp should not build
1192
1190
if mosb .ObjectMeta .Labels [constants .RenderedMachineConfigLabelKey ] != mcp .Spec .Configuration .Name {
1193
1191
klog .Infof ("The MachineOSBuild %q which builds the rendered Machine Config %q is no longer desired by the MCP %q" , mosb .Name , mosb .ObjectMeta .Labels [constants .RenderedMachineConfigLabelKey ], mosb .ObjectMeta .Labels [constants .TargetMachineConfigPoolLabelKey ])
1194
1192
return nil
1195
1193
}
1196
1194
1195
+ oldMCName := mcp .Status .Configuration .Name
1196
+ newMCName := mcp .Spec .Configuration .Name
1197
+
1198
+ oldRendered , err := b .machineConfigLister .Get (oldMCName )
1199
+ if err != nil {
1200
+ return err
1201
+ }
1202
+ newRendered , err := b .machineConfigLister .Get (newMCName )
1203
+ if err != nil {
1204
+ return err
1205
+ }
1206
+
1207
+ old := mcp .DeepCopy ()
1208
+ old .Spec .Configuration .Name = mcp .Status .Configuration .Name
1209
+
1210
+ needsImageRebuild , err := b .reconcileImageRebuild (old , mcp )
1211
+ if err != nil {
1212
+ return err
1213
+ }
1214
+ if oldRendered != newRendered && ! needsImageRebuild {
1215
+ klog .Infof ("[syncMachineOSBuild] MachineOSBuild %q: only layering changes → skipping builder" , mosb .Name )
1216
+ return nil
1217
+ }
1218
+
1197
1219
mosbState := ctrlcommon .NewMachineOSBuildState (mosb )
1198
1220
1199
1221
if mosbState .IsInTerminalState () {
@@ -1290,7 +1312,7 @@ func (b *buildReconciler) syncMachineOSConfig(ctx context.Context, mosc *mcfgv1.
1290
1312
}
1291
1313
}
1292
1314
1293
- klog .Infof ("No matching MachineOSBuild found for MachineOSConfig %q, will create one" , mosc .Name )
1315
+ klog .Infof ("syncMachineOSConfig: No matching MachineOSBuild found for MachineOSConfig %q, will create one by kicking off createNewMachineOSBuildOrReuseExisting " , mosc .Name )
1294
1316
if err := b .createNewMachineOSBuildOrReuseExisting (ctx , mosc , false ); err != nil {
1295
1317
return fmt .Errorf ("could not create new or reuse existing MachineOSBuild for MachineOSConfig %q: %w" , mosc .Name , err )
1296
1318
}
@@ -1328,6 +1350,130 @@ func (b *buildReconciler) syncMachineConfigPools(ctx context.Context) error {
1328
1350
// if needed.
1329
1351
func (b * buildReconciler ) syncMachineConfigPool (ctx context.Context , mcp * mcfgv1.MachineConfigPool ) error {
1330
1352
return b .timeObjectOperation (mcp , syncingVerb , func () error {
1331
- return b .createNewMachineOSBuildOrReuseExistingForPoolChange (ctx , mcp )
1353
+ return b .reconcilePoolChange (ctx , mcp )
1354
+ })
1355
+ }
1356
+
1357
+ func (b * buildReconciler ) reconcilePoolChange (ctx context.Context , mcp * mcfgv1.MachineConfigPool ) error {
1358
+ mosc , err := utils .GetMachineOSConfigForMachineConfigPool (mcp , b .utilListers ())
1359
+ if err != nil {
1360
+ // Not opted in yet, so nothing for us to do.
1361
+ klog .Infof ("buildReconciler: no MachineOSConfig for pool %q, skipping" , mcp .Name )
1362
+ return nil
1363
+ }
1364
+
1365
+ oldRendered := mcp .Status .Configuration .Name
1366
+ newRendered := mcp .Spec .Configuration .Name
1367
+
1368
+ // old pool
1369
+ old := mcp .DeepCopy ()
1370
+ old .Spec .Configuration .Name = mcp .Status .Configuration .Name
1371
+ firstOptIn := mosc .Annotations [constants .CurrentMachineOSBuildAnnotationKey ]
1372
+ if firstOptIn == "" {
1373
+ return fmt .Errorf ("no current build annotation on MachineOSConfig %q" , mosc .Name )
1374
+ }
1375
+
1376
+ needsImageRebuild , err := b .reconcileImageRebuild (old , mcp )
1377
+ if err != nil {
1378
+ return err
1379
+ }
1380
+
1381
+ if (oldRendered != newRendered && needsImageRebuild ) || firstOptIn == "" {
1382
+ klog .Infof ("[reconcilePoolChange] pool %q: detected extension/kernel/OSImageURL change → will rebuild image" , mcp .Name )
1383
+ } else if oldRendered != newRendered && ! needsImageRebuild {
1384
+ klog .Infof ("[reconcilePoolChange] pool %q: only layering changes → reusing existing image" , mcp .Name )
1385
+ prevPullSpec := mosc .Status .CurrentImagePullSpec
1386
+ oldMOSB , err := utils .GetMachineOSBuildForImagePullspec (string (prevPullSpec ), b .utilListers ())
1387
+ if err != nil {
1388
+ klog .Infof ("[reconcilePoolChange] mosb %s not found" , oldMOSB .Name )
1389
+ return err
1390
+ }
1391
+ return b .reuseImageForNewMOSB (ctx , mosc , oldMOSB )
1392
+ }
1393
+
1394
+ return b .createNewMachineOSBuildOrReuseExisting (ctx , mosc , needsImageRebuild )
1395
+
1396
+ }
1397
+
1398
+ // reuseImageForNewMOSB creates a new MOSB (for the new rendered-MC name)
1399
+ // but populates its status from oldMosb so that no build actually runs.
1400
+ func (b * buildReconciler ) reuseImageForNewMOSB (ctx context.Context , mosc * mcfgv1.MachineOSConfig , oldMosb * mcfgv1.MachineOSBuild ,
1401
+ ) error {
1402
+ // Look up the MCP
1403
+ mcp , err := b .machineConfigPoolLister .Get (mosc .Spec .MachineConfigPool .Name )
1404
+ if err != nil {
1405
+ return err
1406
+ }
1407
+
1408
+ // Build the new MOSB object
1409
+ osImageURLs , err := ctrlcommon .GetOSImageURLConfig (ctx , b .kubeclient )
1410
+ if err != nil {
1411
+ return err
1412
+ }
1413
+ newMosb , err := buildrequest .NewMachineOSBuild (
1414
+ buildrequest.MachineOSBuildOpts {
1415
+ MachineOSConfig : mosc ,
1416
+ MachineConfigPool : mcp ,
1417
+ OSImageURLConfig : osImageURLs ,
1418
+ })
1419
+ if err != nil {
1420
+ return err
1421
+ }
1422
+ newMosb .SetOwnerReferences ([]metav1.OwnerReference {
1423
+ * metav1 .NewControllerRef (mosc , mcfgv1 .SchemeGroupVersion .WithKind ("MachineOSConfig" )),
1332
1424
})
1425
+
1426
+ // Create it if not already there
1427
+ _ , err = b .machineOSBuildLister .Get (newMosb .Name )
1428
+ if k8serrors .IsNotFound (err ) {
1429
+ if newMosb , err = b .mcfgclient .
1430
+ MachineconfigurationV1 ().
1431
+ MachineOSBuilds ().
1432
+ Create (ctx , newMosb , metav1.CreateOptions {}); err != nil {
1433
+ return err
1434
+ }
1435
+ } else if err != nil {
1436
+ return err
1437
+ }
1438
+
1439
+ // Change its status so it’s “Succeeded” with the old image
1440
+ toUpdate , err := b .getMachineOSBuildForUpdate (newMosb )
1441
+ if err != nil {
1442
+ return err
1443
+ }
1444
+ oldStatus := toUpdate .Status
1445
+
1446
+ toUpdate .Status .DigestedImagePushSpec = oldMosb .Status .DigestedImagePushSpec
1447
+
1448
+ for _ , c := range apihelpers .MachineOSBuildSucceededConditions () {
1449
+ apihelpers .SetMachineOSBuildCondition (& toUpdate .Status , c )
1450
+ }
1451
+
1452
+ if err := b .setStatusOnMachineOSBuildIfNeeded (ctx , toUpdate , oldStatus , toUpdate .Status ); err != nil {
1453
+ return err
1454
+ }
1455
+
1456
+ // re-point the MC to the NEW build
1457
+ return b .updateMachineOSConfigStatus (ctx , mosc , toUpdate )
1458
+ }
1459
+
1460
+ // reconcilePoolChange returns (annotateRebuild bool, reuseOnly bool, err error)
1461
+ func (b * buildReconciler ) reconcileImageRebuild (oldMCP , curMCP * mcfgv1.MachineConfigPool ) (bool , error ) {
1462
+
1463
+ curr , err := b .machineConfigLister .Get (oldMCP .Spec .Configuration .Name )
1464
+ if err != nil {
1465
+ return false , err
1466
+ }
1467
+ des , err := b .machineConfigLister .Get (curMCP .Spec .Configuration .Name )
1468
+ if err != nil {
1469
+ return false , err
1470
+ }
1471
+
1472
+ needsImageRebuild := ctrlcommon .RequiresRebuild (curr , des )
1473
+ if needsImageRebuild {
1474
+ klog .Info ("[reconcileImageRebuild] needsimage rebuild is true, signalling a rebuild" )
1475
+ return true , nil
1476
+ }
1477
+
1478
+ return false , nil
1333
1479
}
0 commit comments