From d0501e5b71af47ab855a90c3862ade83af633568 Mon Sep 17 00:00:00 2001 From: Dan Clark Date: Fri, 13 Feb 2026 14:06:51 -0500 Subject: [PATCH] Update openshift installer to support the new Azure IL6 cloud regions --- pkg/asset/installconfig/azure/session.go | 16 ++++++++-------- pkg/asset/installconfig/azure/validation.go | 10 ---------- pkg/asset/manifests/azure/cloudproviderconfig.go | 10 +++++++++- pkg/asset/manifests/cloudproviderconfig.go | 4 ++-- pkg/asset/manifests/infrastructure.go | 2 +- pkg/asset/manifests/proxy.go | 2 +- pkg/asset/rhcos/image.go | 3 +++ pkg/infrastructure/azure/azure.go | 6 +++++- pkg/types/azure/platform.go | 2 +- pkg/types/azure/validation/platform.go | 7 ------- 10 files changed, 30 insertions(+), 32 deletions(-) diff --git a/pkg/asset/installconfig/azure/session.go b/pkg/asset/installconfig/azure/session.go index 33cbc02ff0b..3e75e46ab22 100644 --- a/pkg/asset/installconfig/azure/session.go +++ b/pkg/asset/installconfig/azure/session.go @@ -73,8 +73,8 @@ func GetSession(cloudName azure.CloudEnvironment, armEndpoint string) (*Session, func GetSessionWithCredentials(cloudName azure.CloudEnvironment, armEndpoint string, credentials *Credentials) (*Session, error) { var cloudEnv azureenv.Environment var err error - switch cloudName { - case azure.StackCloud: + switch { + case armEndpoint != "": cloudEnv, err = azureenv.EnvironmentFromURL(armEndpoint) default: cloudEnv, err = azureenv.EnvironmentFromName(string(cloudName)) @@ -124,8 +124,8 @@ func GetSessionWithCredentials(cloudName azure.CloudEnvironment, armEndpoint str func GetCloudConfiguration(cloudName azure.CloudEnvironment, armEndpoint string) (*cloud.Configuration, error) { var cloudEnv azureenv.Environment var err error - switch cloudName { - case azure.StackCloud: + switch { + case armEndpoint != "": cloudEnv, err = azureenv.EnvironmentFromURL(armEndpoint) default: cloudEnv, err = azureenv.EnvironmentFromName(string(cloudName)) @@ -135,8 +135,8 @@ func GetCloudConfiguration(cloudName azure.CloudEnvironment, armEndpoint string) } var cloudConfig cloud.Configuration - switch cloudName { - case azure.StackCloud: + switch { + case armEndpoint != "": cloudConfig = cloud.Configuration{ ActiveDirectoryAuthorityHost: cloudEnv.ActiveDirectoryEndpoint, Services: map[cloud.ServiceName]cloud.ServiceConfiguration{ @@ -146,9 +146,9 @@ func GetCloudConfiguration(cloudName azure.CloudEnvironment, armEndpoint string) }, }, } - case azure.USGovernmentCloud: + case cloudName == azure.USGovernmentCloud: cloudConfig = cloud.AzureGovernment - case azure.ChinaCloud: + case cloudName == azure.ChinaCloud: cloudConfig = cloud.AzureChina default: cloudConfig = cloud.AzurePublic diff --git a/pkg/asset/installconfig/azure/validation.go b/pkg/asset/installconfig/azure/validation.go index a07ae672ff5..aa6a635faff 100644 --- a/pkg/asset/installconfig/azure/validation.go +++ b/pkg/asset/installconfig/azure/validation.go @@ -763,16 +763,6 @@ func validateResourceGroup(client API, fieldPath *field.Path, platform *aztypes. allErrs = append(allErrs, field.Invalid(fieldPath.Child("resourceGroupName"), platform.ResourceGroupName, fmt.Sprintf("resource group has conflicting tags %s", strings.Join(conflictingTagKeys, ", ")))) } - ids, err := client.ListResourceIDsByGroup(context.TODO(), platform.ResourceGroupName) - if err != nil { - return append(allErrs, field.InternalError(fieldPath.Child("resourceGroupName"), fmt.Errorf("failed to list resources in the resource group: %w", err))) - } - if l := len(ids); l > 0 { - if len(ids) > 2 { - ids = ids[:2] - } - allErrs = append(allErrs, field.Invalid(fieldPath.Child("resourceGroupName"), platform.ResourceGroupName, fmt.Sprintf("resource group must be empty but it has %d resources like %s ...", l, strings.Join(ids, ", ")))) - } return allErrs } diff --git a/pkg/asset/manifests/azure/cloudproviderconfig.go b/pkg/asset/manifests/azure/cloudproviderconfig.go index ec691bda4cf..7b8dc5a3b20 100644 --- a/pkg/asset/manifests/azure/cloudproviderconfig.go +++ b/pkg/asset/manifests/azure/cloudproviderconfig.go @@ -69,10 +69,18 @@ func (params CloudProviderConfig) JSON() (string, error) { } if params.CloudName == azure.StackCloud { - config.authConfig.ResourceManagerEndpoint = params.ResourceManagerEndpoint + config.authConfig.UseManagedIdentityExtension = false + config.LoadBalancerSku = "basic" config.UseInstanceMetadata = false } + if params.ResourceManagerEndpoint != "" { + config.authConfig.ResourceManagerEndpoint = params.ResourceManagerEndpoint + // Disable Azure Stack Cloud if resource manager endpoint is not empty and not + // azure stack cloud + config.DisableAzureStackCloud = params.CloudName != azure.StackCloud + } + buff := &bytes.Buffer{} encoder := json.NewEncoder(buff) encoder.SetIndent("", "\t") diff --git a/pkg/asset/manifests/cloudproviderconfig.go b/pkg/asset/manifests/cloudproviderconfig.go index 53e9d08ae3d..65b4a9fd50a 100644 --- a/pkg/asset/manifests/cloudproviderconfig.go +++ b/pkg/asset/manifests/cloudproviderconfig.go @@ -186,10 +186,10 @@ NodeIPFamilies=ipv4 } cm.Data[cloudProviderConfigDataKey] = azureConfig - if installConfig.Azure.CloudName == azuretypes.StackCloud { + if installConfig.Azure.CloudName == azuretypes.StackCloud || installConfig.Azure.ARMEndpoint != "" { b, err := json.Marshal(session.Environment) if err != nil { - return errors.Wrap(err, "could not serialize Azure Stack endpoints") + return errors.Wrap(err, "could not serialize Azure endpoints") } cm.Data[cloudProviderEndpointsKey] = string(b) } diff --git a/pkg/asset/manifests/infrastructure.go b/pkg/asset/manifests/infrastructure.go index bc1ac019e31..3e23c364b4a 100644 --- a/pkg/asset/manifests/infrastructure.go +++ b/pkg/asset/manifests/infrastructure.go @@ -155,7 +155,7 @@ func (i *Infrastructure) Generate(ctx context.Context, dependencies asset.Parent if nrg := installConfig.Config.Platform.Azure.NetworkResourceGroupName; nrg != "" { config.Status.PlatformStatus.Azure.NetworkResourceGroupName = nrg } - if installConfig.Config.Platform.Azure.CloudName == azure.StackCloud { + if installConfig.Config.Platform.Azure.ARMEndpoint != "" { config.Status.PlatformStatus.Azure.ARMEndpoint = installConfig.Config.Platform.Azure.ARMEndpoint } if len(installConfig.Config.Azure.UserTags) > 0 { diff --git a/pkg/asset/manifests/proxy.go b/pkg/asset/manifests/proxy.go index 16f47384641..bcc268387f1 100644 --- a/pkg/asset/manifests/proxy.go +++ b/pkg/asset/manifests/proxy.go @@ -160,7 +160,7 @@ func createNoProxy(installConfig *installconfig.InstallConfig, network *Networki if platform == azure.Name && installConfig.Azure.CloudName != azure.PublicCloud { // https://learn.microsoft.com/en-us/azure/virtual-network/what-is-ip-address-168-63-129-16 set.Insert("168.63.129.16") - if installConfig.Azure.CloudName == azure.StackCloud { + if installConfig.Config.Platform.Azure.ARMEndpoint != "" { set.Insert(installConfig.Config.Azure.ARMEndpoint) } } diff --git a/pkg/asset/rhcos/image.go b/pkg/asset/rhcos/image.go index aeef055a389..3b34cc00c6b 100644 --- a/pkg/asset/rhcos/image.go +++ b/pkg/asset/rhcos/image.go @@ -139,6 +139,9 @@ func osImage(ctx context.Context, ic *installconfig.InstallConfig, machinePool * } return "", fmt.Errorf("%s: No openstack build found", streamArchPrefix) case azure.Name: + if config.Platform.Azure.ClusterOSImage != "" { + return config.Platform.Azure.ClusterOSImage, nil + } ext := streamArch.RHELCoreOSExtensions if platform.Azure.CloudName == azure.StackCloud { return platform.Azure.ClusterOSImage, nil diff --git a/pkg/infrastructure/azure/azure.go b/pkg/infrastructure/azure/azure.go index 12afe71bf9e..a155cfccdf5 100644 --- a/pkg/infrastructure/azure/azure.go +++ b/pkg/infrastructure/azure/azure.go @@ -201,7 +201,11 @@ func (p *Provider) InfraReady(ctx context.Context, in clusterapi.InfraReadyInput } azureDisk := streamArch.RHELCoreOSExtensions.AzureDisk - imageURL := azureDisk.URL + + imageURL := installConfig.Platform.Azure.ClusterOSImage + if imageURL == "" { + imageURL = azureDisk.URL + } rawImageVersion := strings.ReplaceAll(azureDisk.Release, "-", "_") imageVersion := rawImageVersion[:len(rawImageVersion)-6] diff --git a/pkg/types/azure/platform.go b/pkg/types/azure/platform.go index 4ab7df3a205..365414dceef 100644 --- a/pkg/types/azure/platform.go +++ b/pkg/types/azure/platform.go @@ -43,7 +43,7 @@ type Platform struct { // ARMEndpoint is the endpoint for the Azure API when installing on Azure Stack. ARMEndpoint string `json:"armEndpoint,omitempty"` - // ClusterOSImage is the url of a storage blob in the Azure Stack environment containing an RHCOS VHD. This field is required for Azure Stack and not applicable to Azure. + // ClusterOSImage is the url of a storage blob in the Azure environment containing an RHCOS VHD. ClusterOSImage string `json:"clusterOSImage,omitempty"` // BaseDomainResourceGroupName specifies the resource group where the Azure DNS zone for the base domain is found. This field is optional when creating a private cluster, otherwise required. diff --git a/pkg/types/azure/validation/platform.go b/pkg/types/azure/validation/platform.go index 611a54f47b4..b3fe873de47 100644 --- a/pkg/types/azure/validation/platform.go +++ b/pkg/types/azure/validation/platform.go @@ -152,13 +152,6 @@ func ValidatePlatform(p *azure.Platform, publish types.PublishingStrategy, fldPa switch cloud := p.CloudName; cloud { case azure.StackCloud: allErrs = append(allErrs, validateAzureStack(p, fldPath)...) - default: - if p.ARMEndpoint != "" { - allErrs = append(allErrs, field.Required(fldPath.Child("armEndpoint"), fmt.Sprintf("ARM endpoint must not be set when the cloud name is %s", cloud))) - } - if p.ClusterOSImage != "" { - allErrs = append(allErrs, field.Required(fldPath.Child("clusterOSImage"), fmt.Sprintf("clusterOSImage must not be set when the cloud name is %s", cloud))) - } } allErrs = append(allErrs, validateIPFamily(p.IPFamily, fldPath.Child("ipFamily"))...)