diff --git a/api/v1alpha3/azurecluster_conversion.go b/api/v1alpha3/azurecluster_conversion.go index 8f3f0bcc029e..5e9a2949a99e 100644 --- a/api/v1alpha3/azurecluster_conversion.go +++ b/api/v1alpha3/azurecluster_conversion.go @@ -52,6 +52,7 @@ func (src *AzureCluster) ConvertTo(dstRaw conversion.Hub) error { // nolint dst.Spec.NetworkSpec.APIServerLB.FrontendIPsCount = restored.Spec.NetworkSpec.APIServerLB.FrontendIPsCount dst.Spec.NetworkSpec.APIServerLB.IdleTimeoutInMinutes = restored.Spec.NetworkSpec.APIServerLB.IdleTimeoutInMinutes + dst.Spec.NetworkSpec.OverrideAPIEndpoint = restored.Spec.NetworkSpec.OverrideAPIEndpoint dst.Spec.CloudProviderConfigOverrides = restored.Spec.CloudProviderConfigOverrides dst.Spec.BastionSpec = restored.Spec.BastionSpec @@ -185,6 +186,8 @@ func Convert_v1alpha3_NetworkSpec_To_v1beta1_NetworkSpec(in *NetworkSpec, out *i } } + out.OverrideAPIEndpoint = nil + if err := autoConvert_v1alpha3_LoadBalancerSpec_To_v1beta1_LoadBalancerSpec(&in.APIServerLB, &out.APIServerLB, s); err != nil { return err } diff --git a/api/v1alpha3/zz_generated.conversion.go b/api/v1alpha3/zz_generated.conversion.go index bf30caeb822c..0cc72b4c9bdb 100644 --- a/api/v1alpha3/zz_generated.conversion.go +++ b/api/v1alpha3/zz_generated.conversion.go @@ -1379,6 +1379,7 @@ func autoConvert_v1beta1_NetworkSpec_To_v1alpha3_NetworkSpec(in *v1beta1.Network if err := Convert_v1beta1_LoadBalancerSpec_To_v1alpha3_LoadBalancerSpec(&in.APIServerLB, &out.APIServerLB, s); err != nil { return err } + // WARNING: in.OverrideAPIEndpoint requires manual conversion: does not exist in peer-type // WARNING: in.NodeOutboundLB requires manual conversion: does not exist in peer-type // WARNING: in.ControlPlaneOutboundLB requires manual conversion: does not exist in peer-type // WARNING: in.PrivateDNSZoneName requires manual conversion: does not exist in peer-type diff --git a/api/v1alpha4/azurecluster_conversion.go b/api/v1alpha4/azurecluster_conversion.go index f97e4e1252f3..03e4aa679436 100644 --- a/api/v1alpha4/azurecluster_conversion.go +++ b/api/v1alpha4/azurecluster_conversion.go @@ -39,6 +39,7 @@ func (src *AzureCluster) ConvertTo(dstRaw conversion.Hub) error { // nolint // Restore list of virtual network peerings dst.Spec.NetworkSpec.Vnet.Peerings = restored.Spec.NetworkSpec.Vnet.Peerings + dst.Spec.NetworkSpec.OverrideAPIEndpoint = restored.Spec.NetworkSpec.OverrideAPIEndpoint return nil } @@ -79,3 +80,19 @@ func Convert_v1beta1_VnetSpec_To_v1alpha4_VnetSpec(in *infrav1beta1.VnetSpec, ou func Convert_v1alpha4_VnetSpec_To_v1beta1_VnetSpec(in *VnetSpec, out *infrav1beta1.VnetSpec, s apiconversion.Scope) error { return autoConvert_v1alpha4_VnetSpec_To_v1beta1_VnetSpec(in, out, s) } + +// Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec is an autogenerated conversion function. +func Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(in *NetworkSpec, out *infrav1beta1.NetworkSpec, s apiconversion.Scope) error { + if err := autoConvert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(in, out, s); err != nil { + return err + } + + out.OverrideAPIEndpoint = nil + + return nil +} + +// Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec is an autogenerated conversion function. +func Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in *infrav1beta1.NetworkSpec, out *NetworkSpec, s apiconversion.Scope) error { + return autoConvert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in, out, s) +} diff --git a/api/v1alpha4/zz_generated.conversion.go b/api/v1alpha4/zz_generated.conversion.go index 4c64345c319a..9e8376c1df9b 100644 --- a/api/v1alpha4/zz_generated.conversion.go +++ b/api/v1alpha4/zz_generated.conversion.go @@ -377,16 +377,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*NetworkSpec)(nil), (*v1beta1.NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(a.(*NetworkSpec), b.(*v1beta1.NetworkSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1beta1.NetworkSpec)(nil), (*NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(a.(*v1beta1.NetworkSpec), b.(*NetworkSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*OSDisk)(nil), (*v1beta1.OSDisk)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_OSDisk_To_v1beta1_OSDisk(a.(*OSDisk), b.(*v1beta1.OSDisk), scope) }); err != nil { @@ -497,6 +487,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*NetworkSpec)(nil), (*v1beta1.NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(a.(*NetworkSpec), b.(*v1beta1.NetworkSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*VnetSpec)(nil), (*v1beta1.VnetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_VnetSpec_To_v1beta1_VnetSpec(a.(*VnetSpec), b.(*v1beta1.VnetSpec), scope) }); err != nil { @@ -507,6 +502,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta1.NetworkSpec)(nil), (*NetworkSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(a.(*v1beta1.NetworkSpec), b.(*NetworkSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta1.VnetSpec)(nil), (*VnetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_VnetSpec_To_v1alpha4_VnetSpec(a.(*v1beta1.VnetSpec), b.(*VnetSpec), scope) }); err != nil { @@ -1629,11 +1629,6 @@ func autoConvert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(in *NetworkSpec, ou return nil } -// Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec is an autogenerated conversion function. -func Convert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(in *NetworkSpec, out *v1beta1.NetworkSpec, s conversion.Scope) error { - return autoConvert_v1alpha4_NetworkSpec_To_v1beta1_NetworkSpec(in, out, s) -} - func autoConvert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in *v1beta1.NetworkSpec, out *NetworkSpec, s conversion.Scope) error { if err := Convert_v1beta1_VnetSpec_To_v1alpha4_VnetSpec(&in.Vnet, &out.Vnet, s); err != nil { return err @@ -1642,17 +1637,13 @@ func autoConvert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in *v1beta1.Network if err := Convert_v1beta1_LoadBalancerSpec_To_v1alpha4_LoadBalancerSpec(&in.APIServerLB, &out.APIServerLB, s); err != nil { return err } + // WARNING: in.OverrideAPIEndpoint requires manual conversion: does not exist in peer-type out.NodeOutboundLB = (*LoadBalancerSpec)(unsafe.Pointer(in.NodeOutboundLB)) out.ControlPlaneOutboundLB = (*LoadBalancerSpec)(unsafe.Pointer(in.ControlPlaneOutboundLB)) out.PrivateDNSZoneName = in.PrivateDNSZoneName return nil } -// Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec is an autogenerated conversion function. -func Convert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in *v1beta1.NetworkSpec, out *NetworkSpec, s conversion.Scope) error { - return autoConvert_v1beta1_NetworkSpec_To_v1alpha4_NetworkSpec(in, out, s) -} - func autoConvert_v1alpha4_OSDisk_To_v1beta1_OSDisk(in *OSDisk, out *v1beta1.OSDisk, s conversion.Scope) error { out.OSType = in.OSType out.DiskSizeGB = (*int32)(unsafe.Pointer(in.DiskSizeGB)) diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index 833a581e8719..d007a010e66b 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -19,6 +19,7 @@ package v1beta1 import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/api/resource" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" ) const ( @@ -75,6 +76,10 @@ type NetworkSpec struct { // +optional APIServerLB LoadBalancerSpec `json:"apiServerLB,omitempty"` + // override API Endpoint passed back to Cluster API (hope you know what you are doing, good luck!) + // +optional + OverrideAPIEndpoint *clusterv1.APIEndpoint `json:"overrideAPIEndpoint,omitempty"` + // NodeOutboundLB is the configuration for the node outbound load balancer. // +optional NodeOutboundLB *LoadBalancerSpec `json:"nodeOutboundLB,omitempty"` diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 9d520e82d0c8..8e43918e4e33 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -942,6 +942,11 @@ func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { } } in.APIServerLB.DeepCopyInto(&out.APIServerLB) + if in.OverrideAPIEndpoint != nil { + in, out := &in.OverrideAPIEndpoint, &out.OverrideAPIEndpoint + *out = new(apiv1beta1.APIEndpoint) + **out = **in + } if in.NodeOutboundLB != nil { in, out := &in.NodeOutboundLB, &out.NodeOutboundLB *out = new(LoadBalancerSpec) diff --git a/azure/scope/cluster.go b/azure/scope/cluster.go index 89d1de14625c..afc77c5cdcd4 100644 --- a/azure/scope/cluster.go +++ b/azure/scope/cluster.go @@ -649,6 +649,10 @@ func (s *ClusterScope) AdditionalTags() infrav1.Tags { // APIServerPort returns the APIServerPort to use when creating the load balancer. func (s *ClusterScope) APIServerPort() int32 { + netSpec := s.AzureCluster.Spec.NetworkSpec + if netSpec.OverrideAPIEndpoint != nil { + return netSpec.OverrideAPIEndpoint.Port + } if s.Cluster.Spec.ClusterNetwork != nil && s.Cluster.Spec.ClusterNetwork.APIServerPort != nil { return *s.Cluster.Spec.ClusterNetwork.APIServerPort } @@ -657,6 +661,10 @@ func (s *ClusterScope) APIServerPort() int32 { // APIServerHost returns the hostname used to reach the API server. func (s *ClusterScope) APIServerHost() string { + netSpec := s.AzureCluster.Spec.NetworkSpec + if netSpec.OverrideAPIEndpoint != nil && len(netSpec.OverrideAPIEndpoint.Host) > 0 { + return netSpec.OverrideAPIEndpoint.Host + } if s.IsAPIServerPrivate() { return azure.GeneratePrivateFQDN(s.GetPrivateDNSZoneName()) } diff --git a/azure/scope/cluster_test.go b/azure/scope/cluster_test.go index 2f6dd41b4297..b47ac18eada7 100644 --- a/azure/scope/cluster_test.go +++ b/azure/scope/cluster_test.go @@ -96,6 +96,21 @@ func TestAPIServerHost(t *testing.T) { }, want: "apiserver.example.private", }, + { + name: "override host returned to cluster api.", + azureCluster: infrav1.AzureCluster{ + Spec: infrav1.AzureClusterSpec{ + SubscriptionID: fakeSubscriptionID, + NetworkSpec: infrav1.NetworkSpec{ + OverrideAPIEndpoint: &clusterv1.APIEndpoint{ + Host: "apiserver.example.private", + Port: 443, + }, + }, + }, + }, + want: "apiserver.example.private", + }, } for _, tc := range tests { diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml index af957be38ea1..492e82f09e71 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml @@ -1788,6 +1788,21 @@ spec: description: LBType defines an Azure load balancer Type. type: string type: object + overrideAPIEndpoint: + description: override API Endpoint passed back to Cluster API + (hope you know what you are doing, good luck!) + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + format: int32 + type: integer + required: + - host + - port + type: object privateDNSZoneName: description: PrivateDNSZoneName defines the zone name for the Azure Private DNS.