From 4b8679a085c1a285de0c75429c14ff69ddf92462 Mon Sep 17 00:00:00 2001 From: Dmitri Fedotov Date: Mon, 7 Oct 2024 18:01:53 +0300 Subject: [PATCH] add calico bgp --- .../charts/calico-bgp/Chart.yaml | 4 + .../templates/bgpconfiguration.yaml | 29 ++++ .../charts/calico-bgp/templates/bgppeer.yaml | 14 ++ .../charts/calico-bgp/values.yaml | 5 + .../shoot-system-components/values.yaml | 3 + hack/api-reference/api.md | 150 ++++++++++++++++++ pkg/apis/metal/types_controlplane.go | 33 ++++ pkg/apis/metal/v1alpha1/types_controlplane.go | 42 +++++ .../metal/v1alpha1/zz_generated.conversion.go | 74 +++++++++ .../metal/v1alpha1/zz_generated.deepcopy.go | 57 +++++++ pkg/apis/metal/zz_generated.deepcopy.go | 57 +++++++ pkg/controller/controlplane/valuesprovider.go | 73 ++++++++- .../controlplane/valuesprovider_test.go | 118 ++++++++++++++ pkg/metal/types.go | 4 + 14 files changed, 662 insertions(+), 1 deletion(-) create mode 100644 charts/internal/shoot-system-components/charts/calico-bgp/Chart.yaml create mode 100644 charts/internal/shoot-system-components/charts/calico-bgp/templates/bgpconfiguration.yaml create mode 100644 charts/internal/shoot-system-components/charts/calico-bgp/templates/bgppeer.yaml create mode 100644 charts/internal/shoot-system-components/charts/calico-bgp/values.yaml diff --git a/charts/internal/shoot-system-components/charts/calico-bgp/Chart.yaml b/charts/internal/shoot-system-components/charts/calico-bgp/Chart.yaml new file mode 100644 index 0000000..3724431 --- /dev/null +++ b/charts/internal/shoot-system-components/charts/calico-bgp/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: Helm chart for Calico BGP +name: calico-bgp +version: 0.1.0 diff --git a/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgpconfiguration.yaml b/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgpconfiguration.yaml new file mode 100644 index 0000000..b2453e8 --- /dev/null +++ b/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgpconfiguration.yaml @@ -0,0 +1,29 @@ +apiVersion: crd.projectcalico.org/v1 +kind: BGPConfiguration +metadata: + name: default +spec: + logSeverityScreen: {{ .Values.bgp.logSeverityScreen }} + nodeToNodeMeshEnabled: {{ .Values.bgp.nodeToNodeMeshEnabled }} + asNumber: {{ required ".Values.bgp.asNumber is required" .Values.bgp.asNumber }} + {{ if .Values.bgp.serviceLoadBalancerIPs }} + serviceLoadBalancerIPs: + {{- range $cidr := .Values.bgp.serviceLoadBalancerIPs }} + - cidr: {{ $cidr }} + {{- end }} + {{- end }} + {{ if .Values.bgp.serviceExternalIPs }} + serviceExternalIPs: + {{- range $cidr := .Values.bgp.serviceExternalIPs }} + - cidr: {{ $cidr }} + {{- end }} + {{- end }} + {{ if .Values.bgp.serviceClusterIPs }} + serviceClusterIPs: + {{- range $cidr := .Values.bgp.serviceClusterIPs }} + - cidr: {{ $cidr }} + {{- end }} + {{- end }} + listenPort: {{ .Values.bgp.listenPort }} + bindMode: {{ .Values.bgp.bindMode }} + diff --git a/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgppeer.yaml b/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgppeer.yaml new file mode 100644 index 0000000..e3a0ad9 --- /dev/null +++ b/charts/internal/shoot-system-components/charts/calico-bgp/templates/bgppeer.yaml @@ -0,0 +1,14 @@ +{{- if .Values.bgp.peers }} +{{- range $peer := .Values.bgp.peers }} +apiVersion: crd.projectcalico.org/v1 +kind: BGPPeer +metadata: + name: bgppeer-{{ $peer.peerIP }}-{{ $peer.asNumber }} +spec: + asNumber: ${{ required ".peer.asNumber is required" peer.asNumber }} + {{- if $peer.nodeSelector }} + nodeSelector: {{ $peer.nodeSelector }} + {{- end }} + peerIP: ${{ required ".peer.peerIP is required" peer.peerIP }} +{{- end }} +{{- end }} diff --git a/charts/internal/shoot-system-components/charts/calico-bgp/values.yaml b/charts/internal/shoot-system-components/charts/calico-bgp/values.yaml new file mode 100644 index 0000000..532b38a --- /dev/null +++ b/charts/internal/shoot-system-components/charts/calico-bgp/values.yaml @@ -0,0 +1,5 @@ +bgp: + logSeverityScreen: Info + nodeToNodeMeshEnabled: false + listenPort: 179 + bindMode: NodeIP diff --git a/charts/internal/shoot-system-components/values.yaml b/charts/internal/shoot-system-components/values.yaml index ac42ceb..74c8ddf 100644 --- a/charts/internal/shoot-system-components/values.yaml +++ b/charts/internal/shoot-system-components/values.yaml @@ -3,3 +3,6 @@ cloud-controller-manager: metallb: enabled: false + +calico-bgp: + enabled: false diff --git a/hack/api-reference/api.md b/hack/api-reference/api.md index 8355b88..e5523c4 100644 --- a/hack/api-reference/api.md +++ b/hack/api-reference/api.md @@ -180,6 +180,142 @@ string +

BgpPeer +

+

+(Appears on: +CalicoBgpConfig) +

+

+

BgpPeer contains configuration for BGPPeer resource.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+peerIP
+ +string + +
+(Optional) +

PeerIP contains IP address of BGP peer followed by an optional port number to peer with.

+
+asNumber
+ +int + +
+(Optional) +

ASNumber contains the AS number of the BGP peer.

+
+nodeSelector
+ +string + +
+(Optional) +

NodeSelector is a key-value pair to select nodes that should have this peering.

+
+

CalicoBgpConfig +

+

+(Appears on: +LoadBalancerConfig) +

+

+

CalicoBgpConfig contains BGP configuration settings for calico.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+asNumber
+ +int + +
+(Optional) +

ASNumber is the default AS number used by a node.

+
+serviceLoadBalancerIPs
+ +[]string + +
+(Optional) +

ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes Service LoadBalancer IPs.

+
+serviceExternalIPs
+ +[]string + +
+(Optional) +

ServiceExternalIPs are the CIDR blocks for Kubernetes Service External IPs.

+
+serviceClusterIPs
+ +[]string + +
+(Optional) +

ServiceClusterIPs are the CIDR blocks from which service cluster IPs are allocated.

+
+bgpPeer
+ + +[]BgpPeer + + +
+(Optional) +

BGPPeer contains configuration for BGPPeer resource.

+

CloudControllerManagerConfig

@@ -257,6 +393,20 @@ MetallbConfig

MetallbConfig contains configuration settings for metallb.

+ + +calicoBgpConfig
+ + +CalicoBgpConfig + + + + +(Optional) +

CalicoBgpConfig contains configuration settings for calico.

+ +

MachineImage diff --git a/pkg/apis/metal/types_controlplane.go b/pkg/apis/metal/types_controlplane.go index 66d8f83..bb21ed0 100644 --- a/pkg/apis/metal/types_controlplane.go +++ b/pkg/apis/metal/types_controlplane.go @@ -31,6 +31,9 @@ type CloudControllerManagerConfig struct { type LoadBalancerConfig struct { // MetallbConfig contains configuration settings for metallb. MetallbConfig *MetallbConfig + + // CalicoBgpConfig contains configuration settings for calico. + CalicoBgpConfig *CalicoBgpConfig } // MetallbConfig contains configuration settings for metallb. @@ -44,3 +47,33 @@ type MetallbConfig struct { // EnableL2Advertisement enables L2 advertisement. EnableL2Advertisement bool } + +// CalicoBgpConfig contains BGP configuration settings for calico. +type CalicoBgpConfig struct { + // ASNumber is the default AS number used by a node. + ASNumber int + + // ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes Service LoadBalancer IPs. + ServiceLoadBalancerIPs []string + + // ServiceExternalIPs are the CIDR blocks for Kubernetes Service External IPs. + ServiceExternalIPs []string + + // ServiceClusterIPs are the CIDR blocks from which service cluster IPs are allocated. + ServiceClusterIPs []string + + // BGPPeer contains configuration for BGPPeer resource. + BgpPeer []BgpPeer +} + +// BgpPeer contains configuration for BGPPeer resource. +type BgpPeer struct { + // PeerIP contains IP address of BGP peer followed by an optional port number to peer with. + PeerIP string + + // ASNumber contains the AS number of the BGP peer. + ASNumber int + + // NodeSelector is a key-value pair to select nodes that should have this peering. + NodeSelector string +} diff --git a/pkg/apis/metal/v1alpha1/types_controlplane.go b/pkg/apis/metal/v1alpha1/types_controlplane.go index f7d9c94..e46aa0e 100644 --- a/pkg/apis/metal/v1alpha1/types_controlplane.go +++ b/pkg/apis/metal/v1alpha1/types_controlplane.go @@ -35,6 +35,10 @@ type LoadBalancerConfig struct { // MetallbConfig contains configuration settings for metallb. // +optional MetallbConfig *MetallbConfig `json:"metallbConfig,omitempty"` + + // CalicoBgpConfig contains configuration settings for calico. + // +optional + CalicoBgpConfig *CalicoBgpConfig `json:"calicoBgpConfig,omitempty"` } // MetallbConfig contains configuration settings for metallb. @@ -51,3 +55,41 @@ type MetallbConfig struct { // +optional EnableL2Advertisement bool `json:"enableL2Advertisement,omitempty"` } + +// CalicoBgpConfig contains BGP configuration settings for calico. +type CalicoBgpConfig struct { + // ASNumber is the default AS number used by a node. + // +required + ASNumber int `json:"asNumber"` + + // ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes Service LoadBalancer IPs. + // +optional + ServiceLoadBalancerIPs []string `json:"serviceLoadBalancerIPs,omitempty"` + + // ServiceExternalIPs are the CIDR blocks for Kubernetes Service External IPs. + // +optional + ServiceExternalIPs []string `json:"serviceExternalIPs,omitempty"` + + // ServiceClusterIPs are the CIDR blocks from which service cluster IPs are allocated. + // +optional + ServiceClusterIPs []string `json:"serviceClusterIPs,omitempty"` + + // BGPPeer contains configuration for BGPPeer resource. + // +optional + BgpPeer []BgpPeer `json:"bgpPeer,omitempty"` +} + +// BgpPeer contains configuration for BGPPeer resource. +type BgpPeer struct { + // PeerIP contains IP address of BGP peer followed by an optional port number to peer with. + // +required + PeerIP string `json:"peerIP"` + + // ASNumber contains the AS number of the BGP peer. + // +required + ASNumber int `json:"asNumber"` + + // NodeSelector is a key-value pair to select nodes that should have this peering. + // +optional + NodeSelector string `json:"nodeSelector,omitempty"` +} diff --git a/pkg/apis/metal/v1alpha1/zz_generated.conversion.go b/pkg/apis/metal/v1alpha1/zz_generated.conversion.go index a3ea91c..f93c5a8 100644 --- a/pkg/apis/metal/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/metal/v1alpha1/zz_generated.conversion.go @@ -23,6 +23,26 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*BgpPeer)(nil), (*metal.BgpPeer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_BgpPeer_To_metal_BgpPeer(a.(*BgpPeer), b.(*metal.BgpPeer), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*metal.BgpPeer)(nil), (*BgpPeer)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_metal_BgpPeer_To_v1alpha1_BgpPeer(a.(*metal.BgpPeer), b.(*BgpPeer), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*CalicoBgpConfig)(nil), (*metal.CalicoBgpConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_CalicoBgpConfig_To_metal_CalicoBgpConfig(a.(*CalicoBgpConfig), b.(*metal.CalicoBgpConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*metal.CalicoBgpConfig)(nil), (*CalicoBgpConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_metal_CalicoBgpConfig_To_v1alpha1_CalicoBgpConfig(a.(*metal.CalicoBgpConfig), b.(*CalicoBgpConfig), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*CloudControllerManagerConfig)(nil), (*metal.CloudControllerManagerConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_CloudControllerManagerConfig_To_metal_CloudControllerManagerConfig(a.(*CloudControllerManagerConfig), b.(*metal.CloudControllerManagerConfig), scope) }); err != nil { @@ -156,6 +176,58 @@ func RegisterConversions(s *runtime.Scheme) error { return nil } +func autoConvert_v1alpha1_BgpPeer_To_metal_BgpPeer(in *BgpPeer, out *metal.BgpPeer, s conversion.Scope) error { + out.PeerIP = in.PeerIP + out.ASNumber = in.ASNumber + out.NodeSelector = in.NodeSelector + return nil +} + +// Convert_v1alpha1_BgpPeer_To_metal_BgpPeer is an autogenerated conversion function. +func Convert_v1alpha1_BgpPeer_To_metal_BgpPeer(in *BgpPeer, out *metal.BgpPeer, s conversion.Scope) error { + return autoConvert_v1alpha1_BgpPeer_To_metal_BgpPeer(in, out, s) +} + +func autoConvert_metal_BgpPeer_To_v1alpha1_BgpPeer(in *metal.BgpPeer, out *BgpPeer, s conversion.Scope) error { + out.PeerIP = in.PeerIP + out.ASNumber = in.ASNumber + out.NodeSelector = in.NodeSelector + return nil +} + +// Convert_metal_BgpPeer_To_v1alpha1_BgpPeer is an autogenerated conversion function. +func Convert_metal_BgpPeer_To_v1alpha1_BgpPeer(in *metal.BgpPeer, out *BgpPeer, s conversion.Scope) error { + return autoConvert_metal_BgpPeer_To_v1alpha1_BgpPeer(in, out, s) +} + +func autoConvert_v1alpha1_CalicoBgpConfig_To_metal_CalicoBgpConfig(in *CalicoBgpConfig, out *metal.CalicoBgpConfig, s conversion.Scope) error { + out.ASNumber = in.ASNumber + out.ServiceLoadBalancerIPs = *(*[]string)(unsafe.Pointer(&in.ServiceLoadBalancerIPs)) + out.ServiceExternalIPs = *(*[]string)(unsafe.Pointer(&in.ServiceExternalIPs)) + out.ServiceClusterIPs = *(*[]string)(unsafe.Pointer(&in.ServiceClusterIPs)) + out.BgpPeer = *(*[]metal.BgpPeer)(unsafe.Pointer(&in.BgpPeer)) + return nil +} + +// Convert_v1alpha1_CalicoBgpConfig_To_metal_CalicoBgpConfig is an autogenerated conversion function. +func Convert_v1alpha1_CalicoBgpConfig_To_metal_CalicoBgpConfig(in *CalicoBgpConfig, out *metal.CalicoBgpConfig, s conversion.Scope) error { + return autoConvert_v1alpha1_CalicoBgpConfig_To_metal_CalicoBgpConfig(in, out, s) +} + +func autoConvert_metal_CalicoBgpConfig_To_v1alpha1_CalicoBgpConfig(in *metal.CalicoBgpConfig, out *CalicoBgpConfig, s conversion.Scope) error { + out.ASNumber = in.ASNumber + out.ServiceLoadBalancerIPs = *(*[]string)(unsafe.Pointer(&in.ServiceLoadBalancerIPs)) + out.ServiceExternalIPs = *(*[]string)(unsafe.Pointer(&in.ServiceExternalIPs)) + out.ServiceClusterIPs = *(*[]string)(unsafe.Pointer(&in.ServiceClusterIPs)) + out.BgpPeer = *(*[]BgpPeer)(unsafe.Pointer(&in.BgpPeer)) + return nil +} + +// Convert_metal_CalicoBgpConfig_To_v1alpha1_CalicoBgpConfig is an autogenerated conversion function. +func Convert_metal_CalicoBgpConfig_To_v1alpha1_CalicoBgpConfig(in *metal.CalicoBgpConfig, out *CalicoBgpConfig, s conversion.Scope) error { + return autoConvert_metal_CalicoBgpConfig_To_v1alpha1_CalicoBgpConfig(in, out, s) +} + func autoConvert_v1alpha1_CloudControllerManagerConfig_To_metal_CloudControllerManagerConfig(in *CloudControllerManagerConfig, out *metal.CloudControllerManagerConfig, s conversion.Scope) error { out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) return nil @@ -260,6 +332,7 @@ func Convert_metal_InfrastructureStatus_To_v1alpha1_InfrastructureStatus(in *met func autoConvert_v1alpha1_LoadBalancerConfig_To_metal_LoadBalancerConfig(in *LoadBalancerConfig, out *metal.LoadBalancerConfig, s conversion.Scope) error { out.MetallbConfig = (*metal.MetallbConfig)(unsafe.Pointer(in.MetallbConfig)) + out.CalicoBgpConfig = (*metal.CalicoBgpConfig)(unsafe.Pointer(in.CalicoBgpConfig)) return nil } @@ -270,6 +343,7 @@ func Convert_v1alpha1_LoadBalancerConfig_To_metal_LoadBalancerConfig(in *LoadBal func autoConvert_metal_LoadBalancerConfig_To_v1alpha1_LoadBalancerConfig(in *metal.LoadBalancerConfig, out *LoadBalancerConfig, s conversion.Scope) error { out.MetallbConfig = (*MetallbConfig)(unsafe.Pointer(in.MetallbConfig)) + out.CalicoBgpConfig = (*CalicoBgpConfig)(unsafe.Pointer(in.CalicoBgpConfig)) return nil } diff --git a/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go index 3d2eb20..57500af 100644 --- a/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/metal/v1alpha1/zz_generated.deepcopy.go @@ -12,6 +12,58 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BgpPeer) DeepCopyInto(out *BgpPeer) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BgpPeer. +func (in *BgpPeer) DeepCopy() *BgpPeer { + if in == nil { + return nil + } + out := new(BgpPeer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CalicoBgpConfig) DeepCopyInto(out *CalicoBgpConfig) { + *out = *in + if in.ServiceLoadBalancerIPs != nil { + in, out := &in.ServiceLoadBalancerIPs, &out.ServiceLoadBalancerIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServiceExternalIPs != nil { + in, out := &in.ServiceExternalIPs, &out.ServiceExternalIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServiceClusterIPs != nil { + in, out := &in.ServiceClusterIPs, &out.ServiceClusterIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.BgpPeer != nil { + in, out := &in.BgpPeer, &out.BgpPeer + *out = make([]BgpPeer, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CalicoBgpConfig. +func (in *CalicoBgpConfig) DeepCopy() *CalicoBgpConfig { + if in == nil { + return nil + } + out := new(CalicoBgpConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CloudControllerManagerConfig) DeepCopyInto(out *CloudControllerManagerConfig) { *out = *in @@ -174,6 +226,11 @@ func (in *LoadBalancerConfig) DeepCopyInto(out *LoadBalancerConfig) { *out = new(MetallbConfig) (*in).DeepCopyInto(*out) } + if in.CalicoBgpConfig != nil { + in, out := &in.CalicoBgpConfig, &out.CalicoBgpConfig + *out = new(CalicoBgpConfig) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/apis/metal/zz_generated.deepcopy.go b/pkg/apis/metal/zz_generated.deepcopy.go index 0706256..6a7ddc1 100644 --- a/pkg/apis/metal/zz_generated.deepcopy.go +++ b/pkg/apis/metal/zz_generated.deepcopy.go @@ -12,6 +12,58 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BgpPeer) DeepCopyInto(out *BgpPeer) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BgpPeer. +func (in *BgpPeer) DeepCopy() *BgpPeer { + if in == nil { + return nil + } + out := new(BgpPeer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CalicoBgpConfig) DeepCopyInto(out *CalicoBgpConfig) { + *out = *in + if in.ServiceLoadBalancerIPs != nil { + in, out := &in.ServiceLoadBalancerIPs, &out.ServiceLoadBalancerIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServiceExternalIPs != nil { + in, out := &in.ServiceExternalIPs, &out.ServiceExternalIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServiceClusterIPs != nil { + in, out := &in.ServiceClusterIPs, &out.ServiceClusterIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.BgpPeer != nil { + in, out := &in.BgpPeer, &out.BgpPeer + *out = make([]BgpPeer, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CalicoBgpConfig. +func (in *CalicoBgpConfig) DeepCopy() *CalicoBgpConfig { + if in == nil { + return nil + } + out := new(CalicoBgpConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CloudControllerManagerConfig) DeepCopyInto(out *CloudControllerManagerConfig) { *out = *in @@ -174,6 +226,11 @@ func (in *LoadBalancerConfig) DeepCopyInto(out *LoadBalancerConfig) { *out = new(MetallbConfig) (*in).DeepCopyInto(*out) } + if in.CalicoBgpConfig != nil { + in, out := &in.CalicoBgpConfig, &out.CalicoBgpConfig + *out = new(CalicoBgpConfig) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/controller/controlplane/valuesprovider.go b/pkg/controller/controlplane/valuesprovider.go index a1d27bb..b8d54b0 100644 --- a/pkg/controller/controlplane/valuesprovider.go +++ b/pkg/controller/controlplane/valuesprovider.go @@ -342,13 +342,20 @@ func (vp *valuesProvider) getControlPlaneShootChartValues(cluster *extensionscon if err != nil { return nil, err } + + calicoBgp, err := getCalicoBgpChartValues(cp, cluster) + if err != nil { + return nil, err + } + return map[string]any{ metal.CloudControllerManagerName: map[string]any{"enabled": true}, metal.MetallbName: metallb, + metal.CalicoBgpName: calicoBgp, }, nil } -// getMetallbChartValues collects and returns the CCM chart values. +// getMetallbChartValues collects and returns the MetalLB chart values. func getMetallbChartValues( cpConfig *apismetal.ControlPlaneConfig, ) (map[string]any, error) { @@ -376,6 +383,70 @@ func getMetallbChartValues( }, nil } +// getCalicoBgpChartValues collects and returns the Calico BGP chart values. +func getCalicoBgpChartValues( + cpConfig *apismetal.ControlPlaneConfig, + cluster *extensionscontroller.Cluster, +) (map[string]any, error) { + if cpConfig.LoadBalancerConfig == nil || cpConfig.LoadBalancerConfig.CalicoBgpConfig == nil { + return map[string]any{ + "enabled": false, + }, nil + } + + var serviceLbIPs, serviceExtIPs, serviceClusterIPs []string + var peers []map[string]any + if cpConfig.LoadBalancerConfig.CalicoBgpConfig != nil && + *cluster.Shoot.Spec.Networking.Type == metal.ShootCalicoNetworkType { + if cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceLoadBalancerIPs != nil { + for _, cidr := range cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceLoadBalancerIPs { + if err := parseAddressPool(cidr); err != nil { + return nil, fmt.Errorf("invalid CIDR %q in pool: %w", cidr, err) + } + serviceLbIPs = append(serviceLbIPs, fmt.Sprintf("cidr: %s", cidr)) + } + } + + if cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceExternalIPs != nil { + for _, cidr := range cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceExternalIPs { + if err := parseAddressPool(cidr); err != nil { + return nil, fmt.Errorf("invalid CIDR %q in pool: %w", cidr, err) + } + serviceExtIPs = append(serviceExtIPs, fmt.Sprintf("cidr: %s", cidr)) + } + } + + if cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceClusterIPs != nil { + for _, cidr := range cpConfig.LoadBalancerConfig.CalicoBgpConfig.ServiceClusterIPs { + if err := parseAddressPool(cidr); err != nil { + return nil, fmt.Errorf("invalid CIDR %q in pool: %w", cidr, err) + } + serviceClusterIPs = append(serviceClusterIPs, fmt.Sprintf("cidr: %s", cidr)) + } + } + + if cpConfig.LoadBalancerConfig.CalicoBgpConfig.BgpPeer != nil { + for _, peer := range cpConfig.LoadBalancerConfig.CalicoBgpConfig.BgpPeer { + peers = append(peers, map[string]any{ + "peerIP": peer.PeerIP, + "asNumber": peer.ASNumber, + "nodeSelector": peer.NodeSelector, + }) + } + } + } + return map[string]any{ + "enabled": true, + "bgp": map[string]any{ + "asNumber": cpConfig.LoadBalancerConfig.CalicoBgpConfig.ASNumber, + "serviceLoadBalancerIPs": serviceLbIPs, + "serviceExternalIPs": serviceExtIPs, + "serviceClusterIPs": serviceClusterIPs, + "bgpPeer": peers, + }, + }, nil +} + func parseAddressPool(cidr string) error { if !strings.Contains(cidr, "-") { _, _, err := net.ParseCIDR(cidr) diff --git a/pkg/controller/controlplane/valuesprovider_test.go b/pkg/controller/controlplane/valuesprovider_test.go index 9935e77..990ab42 100644 --- a/pkg/controller/controlplane/valuesprovider_test.go +++ b/pkg/controller/controlplane/valuesprovider_test.go @@ -287,6 +287,9 @@ var _ = Describe("Valueprovider Reconcile", func() { "metallb": map[string]any{ "enabled": false, }, + "calico-bgp": map[string]any{ + "enabled": false, + }, })) }) }) @@ -379,6 +382,121 @@ var _ = Describe("Valueprovider Reconcile", func() { }, "ipAddressPool": []string{"10.10.10.0/24", "10.20.20.10-10.20.20.30"}, }, + "calico-bgp": map[string]any{ + "enabled": false, + }, + })) + }) + }) + + Describe("#GetControlPlaneShootChartValues", func() { + It("should return correct shoot system chart values with calico", func(ctx SpecContext) { + cp := &extensionsv1alpha1.ControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "control-plane", + Namespace: ns.Name, + }, + Spec: extensionsv1alpha1.ControlPlaneSpec{ + Region: "foo", + SecretRef: corev1.SecretReference{ + Name: "my-infra-creds", + Namespace: ns.Name, + }, + DefaultSpec: extensionsv1alpha1.DefaultSpec{ + Type: metal.Type, + ProviderConfig: &runtime.RawExtension{ + Raw: encode(&apismetal.ControlPlaneConfig{ + CloudControllerManager: &apismetal.CloudControllerManagerConfig{ + FeatureGates: map[string]bool{ + "CustomResourceValidation": true, + }, + }, + LoadBalancerConfig: &apismetal.LoadBalancerConfig{ + CalicoBgpConfig: &apismetal.CalicoBgpConfig{ + ASNumber: 12345, + ServiceLoadBalancerIPs: []string{"10.10.10.0/24", "10.20.20.10-10.20.20.30"}, + ServiceClusterIPs: []string{"10.10.10.0/24", "10.20.20.10-10.20.20.30"}, + ServiceExternalIPs: []string{"10.10.10.0/24", "10.20.20.10-10.20.20.30"}, + BgpPeer: []apismetal.BgpPeer{ + { + PeerIP: "1.2.3.4", + ASNumber: 12345, + NodeSelector: "foo=bar", + }, + }, + }, + }, + }), + }, + }, + }, + } + Expect(k8sClient.Create(ctx, cp)).To(Succeed()) + + providerCloudProfile := &apismetal.CloudProfileConfig{} + providerCloudProfileJson, err := json.Marshal(providerCloudProfile) + Expect(err).NotTo(HaveOccurred()) + networkProviderConfig := &unstructured.Unstructured{Object: map[string]any{ + "kind": "FooNetworkConfig", + "apiVersion": "v1alpha1", + "overlay": map[string]any{ + "enabled": false, + }, + }} + networkProviderConfigData, err := runtime.Encode(unstructured.UnstructuredJSONScheme, networkProviderConfig) + Expect(err).NotTo(HaveOccurred()) + cluster := &controller.Cluster{ + CloudProfile: &gardencorev1beta1.CloudProfile{ + Spec: gardencorev1beta1.CloudProfileSpec{ + ProviderConfig: &runtime.RawExtension{ + Raw: providerCloudProfileJson, + }, + }, + }, + Shoot: &gardencorev1beta1.Shoot{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + Name: "my-shoot", + }, + Spec: gardencorev1beta1.ShootSpec{ + Networking: &gardencorev1beta1.Networking{ + Type: ptr.To[string](metal.ShootCalicoNetworkType), + ProviderConfig: &runtime.RawExtension{Raw: networkProviderConfigData}, + Pods: ptr.To[string]("10.0.0.0/16"), + }, + Kubernetes: gardencorev1beta1.Kubernetes{ + Version: "1.26.0", + VerticalPodAutoscaler: &gardencorev1beta1.VerticalPodAutoscaler{ + Enabled: true, + }, + }, + }, + }, + } + + values, err := vp.GetControlPlaneShootChartValues(ctx, cp, cluster, fakeSecretsManager, nil) + Expect(err).NotTo(HaveOccurred()) + Expect(values).To(Equal(map[string]any{ + "cloud-controller-manager": map[string]any{"enabled": true}, + "metallb": map[string]any{ + "enabled": false, + }, + "calico-bgp": map[string]any{ + "enabled": true, + "bgp": map[string]any{ + "asNumber": 12345, + "serviceLoadBalancerIPs": []string{"cidr: 10.10.10.0/24", "cidr: 10.20.20.10-10.20.20.30"}, + "serviceExternalIPs": []string{"cidr: 10.10.10.0/24", "cidr: 10.20.20.10-10.20.20.30"}, + "serviceClusterIPs": []string{"cidr: 10.10.10.0/24", "cidr: 10.20.20.10-10.20.20.30"}, + "bgpPeer": []map[string]any{ + { + "peerIP": "1.2.3.4", + "asNumber": 12345, + "nodeSelector": "foo=bar", + }, + }, + }, + }, })) }) }) diff --git a/pkg/metal/types.go b/pkg/metal/types.go index 0bdfbb3..22fdc07 100644 --- a/pkg/metal/types.go +++ b/pkg/metal/types.go @@ -47,10 +47,14 @@ const ( CloudProviderConfigName = "cloud-provider-config" // CloudControllerManagerName is a constant for the name of the CloudController deployed by the worker controller. CloudControllerManagerName = "cloud-controller-manager" + // CalicoBgpName is a constant for the name of the Calico BGP deployed by the worker controller. + CalicoBgpName = "calico-bgp" // MetallbName is a constant for the name of the MetalLB deployed by the worker controller. MetallbName = "metallb" // MachineControllerManagerName is a constant for the name of the machine-controller-manager. MachineControllerManagerName = "machine-controller-manager" + // ShootCalicoNetworkType is the network type for calico in a shoot. + ShootCalicoNetworkType = "calico" // MachineControllerManagerVpaName is the name of the VerticalPodAutoscaler of the machine-controller-manager deployment. MachineControllerManagerVpaName = "machine-controller-manager-vpa" // MachineControllerManagerMonitoringConfigName is the name of the ConfigMap containing monitoring stack configurations for machine-controller-manager.