From c33bdac5b812d150757c7cd81097e59d0272e9d5 Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Fri, 13 Feb 2026 16:55:44 +0530 Subject: [PATCH] Bug 10108: Copy LoadBalancer config to AgentClusterInstall for BareMetal platform When using platform: baremetal with loadBalancer: type: UserManaged, the LoadBalancer configuration was not being copied to the AgentClusterInstall manifest. This caused assisted-service to fail validation when using the same VIP for both API and Ingress. Fixes: https://github.com/openshift/installer/issues/10108 --- .../agent/manifests/agentclusterinstall.go | 20 +++++++++++++++++++ .../manifests/agentclusterinstall_test.go | 16 +++++++++++++++ pkg/asset/agent/manifests/util_test.go | 10 ++++++++++ 3 files changed, 46 insertions(+) diff --git a/pkg/asset/agent/manifests/agentclusterinstall.go b/pkg/asset/agent/manifests/agentclusterinstall.go index fe8a6c0ea78..9b92db2da86 100644 --- a/pkg/asset/agent/manifests/agentclusterinstall.go +++ b/pkg/asset/agent/manifests/agentclusterinstall.go @@ -308,6 +308,13 @@ func (a *AgentClusterInstall) Generate(_ context.Context, dependencies asset.Par agentClusterInstall.Spec.IngressVIPs = installConfig.Config.Platform.BareMetal.IngressVIPs agentClusterInstall.Spec.APIVIP = installConfig.Config.Platform.BareMetal.APIVIPs[0] agentClusterInstall.Spec.IngressVIP = installConfig.Config.Platform.BareMetal.IngressVIPs[0] + + // Copy LoadBalancer configuration to allow UserManaged load balancer with same API/Ingress VIPs + if installConfig.Config.Platform.BareMetal.LoadBalancer != nil { + agentClusterInstall.Spec.LoadBalancer = &hiveext.LoadBalancer{ + Type: convertLoadBalancerType(installConfig.Config.Platform.BareMetal.LoadBalancer.Type), + } + } } else if installConfig.Config.Platform.VSphere != nil { vspherePlatform := vsphere.Platform{} if len(installConfig.Config.Platform.VSphere.APIVIPs) > 1 { @@ -654,3 +661,16 @@ func (a *AgentClusterInstall) validateDiskEncryption() field.ErrorList { } return allErrs } + +// convertLoadBalancerType converts the configv1 PlatformLoadBalancerType to hiveext LoadBalancerType. +func convertLoadBalancerType(lbType configv1.PlatformLoadBalancerType) hiveext.LoadBalancerType { + switch lbType { + case configv1.LoadBalancerTypeUserManaged: + return hiveext.LoadBalancerTypeUserManaged + case configv1.LoadBalancerTypeOpenShiftManagedDefault: + return hiveext.LoadBalancerTypeClusterManaged + default: + // Default to ClusterManaged if type is empty or unknown + return hiveext.LoadBalancerTypeClusterManaged + } +} diff --git a/pkg/asset/agent/manifests/agentclusterinstall_test.go b/pkg/asset/agent/manifests/agentclusterinstall_test.go index 665fdccb110..fa1587925ab 100644 --- a/pkg/asset/agent/manifests/agentclusterinstall_test.go +++ b/pkg/asset/agent/manifests/agentclusterinstall_test.go @@ -156,6 +156,12 @@ func TestAgentClusterInstall_Generate(t *testing.T) { goodArbiterACI.Spec.ProvisionRequirements.ArbiterAgents = 1 goodArbiterACI.Spec.ProvisionRequirements.WorkerAgents = 0 + installConfigWithUserManagedLB := getValidOptionalInstallConfigWithUserManagedLB() + goodUserManagedLBACI := getGoodACI() + goodUserManagedLBACI.Spec.LoadBalancer = &hiveext.LoadBalancer{ + Type: hiveext.LoadBalancerTypeUserManaged, + } + cases := []struct { name string dependencies []asset.Asset @@ -322,6 +328,16 @@ func TestAgentClusterInstall_Generate(t *testing.T) { }, expectedConfig: goodArbiterACI, }, + { + name: "valid configuration with UserManaged LoadBalancer", + dependencies: []asset.Asset{ + &workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall}, + installConfigWithUserManagedLB, + &agentconfig.AgentHosts{}, + &agentconfig.AgentConfig{}, + }, + expectedConfig: goodUserManagedLBACI, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/asset/agent/manifests/util_test.go b/pkg/asset/agent/manifests/util_test.go index 8e775ebc12b..2f4de8120a4 100644 --- a/pkg/asset/agent/manifests/util_test.go +++ b/pkg/asset/agent/manifests/util_test.go @@ -10,6 +10,7 @@ import ( "k8s.io/utils/ptr" "sigs.k8s.io/yaml" + configv1 "github.com/openshift/api/config/v1" hiveext "github.com/openshift/assisted-service/api/hiveextension/v1beta1" "github.com/openshift/assisted-service/api/v1beta1" hivev1 "github.com/openshift/hive/apis/hive/v1" @@ -603,6 +604,15 @@ func getInValidAgentHostsConfig() *agentconfig.AgentHosts { } } +// getValidOptionalInstallConfigWithUserManagedLB returns a valid optional install config with UserManaged load balancer. +func getValidOptionalInstallConfigWithUserManagedLB() *agent.OptionalInstallConfig { + installConfig := getValidOptionalInstallConfig() + installConfig.Config.Platform.BareMetal.LoadBalancer = &configv1.BareMetalPlatformLoadBalancer{ + Type: configv1.LoadBalancerTypeUserManaged, + } + return installConfig +} + func getGoodACIDualStack() *hiveext.AgentClusterInstall { goodACI := getGoodACI() goodACI.Spec.Networking.MachineNetwork = append(goodACI.Spec.Networking.MachineNetwork, hiveext.MachineNetworkEntry{