Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5d3643e
OCPBUGS-112075: skip proxy for OSImageStream discovery in HyperShift
jparrill Aug 19, 2026
95d8caf
OCPBUGS-109739: Increase rpm-ostree rebase retry backoff and preserve…
umohnani8 Aug 17, 2026
9c9ad82
OCPBUGS-98258: Fix upstreams for CoreDNS pods on Cloud platforms
sadasu Aug 6, 2026
83bd4e3
Merge pull request #6423 from openshift-cherrypick-robot/cherry-pick-…
sdodson Aug 20, 2026
f3805fe
Merge pull request #6429 from openshift-cherrypick-robot/cherry-pick-…
openshift-merge-bot[bot] Aug 21, 2026
d20efd9
Merge pull request #6425 from openshift-cherrypick-robot/cherry-pick-…
openshift-merge-bot[bot] Aug 21, 2026
c1a172e
bootimage: fix Confidential Cluster skip
djoshy Aug 14, 2026
eee8cd5
test: use Image struct for Azure fake boot image
djoshy Aug 19, 2026
27ba14f
Merge pull request #6448 from djoshy/5.0-azure-fix
openshift-merge-bot[bot] Aug 25, 2026
92a7021
bootimage: handle gen1 removal
djoshy Aug 26, 2026
cca0e99
OCPBUGS-64623: Use kubernetes scheme in drain controller event recorder
proietfb Aug 24, 2026
307b4ad
Merge pull request #6453 from djoshy/5.0-azure-gen1-fix
openshift-merge-bot[bot] Aug 26, 2026
524359c
Merge pull request #6455 from openshift-cherrypick-robot/cherry-pick-…
openshift-merge-bot[bot] Aug 27, 2026
2957d5f
Revert TNF GNS
vimauro Aug 24, 2026
ad929f9
controller: modify MachineOSBuild event and condition update function…
isabella-janssen Aug 24, 2026
6965d49
Merge pull request #6460 from openshift-cherrypick-robot/cherry-pick-…
openshift-merge-bot[bot] Aug 27, 2026
ac99dd9
Merge pull request #6463 from openshift-cherrypick-robot/cherry-pick-…
openshift-merge-bot[bot] Sep 1, 2026
837570c
chore: update AMIs
openshift-ci-robot Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion pkg/controller/bootimage/ami.go
Original file line number Diff line number Diff line change
Expand Up @@ -1922,5 +1922,45 @@ var AllowedAMIs = sets.New(
"ami-0e6a4ffe9dd1dee56", "ami-0e721586ef04044d2", "ami-0e75465363d8378f0", "ami-0e79be45f2303f422", "ami-0e9a0f9e1a4c49b92",
"ami-0ec2f94496976cb5f", "ami-0f186d1a862e47c8f", "ami-0f480726bfb767807", "ami-0f5633a3440704a9d", "ami-0f567edf0859e3b39",
"ami-0f5b937ac530500da", "ami-0f752ff59c8b0d39f", "ami-0f7add16535539145", "ami-0f99bc65b81da18b0", "ami-0fb8045529e752a6f",
"ami-0fc49ff64e479b1f5", "ami-0fe15e383af1e71d4", "ami-0feb18654dafb55c6", "ami-0fed99e2bf80aea18",
"ami-0fc49ff64e479b1f5", "ami-0fe15e383af1e71d4", "ami-0feb18654dafb55c6", "ami-0fed99e2bf80aea18", "ami-0012f6e857cddb9a3",
"ami-0045babcefcde70ad", "ami-00468ad759fd2d7b1", "ami-0047b12f232e22bdb", "ami-004f5780eeabcc87a", "ami-005037a6054789706",
"ami-006ceba545a1fc2e4", "ami-007f29d20651b2967", "ami-009377da169f64c55", "ami-00bfd186388b8380c", "ami-00c830a23b63d4db9",
"ami-0104bef90662c2efd", "ami-013471b87ace7db65", "ami-0180fbb452a64abda", "ami-0186aa560203c6187", "ami-019714e3997bd07a7",
"ami-01973dc30b4a31e97", "ami-01b95e0b30b0ea34c", "ami-01c33df45d576ada8", "ami-01e235e15a11eb0df", "ami-01f5e666e658ad1ab",
"ami-01f61d4d53aa2a9b6", "ami-0202fd73338464188", "ami-0209332acb1e36853", "ami-021ab1158e383ad67", "ami-022be29d2d96de13c",
"ami-02432a7c4ea6e9a3c", "ami-0252011a6427df19f", "ami-02855fa6ea815d06b", "ami-028d46fe147b1cd05", "ami-029820074e2035ae4",
"ami-02c128dd1f85bbfee", "ami-02cf45d9cde4da953", "ami-02d471a336435f50a", "ami-02da66fa6254fc712", "ami-02e03c003116ad480",
"ami-02e9e72117f14091c", "ami-02eef3fb87f70be2f", "ami-030d8b87df4826acc", "ami-033b1cf48ab5ed019", "ami-034f4fd71b696a198",
"ami-035173bcb9f915eb7", "ami-035f7d85a34f9141c", "ami-036ce05c3a726a8d8", "ami-036d1e4326e2e57e0", "ami-037f5cb9b1933c006",
"ami-03877388d3d6b48fb", "ami-0388cbd1d1429c4c7", "ami-0396eaa6d72c99d19", "ami-039d3e3ccfd6e5408", "ami-03c999a079ddde054",
"ami-03ce0238d62983330", "ami-03cf2640751bbd84e", "ami-03d2f6868a810f16e", "ami-03f1bd9904faf3058", "ami-041bc3e9395d5bae7",
"ami-041c964652b0dff67", "ami-042619f83fbf591a2", "ami-0429c8240a8bad514", "ami-043a374947b137a5a", "ami-0445378debb78f68d",
"ami-044735b15a195810a", "ami-0489962ff65796c68", "ami-04946ee6336a5fdef", "ami-049e29474b06cb799", "ami-04a0abd17c9871211",
"ami-04a0b75d82d641bb3", "ami-04aaae682d4870b7c", "ami-04c82f85d00c673ec", "ami-04dad94be03c8edd9", "ami-04ee1d46e3cb6f3a4",
"ami-04f93fc50a015aaf2", "ami-050ce14fc96932898", "ami-0519ca783d0405301", "ami-052e0663607930a9d", "ami-0532c87dee2e73586",
"ami-0537af5461a58de15", "ami-055eb42c9ac922b60", "ami-0561d6e6064bb80d9", "ami-056e65e8594c0ab06", "ami-056fb8260d98c0caa",
"ami-057ecb31eeebbfb28", "ami-058733b6471456f95", "ami-0589fd0ec9af25c2a", "ami-05918a69def5e5faa", "ami-05b1fc1eeda2c2c1c",
"ami-0615fc30e2ca45e48", "ami-063a2c8fc9621d0bc", "ami-0666d4665ad983743", "ami-06752c2e4bb6e0bc7", "ami-068ef76d0b96c5962",
"ami-06a4512ffd164d0fd", "ami-06a79aa0169e4e304", "ami-06a9715660aa4d7e2", "ami-06aabe4eb1a6f5474", "ami-06b5e1e107986965c",
"ami-06c3ad3985c66cdb1", "ami-06d064935da85e2c8", "ami-070aec204c9ffc2f9", "ami-071bbf4bfda59764e", "ami-0724620758713e90a",
"ami-0789ec6c1b57d2aee", "ami-079b5123ee195034a", "ami-079bdaf173b88cb3d", "ami-07a8f5c9253f89580", "ami-07ca8313ee5def8ee",
"ami-07da482306ca26c90", "ami-07dd252d750c538b1", "ami-07e3b70729b7e899b", "ami-07e428ccbe30749f5", "ami-07e83229bad88b7da",
"ami-07f1f64194c014cbe", "ami-0806b1e81c02af6a5", "ami-081c6b6190b8a96f9", "ami-082401c298bb6d19a", "ami-083d6d8c0825b5e77",
"ami-0860c0446f0d0edff", "ami-0866e7d7620662cb8", "ami-086c4794dcbad5968", "ami-08815949a9efd3f9d", "ami-08894d33a8238ae1f",
"ami-08a8683cdafafd025", "ami-08c5a756919080ed3", "ami-08f70223a9e974fc2", "ami-090feca83f7df5af0", "ami-09116dce527366abf",
"ami-0932ffb821f6ede9a", "ami-09390eb5fa05105cb", "ami-0943da5f9c2e42bf1", "ami-094be75c86c860575", "ami-09611a0d3a8b93f5e",
"ami-096a14dab9918e653", "ami-0977a293b90a4dcd4", "ami-099b01d69f79c10de", "ami-09a227b539f0108dd", "ami-09a6deb5147f425c1",
"ami-09ca2efc70796ebb9", "ami-09f6c75068ed7d615", "ami-09fc07d00a02e1a75", "ami-0a5ec51a9dad18def", "ami-0adf76c9ca225891d",
"ami-0ae0c3359ca6aa3df", "ami-0b6ed5cedd5f504dd", "ami-0b7e179e05a0c8aed", "ami-0b7f7c4c5c1fec821", "ami-0b8633f808328467f",
"ami-0b924a152c5107772", "ami-0b9f7f6c100a4e205", "ami-0bc0b6ee7b08808e7", "ami-0bc200ec19c86b0e8", "ami-0bfa9e8ab847dc884",
"ami-0c085c5a670ed56e2", "ami-0c0e529a01661c018", "ami-0c14479e30c43c66e", "ami-0c1ea9aa8ff649700", "ami-0c20892f27a4b30ab",
"ami-0c25f24ad1d9ca99f", "ami-0c26e0c09048c67d2", "ami-0c4d8f126d6b48df5", "ami-0c5ce5542a11b1625", "ami-0c5de5918dd160bfb",
"ami-0c706f9ea60c95209", "ami-0c71ad8672b323c81", "ami-0c7b24d72d02ab879", "ami-0c8ac6d2d139ed219", "ami-0c9350869efbbadb8",
"ami-0cbf4be274bd5af48", "ami-0cdc52b7f6229c45d", "ami-0cec7d60b4e64aa10", "ami-0d16876eaa5aa6dfa", "ami-0d1905921e683afab",
"ami-0d26db932afc5b88b", "ami-0d2babc9b55094593", "ami-0d3b1aefc3285a531", "ami-0d5313a5ea3e8ffb7", "ami-0d54c1cbf3f2e8fec",
"ami-0d59eeb1aefa86643", "ami-0d78c386ff1adf973", "ami-0d7d88bd7bfc31a5c", "ami-0d8786dc679ff9a19", "ami-0d955ed29c6286ffb",
"ami-0e14bfe5873a1d8f6", "ami-0e1bf6775f2d3adc5", "ami-0e2fa97cd490f90ff", "ami-0e319599cb7cad8df", "ami-0e350eb65edaab597",
"ami-0e5fa644db548e0ca", "ami-0e8580dcb3b54bc65", "ami-0eee7e0e3b42ca954", "ami-0ef6a62b4537e52c4", "ami-0efc707d4bb86da28",
"ami-0f1df8bccf443942f", "ami-0f29e5607aaabba57", "ami-0f3f3636d4e229c66", "ami-0f650e3d802e28557", "ami-0f6fb9bca28c962d0",
"ami-0fb5741e6b20f10f1", "ami-0fc60b0d0fb8d5a8c", "ami-0fc93459d0da40cf1", "ami-0fd7aabf34efa0f19",
)
114 changes: 93 additions & 21 deletions pkg/controller/bootimage/boot_image_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
opv1 "github.com/openshift/api/operator/v1"
configlistersv1 "github.com/openshift/client-go/config/listers/config/v1"
fakemcopclient "github.com/openshift/client-go/operator/clientset/versioned/fake"
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
Expand All @@ -25,7 +26,6 @@ import (
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
)

func TestIsClusterStable(t *testing.T) {
Expand Down Expand Up @@ -546,14 +546,14 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
fakeClient := fake.NewClientset(testSecret)

tests := []struct {
name string
arch string
currentImage machinev1beta1.Image
expectedImage machinev1beta1.Image
expectPatch bool
expectSkip bool
streamData *stream.Stream // Custom stream data for specific tests
securityProfile *machinev1beta1.SecurityProfile // Custom security profile for specific tests
name string
arch string
currentImage machinev1beta1.Image
expectedImage machinev1beta1.Image
expectPatch bool
expectReconcileSkipped bool
streamData *stream.Stream // Custom stream data for specific tests
securityProfile *machinev1beta1.SecurityProfile // Custom security profile for specific tests
}{
{
name: "Legacy Gen1 upload image transitions to marketplace Gen1",
Expand Down Expand Up @@ -682,7 +682,6 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
},
{
name: "Skip unsupported architecture s390x",
Expand All @@ -695,7 +694,6 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
},
{
name: "Paid OCP Gen1 image updates to newer version",
Expand Down Expand Up @@ -813,7 +811,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
expectReconcileSkipped: true,
streamData: &stream.Stream{
Architectures: map[string]stream.Arch{
"x86_64": {
Expand All @@ -835,7 +833,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
expectReconcileSkipped: true,
streamData: &stream.Stream{
Architectures: map[string]stream.Arch{
"x86_64": {
Expand All @@ -848,6 +846,84 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
},
},
},
{
name: "Skip when Gen1 Azure marketplace image is unavailable (Gen1 removal)",
arch: "x86_64",
currentImage: machinev1beta1.Image{
Offer: "aro4",
Publisher: "azureopenshift",
ResourceID: "",
SKU: "aro_418",
Version: "418.94.20241201",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectReconcileSkipped: true,
streamData: &stream.Stream{
Architectures: map[string]stream.Arch{
"x86_64": {
RHELCoreOSExtensions: &rhcos.Extensions{
Marketplace: &rhcos.Marketplace{
Azure: &rhcos.AzureMarketplace{
NoPurchasePlan: &rhcos.AzureMarketplaceImages{
// Gen1 intentionally omitted, mirroring the stream once
// Gen1 Azure images are removed upstream (CORS-4441).
Gen2: &rhcos.AzureMarketplaceImage{
Offer: "aro4",
Publisher: "azureopenshift",
SKU: "aro_50-x64",
Version: "50.0.20260601",
},
},
},
},
},
},
},
},
},
{
name: "Post-Gen1-removal Gen2 SKU ('gen2' suffix) still updates",
arch: "x86_64",
currentImage: machinev1beta1.Image{
Offer: "aro4",
Publisher: "azureopenshift",
ResourceID: "",
SKU: "aro_5-0_x86_gen2",
Version: "50.0.20260601",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectedImage: machinev1beta1.Image{
Offer: "aro4",
Publisher: "azureopenshift",
ResourceID: "",
SKU: "aro_5-0_x86_gen2",
Version: "50.0.20260701",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectPatch: true,
streamData: &stream.Stream{
Architectures: map[string]stream.Arch{
"x86_64": {
RHELCoreOSExtensions: &rhcos.Extensions{
Marketplace: &rhcos.Marketplace{
Azure: &rhcos.AzureMarketplace{
NoPurchasePlan: &rhcos.AzureMarketplaceImages{
// Gen1 intentionally omitted, mirroring the stream once
// Gen1 Azure images are removed upstream (CORS-4441).
Gen2: &rhcos.AzureMarketplaceImage{
Offer: "aro4",
Publisher: "azureopenshift",
SKU: "aro_5-0_x86_gen2",
Version: "50.0.20260701",
},
},
},
},
},
},
},
},
},
{
name: "Skip machineset with ConfidentialVM SecurityType",
arch: "x86_64",
Expand All @@ -859,7 +935,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
expectReconcileSkipped: true,
securityProfile: &machinev1beta1.SecurityProfile{
Settings: machinev1beta1.SecuritySettings{
SecurityType: "ConfidentialVM",
Expand All @@ -877,7 +953,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
Version: "419.94.20250101",
Type: machinev1beta1.AzureImageTypeMarketplaceNoPlan,
},
expectSkip: true,
expectReconcileSkipped: true,
securityProfile: &machinev1beta1.SecurityProfile{
Settings: machinev1beta1.SecuritySettings{
SecurityType: "TrustedLaunch",
Expand Down Expand Up @@ -954,7 +1030,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {
testStreamData = tt.streamData
}

patchRequired, _, updatedProviderSpec, _, err := reconcileAzureProviderSpec(
patchRequired, reconcileSkipped, updatedProviderSpec, _, err := reconcileAzureProviderSpec(
testStreamData,
tt.arch,
infra,
Expand All @@ -965,11 +1041,7 @@ func TestReconcileAzureProviderSpec(t *testing.T) {

require.NoError(t, err)

if tt.expectSkip {
assert.False(t, patchRequired, "Expected no patch for skipped case")
return
}

assert.Equal(t, tt.expectReconcileSkipped, reconcileSkipped, "Reconcile skipped mismatch")
assert.Equal(t, tt.expectPatch, patchRequired, "Patch required mismatch")

if tt.expectPatch {
Expand Down
30 changes: 19 additions & 11 deletions pkg/controller/bootimage/platform_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func reconcileAzureProviderSpec(streamData *stream.Stream, arch string, _ *oscon

if providerSpec.SecurityProfile != nil && providerSpec.SecurityProfile.Settings.SecurityType != "" {
klog.Infof("Skipping update for %s, machinesets/controlplanemachinesets with a SecurityType defined(%s in this case) is not currently supported for Azure", machineSetName, providerSpec.SecurityProfile.Settings.SecurityType)
return false, false, nil, "", nil
return false, true, nil, "", nil
}

currentImage := providerSpec.Image
Expand Down Expand Up @@ -326,7 +326,8 @@ func reconcileAzureProviderSpec(streamData *stream.Stream, arch string, _ *oscon
// Uploaded images(legacy) have a "gen2" in the resourceID field to indicate hyperGenV2
//
// Unpaid marketplace images:
// - have a "v2" in the SKU field to indicate hyperGenV2
// - have a "v2" in the SKU field to indicate hyperGenV2 (e.g. "aro_422-v2")
// - have a "gen2" in the SKU field to indicate hyperGenV2 (5.0+, e.g. "aro_5-0_x86_gen2")
// - aarch64 machinesets can only use hyperGenV2 images
//
// Paid marketplace images(MCO-1790):
Expand All @@ -337,16 +338,20 @@ func reconcileAzureProviderSpec(streamData *stream.Stream, arch string, _ *oscon
case usesLegacyImageUpload:
usesHyperVGen2 = strings.Contains(currentImage.ResourceID, "gen2")
case providerSpec.Image.Type == machinev1beta1.AzureImageTypeMarketplaceNoPlan:
usesHyperVGen2 = strings.Contains(currentImage.SKU, "v2") || arch == "aarch64"
usesHyperVGen2 = strings.Contains(currentImage.SKU, "v2") || strings.Contains(currentImage.SKU, "gen2") || arch == "aarch64"
default:
usesHyperVGen2 = !strings.Contains(currentImage.SKU, "gen1")
}

// Determine target image from RHCOS stream
targetImage, err := getTargetImageFromStream(streamArch, azureVariant, usesHyperVGen2, arch)
targetImage, reconcileSkipped, err := getTargetImageFromStream(streamArch, azureVariant, usesHyperVGen2, arch)
if err != nil {
return false, false, nil, "", err
}
if reconcileSkipped {
klog.Infof("Skipping machineset %s, no Gen1 Azure marketplace image available for architecture %s", machineSetName, arch)
return false, true, nil, "", nil
}

// If the current image matches, nothing to do here
// Q: Should we enhance this to do version comparisons?
Expand Down Expand Up @@ -415,8 +420,11 @@ func determineAzureVariant(usesLegacyImageUpload bool, currentImage machinev1bet
return "", fmt.Errorf("could not determine azure marketplace variant, cannot update boot images")
}

// getTargetImageFromStream determines the correct Azure marketplace image based on architecture and variant
func getTargetImageFromStream(streamArch *stream.Arch, variant AzureVariant, usesHyperVGen2 bool, arch string) (machinev1beta1.Image, error) {
// getTargetImageFromStream determines the correct Azure marketplace image based on architecture and variant.
// Returns reconcileSkipped=true (with no error) when a Gen1 image is requested but the stream no longer
// publishes one, e.g. once Gen1 Azure images are removed upstream (see CORS-4441): the boot image update is
// skipped for this MachineSet rather than treated as an error, so skew enforcement can flag it as out of date.
func getTargetImageFromStream(streamArch *stream.Arch, variant AzureVariant, usesHyperVGen2 bool, arch string) (machinev1beta1.Image, bool, error) {
marketplace := streamArch.RHELCoreOSExtensions.Marketplace.Azure

var imageSet *rhcos.AzureMarketplaceImages
Expand All @@ -438,24 +446,24 @@ func getTargetImageFromStream(streamArch *stream.Arch, variant AzureVariant, use
case AzureVariantOKEEMEA:
imageSet = marketplace.OKEEMEA
default:
return machinev1beta1.Image{}, fmt.Errorf("unsupported Azure variant")
return machinev1beta1.Image{}, false, fmt.Errorf("unsupported Azure variant")
}

if imageSet == nil {
return machinev1beta1.Image{}, fmt.Errorf("no Azure marketplace images available for variant %s", variant)
return machinev1beta1.Image{}, false, fmt.Errorf("no Azure marketplace images available for variant %s", variant)
}

var streamImage *rhcos.AzureMarketplaceImage

// arm64 only uses hyperGenV2
if usesHyperVGen2 {
if imageSet.Gen2 == nil {
return machinev1beta1.Image{}, fmt.Errorf("no Gen2 Azure marketplace image available for architecture %s", arch)
return machinev1beta1.Image{}, false, fmt.Errorf("no Gen2 Azure marketplace image available for architecture %s", arch)
}
streamImage = imageSet.Gen2
} else {
if imageSet.Gen1 == nil {
return machinev1beta1.Image{}, fmt.Errorf("no Gen1 Azure marketplace image available for architecture %s", arch)
return machinev1beta1.Image{}, true, nil
}
streamImage = imageSet.Gen1
}
Expand All @@ -464,5 +472,5 @@ func getTargetImageFromStream(streamArch *stream.Arch, variant AzureVariant, use
// Convert stream image to Azure machine image
targetImage := getAzureImageFromStreamImage(*streamImage, isPaidImage)

return targetImage, nil
return targetImage, false, nil
}
Loading