@@ -1452,13 +1452,150 @@ func TestImageBuildDegradedOnFailureAndClearedOnBuildStart(t *testing.T) {
14521452 moscChangeMosb := buildrequest .NewMachineOSBuildFromAPIOrDie (ctx , cs .GetKubeclient (), updated , mcp )
14531453
14541454 // Wait for the second build to start
1455- waitForBuildToStart (t , cs , moscChangeMosb )
1455+ secondMosb := waitForBuildToStart (t , cs , moscChangeMosb )
1456+ t .Logf ("Second build started successfully: %s" , secondMosb .Name )
14561457
14571458 // Wait for and verify ImageBuildDegraded condition is False after the new build starts.
1459+ // The condition should be cleared when the build starts.
14581460 degradedCondition = waitForImageBuildDegradedCondition (ctx , t , cs , layeredMCPName , corev1 .ConditionFalse )
14591461 require .NotNil (t , degradedCondition , "ImageBuildDegraded condition should still be present" )
14601462 assert .Equal (t , string (mcfgv1 .MachineConfigPoolBuilding ), degradedCondition .Reason , "ImageBuildDegraded reason should be Building" )
1461- t .Logf ("ImageBuildDegraded condition correctly cleared to False with message: %s" , degradedCondition .Message )
1463+ t .Logf ("ImageBuildDegraded condition correctly cleared to False when build started with message: %s" , degradedCondition .Message )
1464+
1465+ // Wait for the second build to complete successfully
1466+ finishedBuild := waitForBuildToComplete (t , cs , secondMosb )
1467+ t .Logf ("Second build completed successfully: %s" , finishedBuild .Name )
1468+
1469+ // Wait for the MachineOSConfig to get the new pullspec, which indicates full reconciliation
1470+ waitForMOSCToGetNewPullspec (ctx , t , cs , mosc .Name , string (finishedBuild .Status .DigestedImagePushSpec ))
1471+
1472+ // Wait for and verify ImageBuildDegraded condition is False with reason BuildSucceeded
1473+ degradedCondition = waitForImageBuildDegradedCondition (ctx , t , cs , layeredMCPName , corev1 .ConditionFalse )
1474+ require .NotNil (t , degradedCondition , "ImageBuildDegraded condition should still be present" )
1475+ assert .Equal (t , string (mcfgv1 .MachineConfigPoolBuildSuccess ), degradedCondition .Reason , "ImageBuildDegraded reason should be BuildSuccess" )
1476+ t .Logf ("ImageBuildDegraded condition correctly set to False when build succeeded with message: %s" , degradedCondition .Message )
1477+
1478+ // Verify MCP status is correct after successful build and full reconciliation
1479+ successMcp , err := cs .MachineconfigurationV1Interface .MachineConfigPools ().Get (ctx , layeredMCPName , metav1.GetOptions {})
1480+ require .NoError (t , err )
1481+
1482+ // After successful build completion and full reconciliation, MCP should show:
1483+ // Updated=True, Updating=False, Degraded=False, ImageBuildDegraded=False
1484+ kubeassert .Eventually ().MachineConfigPoolReachesState (successMcp , func (mcp * mcfgv1.MachineConfigPool , err error ) (bool , error ) {
1485+ if err != nil {
1486+ return false , err
1487+ }
1488+ // Return false (keep polling) if conditions don't match expected state
1489+ if ! apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ) ||
1490+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ) ||
1491+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ) ||
1492+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ) {
1493+ return false , nil
1494+ }
1495+
1496+ // Return true when expected state is reached
1497+ t .Logf ("MCP status after successful build - Updated: %v, Updating: %v, Degraded: %v, ImageBuildDegraded: %v" ,
1498+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ),
1499+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ),
1500+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ),
1501+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ))
1502+
1503+ return true , nil
1504+ }, "MCP should reach correct state after successful build (Updated=True, Updating=False, Degraded=False, ImageBuildDegraded=False)" )
1505+
1506+ // Now trigger another build to test MCP status transitions when a new build starts
1507+ t .Logf ("Triggering a third build to test MCP status transitions" )
1508+
1509+ // Modify the containerfile slightly to trigger a new build
1510+ apiMosc , err = cs .MachineconfigurationV1Interface .MachineOSConfigs ().Get (ctx , mosc .Name , metav1.GetOptions {})
1511+ require .NoError (t , err )
1512+
1513+ // Add a comment to the containerfile to change it and trigger a new build
1514+ modifiedDockerfile := cowsayDockerfile + "\n # Comment to trigger new build"
1515+ apiMosc .Spec .Containerfile = []mcfgv1.MachineOSContainerfile {
1516+ {
1517+ ContainerfileArch : mcfgv1 .NoArch ,
1518+ Content : modifiedDockerfile ,
1519+ },
1520+ }
1521+
1522+ updated , err = cs .MachineconfigurationV1Interface .MachineOSConfigs ().Update (ctx , apiMosc , metav1.UpdateOptions {})
1523+ require .NoError (t , err )
1524+
1525+ t .Logf ("Modified containerfile, waiting for third build to start" )
1526+
1527+ // Get the updated MCP to compute the new build
1528+ mcp , err = cs .MachineconfigurationV1Interface .MachineConfigPools ().Get (ctx , layeredMCPName , metav1.GetOptions {})
1529+ require .NoError (t , err )
1530+
1531+ // Compute the new MachineOSBuild name for the third build
1532+ thirdMoscMosb := buildrequest .NewMachineOSBuildFromAPIOrDie (ctx , cs .GetKubeclient (), updated , mcp )
1533+
1534+ // Wait for the third build to start
1535+ thirdMosb := waitForBuildToStart (t , cs , thirdMoscMosb )
1536+ t .Logf ("Third build started: %s" , thirdMosb .Name )
1537+
1538+ // Verify MCP status during active build:
1539+ // Updated=False, Updating=True, Degraded=False, ImageBuildDegraded=False
1540+ buildingMcp , err := cs .MachineconfigurationV1Interface .MachineConfigPools ().Get (ctx , layeredMCPName , metav1.GetOptions {})
1541+ require .NoError (t , err )
1542+
1543+ kubeassert .Eventually ().MachineConfigPoolReachesState (buildingMcp , func (mcp * mcfgv1.MachineConfigPool , err error ) (bool , error ) {
1544+ if err != nil {
1545+ return false , err
1546+ }
1547+ // During build, MCP should show: Updated=False, Updating=True
1548+ if apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ) ||
1549+ ! apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ) ||
1550+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ) ||
1551+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ) {
1552+ return false , nil
1553+ }
1554+
1555+ t .Logf ("MCP status during active build - Updated: %v, Updating: %v, Degraded: %v, ImageBuildDegraded: %v" ,
1556+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ),
1557+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ),
1558+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ),
1559+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ))
1560+
1561+ return true , nil
1562+ }, "MCP should reach correct state during active build (Updated=False, Updating=True, Degraded=False, ImageBuildDegraded=False)" )
1563+
1564+ // Wait for the third build to complete successfully
1565+ finalBuild := waitForBuildToComplete (t , cs , thirdMosb )
1566+ t .Logf ("Third build completed successfully: %s" , finalBuild .Name )
1567+
1568+ // Wait for the MachineOSConfig to get the new pullspec, which indicates full reconciliation
1569+ waitForMOSCToGetNewPullspec (ctx , t , cs , mosc .Name , string (finalBuild .Status .DigestedImagePushSpec ))
1570+
1571+ // Final verification: MCP status should return to:
1572+ // Updated=True, Updating=False, Degraded=False, ImageBuildDegraded=False
1573+ finalMcp , err := cs .MachineconfigurationV1Interface .MachineConfigPools ().Get (ctx , layeredMCPName , metav1.GetOptions {})
1574+ require .NoError (t , err )
1575+
1576+ kubeassert .Eventually ().MachineConfigPoolReachesState (finalMcp , func (mcp * mcfgv1.MachineConfigPool , err error ) (bool , error ) {
1577+ if err != nil {
1578+ return false , err
1579+ }
1580+ // Return false (keep polling) if conditions don't match expected state
1581+ if ! apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ) ||
1582+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ) ||
1583+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ) ||
1584+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ) {
1585+ return false , nil
1586+ }
1587+
1588+ // Return true when expected state is reached
1589+ t .Logf ("Final MCP status after third build completion - Updated: %v, Updating: %v, Degraded: %v, ImageBuildDegraded: %v" ,
1590+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdated ),
1591+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolUpdating ),
1592+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolDegraded ),
1593+ apihelpers .IsMachineConfigPoolConditionTrue (mcp .Status .Conditions , mcfgv1 .MachineConfigPoolImageBuildDegraded ))
1594+
1595+ return true , nil
1596+ }, "MCP should return to correct state after final build completion (Updated=True, Updating=False, Degraded=False, ImageBuildDegraded=False)" )
1597+
1598+ t .Logf ("All MCP status transitions verified successfully across build failure, success, and subsequent new build" )
14621599}
14631600
14641601// TestCurrentMachineOSBuildAnnotationHandling tests that the node controller correctly uses the
0 commit comments