diff --git a/machineconfiguration/v1alpha1/register.go b/machineconfiguration/v1alpha1/register.go index e640a51ea22..64f90798650 100644 --- a/machineconfiguration/v1alpha1/register.go +++ b/machineconfiguration/v1alpha1/register.go @@ -28,6 +28,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OSImageStreamList{}, &InternalReleaseImage{}, &InternalReleaseImageList{}, + &BGPVIPConfig{}, + &BGPVIPConfigList{}, ) metav1.AddToGroupVersion(scheme, GroupVersion) return nil diff --git a/machineconfiguration/v1alpha1/tests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml b/machineconfiguration/v1alpha1/tests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml new file mode 100644 index 00000000000..6f45fd5851d --- /dev/null +++ b/machineconfiguration/v1alpha1/tests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml @@ -0,0 +1,802 @@ +apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this +name: "[TechPreview] BGPVIPConfig" +crdName: bgpvipconfigs.machineconfiguration.openshift.io +featureGate: BGPBasedVIPManagement +tests: + onCreate: + - name: Should be able to create a minimal BGPVIPConfig + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - name: Should reject a non-cluster name + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: not-cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "metadata.name must be 'cluster'" + - name: Should reject an invalid peer address + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: not-an-ip + peerASN: 64513 + expectedError: "peerAddress must be a valid IP address" + - name: Should reject an out-of-range ASN + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 4294967296 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "localASN" + - name: Should reject holdTime shorter than 3x keepalive + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 5 + keepaliveTimeSeconds: 5 + expectedError: "holdTimeSeconds must be at least 3 times keepaliveTimeSeconds" + - name: Should accept a dual-stack peer set with an IPv6 host override + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - peerAddress: fd2e:6f44:5dd8:c956::1 + peerASN: 64513 + hostOverrides: + - hostname: worker-0 + peers: + - peerAddress: fd2e:6f44:5dd8:c956::2 + peerASN: 64514 + bfd: Enabled + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - peerAddress: fd2e:6f44:5dd8:c956::1 + peerASN: 64513 + hostOverrides: + - hostname: worker-0 + peers: + - peerAddress: fd2e:6f44:5dd8:c956::2 + peerASN: 64514 + bfd: Enabled + - name: Should reject an invalid bfd mode + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + bfd: maybe + expectedError: "Unsupported value" + - name: Should reject an invalid community + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["banana"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "communities" + - name: Should reject a classic community segment above 65535 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["64512:65536"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "classic community (n:n) segments must be between 0 and 65535" + - name: Should reject a 32-bit value in a classic community + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["64512:4294967295"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "classic community (n:n) segments must be between 0 and 65535" + - name: Should accept a classic community at the 16-bit boundary + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["65535:65535"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["65535:65535"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - name: Should reject a large community segment above 4294967295 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["64512:100:4294967296"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "large community (n:n:n) segments must be between 0 and 4294967295" + - name: Should accept a large community at the 32-bit boundary + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["4294967295:4294967295:4294967295"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["4294967295:4294967295:4294967295"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - name: Should accept a peer with a passwordSecret reference + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + passwordSecret: + name: bgp-peer-tor + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + passwordSecret: + name: bgp-peer-tor + - name: Should reject a passwordSecret name that is not an RFC 1123 subdomain + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + passwordSecret: + name: "Not_Valid" + expectedError: "name must be an RFC 1123 subdomain with labels of at most 63 characters" + - name: Should reject localASN 0 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 0 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "spec.localASN" + - name: Should accept the ASN boundaries 1 and 4294967295 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 1 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 4294967295 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 1 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 4294967295 + - name: Should reject peerASN above 4294967295 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 4294967296 + expectedError: "peerASN" + - name: Should reject port 0 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + port: 0 + expectedError: "port" + - name: Should reject port above 65535 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + port: 65536 + expectedError: "port" + - name: Should accept the port boundaries 1 and 65535 + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + port: 1 + - peerAddress: 192.168.111.2 + peerASN: 64513 + port: 65535 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + port: 1 + - peerAddress: 192.168.111.2 + peerASN: 64513 + port: 65535 + - name: Should reject a hold time of 1 or 2 seconds + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 2 + expectedError: "holdTimeSeconds must be 0 or at least 3" + - name: Should accept hold time exactly 3x keepalive + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 15 + keepaliveTimeSeconds: 5 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 15 + keepaliveTimeSeconds: 5 + - name: Should accept explicit hold time 0 with a keepalive + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 0 + keepaliveTimeSeconds: 5 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 0 + keepaliveTimeSeconds: 5 + - name: Should accept a keepalive with an explicit zero hold time escape hatch reversed + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 9 + keepaliveTimeSeconds: 0 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + holdTimeSeconds: 9 + keepaliveTimeSeconds: 0 + - name: Should reject an empty defaultPeers list + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: [] + expectedError: "defaultPeers" + - name: Should reject duplicate peer addresses + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - peerAddress: 192.168.111.1 + peerASN: 64514 + expectedError: "Duplicate value" + - name: Should reject duplicate hostnames in hostOverrides + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + hostOverrides: + - hostname: worker-0 + peers: + - peerAddress: 192.168.1.1 + peerASN: 64513 + - hostname: worker-0 + peers: + - peerAddress: 192.168.1.2 + peerASN: 64513 + expectedError: "Duplicate value" + - name: Should reject an override with an empty peer list + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + hostOverrides: + - hostname: worker-0 + peers: [] + expectedError: "peers" + - name: Should reject a non-canonical IPv6 peer address + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: "fd00:0::1" + peerASN: 64513 + expectedError: "peerAddress must be a valid IP address in canonical form" + - name: Should reject an uppercase IPv6 peer address + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: "FD00::1" + peerASN: 64513 + expectedError: "peerAddress must be a valid IP address in canonical form" + - name: Should reject a community with leading zeros + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: + - "065535:1" + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "should match" + - name: Should accept zero-valued communities + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: + - "0:0" + - "0:0:0" + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: + - "0:0" + - "0:0:0" + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + - name: Should reject a single-segment community + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: + - "64512" + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "should match" + - name: Should reject more than 8 communities + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + communities: ["1:1", "1:2", "1:3", "1:4", "1:5", "1:6", "1:7", "1:8", "1:9"] + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "communities" + - name: Should reject an uppercase hostname + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + hostOverrides: + - hostname: Worker-0 + peers: + - peerAddress: 192.168.1.1 + peerASN: 64513 + expectedError: "hostname must be an RFC 1123 subdomain with labels of at most 63 characters" + - name: Should accept ebgpMultiHop Enabled + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + ebgpMultiHop: Enabled + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + ebgpMultiHop: Enabled + - name: Should reject an invalid ebgpMultiHop mode + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + ebgpMultiHop: sometimes + expectedError: "Unsupported value" + - name: Should reject an empty passwordSecret name + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + passwordSecret: + name: "" + expectedError: "name" + - name: Should reject a spec without localASN + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + expectedError: "spec.localASN: Required value" + - name: Should reject a hostname label longer than 63 characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + hostOverrides: + - hostname: llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.example.com + peers: + - peerAddress: 192.168.1.1 + peerASN: 64513 + expectedError: "hostname must be an RFC 1123 subdomain with labels of at most 63 characters" + - name: Should reject a passwordSecret name label longer than 63 characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + passwordSecret: + name: llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.example.com + expectedError: "name must be an RFC 1123 subdomain with labels of at most 63 characters" + onUpdate: + - name: Should allow day-2 edits to the peer set + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + updated: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.2 + peerASN: 64514 + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.2 + peerASN: 64514 + - name: Should be able to write status through the status subresource + initial: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + updated: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + status: + observedGeneration: 1 + conditions: + - type: Rendered + status: "True" + reason: RenderComplete + message: per-node peer configuration rendered + lastTransitionTime: "2026-01-01T00:00:00Z" + - type: SessionsConfigured + status: "True" + reason: SessionsRendered + message: FRR session configuration rendered + lastTransitionTime: "2026-01-01T00:00:00Z" + expected: | + apiVersion: machineconfiguration.openshift.io/v1alpha1 + kind: BGPVIPConfig + metadata: + name: cluster + spec: + localASN: 64512 + defaultPeers: + - peerAddress: 192.168.111.1 + peerASN: 64513 + status: + observedGeneration: 1 + conditions: + - type: Rendered + status: "True" + reason: RenderComplete + message: per-node peer configuration rendered + lastTransitionTime: "2026-01-01T00:00:00Z" + - type: SessionsConfigured + status: "True" + reason: SessionsRendered + message: FRR session configuration rendered + lastTransitionTime: "2026-01-01T00:00:00Z" diff --git a/machineconfiguration/v1alpha1/types_bgpvipconfig.go b/machineconfiguration/v1alpha1/types_bgpvipconfig.go new file mode 100644 index 00000000000..f6285ddda94 --- /dev/null +++ b/machineconfiguration/v1alpha1/types_bgpvipconfig.go @@ -0,0 +1,285 @@ +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=bgpvipconfigs,scope=Cluster +// +kubebuilder:subresource:status +// +kubebuilder:metadata:labels=openshift.io/operator-managed= +// +kubebuilder:validation:XValidation:rule="self.metadata.name == 'cluster'",message="bgpvipconfig is a singleton, .metadata.name must be 'cluster'" +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/2972 +// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01 +// +openshift:enable:FeatureGate=BGPBasedVIPManagement +// +openshift:compatibility-gen:level=4 + +// BGPVIPConfig carries the BGP peering configuration for BGP-based VIP +// management (enhancement openshift/enhancements#1982). It is a singleton +// named "cluster", generated by the installer from +// platform.baremetal.bgpVIPConfig in the install-config, and may be edited +// day-2 to reconfigure peering. +// +// Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. +type BGPVIPConfig struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // +required + metav1.ObjectMeta `json:"metadata,omitempty"` + + // spec is the desired BGP VIP peering configuration. + // +required + Spec BGPVIPConfigSpec `json:"spec,omitempty,omitzero"` + + // status reports the consumers' progress applying the configuration. + // +optional + Status BGPVIPConfigStatus `json:"status,omitempty,omitzero"` +} + +// BGPVIPConfigSpec describes the BGP peering used to advertise the API and +// Ingress VIPs. +type BGPVIPConfigSpec struct { + // localASN is the autonomous system number the cluster's FRR instances + // run under. Must be between 1 and 4294967295 (int64 because valid ASNs + // exceed int32 range). + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=4294967295 + // +required + LocalASN int64 `json:"localASN,omitempty"` + + // defaultPeers are the BGP peers every node establishes sessions with, + // unless the node is named in hostOverrides. Must contain between 1 and + // 16 peers, unique by peerAddress. + // +listType=map + // +listMapKey=peerAddress + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +required + DefaultPeers []BGPVIPPeer `json:"defaultPeers,omitempty"` + + // communities are BGP community strings attached to the VIP + // advertisements: "n:n" classic communities (RFC 1997) where each + // segment is a 16-bit value between 0 and 65535, or "n:n:n" large + // communities (RFC 8092) where each segment is a 32-bit value between + // 0 and 4294967295. When omitted, no communities are attached. Each + // entry must be colon-separated decimal numbers without leading zeros, + // between 3 and 32 characters long; when set, between 1 and 8 entries. + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:validation:items:MinLength=3 + // +kubebuilder:validation:items:MaxLength=32 + // +kubebuilder:validation:items:Pattern=`^(0|[1-9]\d*)(:(0|[1-9]\d*)){1,2}$` + // +kubebuilder:validation:items:XValidation:rule="self.split(':').size() == 2 ? self.split(':').all(s, s.size() <= 5 && int(s) <= 65535) : self.split(':').all(s, s.size() <= 10 && int(s) <= 4294967295)",message="classic community (n:n) segments must be between 0 and 65535; large community (n:n:n) segments must be between 0 and 4294967295" + // +optional + Communities []string `json:"communities,omitempty"` + + // hostOverrides replaces (does not merge with) defaultPeers for the + // named nodes. Only the per-node peer file rendered by the + // machine-config-operator consumes overrides; the cluster-wide session + // configuration rendered by the cluster-network-operator uses + // defaultPeers. When omitted, all nodes use defaultPeers; when set, + // between 1 and 256 entries, unique by hostname. + // +listType=map + // +listMapKey=hostname + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=256 + // +optional + HostOverrides []BGPVIPHostPeers `json:"hostOverrides,omitempty"` +} + +// BGPVIPHostPeers is a per-node replacement peer list. +type BGPVIPHostPeers struct { + // hostname of the node this override applies to, as a non-empty RFC + // 1123 subdomain of at most 253 characters with dot-separated labels of + // at most 63 characters each. It is compared verbatim against + // the hostname the node resolves for itself (as rendered into the + // per-node peer file), so a short name and its fully qualified form are + // distinct entries and only the exact match applies. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$')",message="hostname must be an RFC 1123 subdomain with labels of at most 63 characters" + // +required + Hostname string `json:"hostname,omitempty"` + + // peers replaces defaultPeers for this node. Must contain between 1 and + // 16 peers, unique by peerAddress. + // +listType=map + // +listMapKey=peerAddress + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +required + Peers []BGPVIPPeer `json:"peers,omitempty"` +} + +// BFDMode enables or disables BFD for a BGP session. +// +kubebuilder:validation:Enum:=Enabled;Disabled +type BFDMode string + +const ( + // BFDModeEnabled backs the session with BFD fast failure detection. + BFDModeEnabled BFDMode = "Enabled" + // BFDModeDisabled runs the session without BFD. + BFDModeDisabled BFDMode = "Disabled" +) + +// EBGPMultiHopMode enables or disables eBGP multihop for a BGP session. +// +kubebuilder:validation:Enum:=Enabled;Disabled +type EBGPMultiHopMode string + +const ( + // EBGPMultiHopModeEnabled allows the session to cross multiple hops. + EBGPMultiHopModeEnabled EBGPMultiHopMode = "Enabled" + // EBGPMultiHopModeDisabled requires the peer to be directly connected. + EBGPMultiHopModeDisabled EBGPMultiHopMode = "Disabled" +) + +// BGPVIPPasswordSecret references a Secret in the openshift-config +// namespace by name. +type BGPVIPPasswordSecret struct { + // name is the metadata.name of the referenced Secret in the + // openshift-config namespace. Must be a non-empty RFC 1123 subdomain of + // at most 253 characters with dot-separated labels of at most 63 + // characters each. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$')",message="name must be an RFC 1123 subdomain with labels of at most 63 characters" + // +required + Name string `json:"name,omitempty"` +} + +// BGPVIPPeer describes one BGP peer. +// +kubebuilder:validation:XValidation:rule="!(has(self.holdTimeSeconds) && has(self.keepaliveTimeSeconds)) || self.holdTimeSeconds == 0 || self.keepaliveTimeSeconds == 0 || self.holdTimeSeconds >= 3 * self.keepaliveTimeSeconds",message="holdTimeSeconds must be at least 3 times keepaliveTimeSeconds" +type BGPVIPPeer struct { + // peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in + // canonical form (lowercase, no leading zeros, IPv6 zero-compressed), + // between 2 and 45 characters; the session's address family follows the + // address family of this value. Canonical form is required so that two + // spellings of one address cannot form duplicate peers. + // +kubebuilder:validation:MinLength=2 + // +kubebuilder:validation:MaxLength=45 + // +kubebuilder:validation:XValidation:rule="isIP(self) && ip.isCanonical(self)",message="peerAddress must be a valid IP address in canonical form" + // +required + PeerAddress string `json:"peerAddress,omitempty"` + + // peerASN is the autonomous system number of the peer. Must be + // between 1 and 4294967295. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=4294967295 + // +required + PeerASN int64 `json:"peerASN,omitempty"` + + // passwordSecret references the Secret carrying the TCP MD5 password + // (RFC 2385) for the session. The Secret must be of type + // kubernetes.io/basic-auth, live in the openshift-config namespace, and + // carry the password in its "password" key (at most 80 bytes, the + // kernel's TCP MD5 limit). The Secret type, key, and size requirements + // are not validated by the API server; the consumers validate them when + // resolving the reference and must never surface the Secret contents in + // status, events, or logs. Passwords are never stored in this API. When + // omitted, the session is unauthenticated. + // +optional + PasswordSecret BGPVIPPasswordSecret `json:"passwordSecret,omitempty,omitzero"` + + // port is the TCP port of the BGP session, between 1 and 65535. When + // omitted, port 179 is used; this default is applied by the consumers + // and is subject to change over time. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +optional + Port int32 `json:"port,omitempty"` + + // bfd determines whether the session is backed by BFD fast failure + // detection. When set to "Enabled", a BFD session is established with + // the peer and BGP reacts to BFD failure detection. When set to + // "Disabled", failure detection relies on the BGP hold timer alone. + // When omitted, BFD is disabled; this default is subject to change over + // time. + // +optional + BFD BFDMode `json:"bfd,omitempty"` + + // ebgpMultiHop determines whether the session may cross multiple hops. + // When set to "Enabled", the session may be established with a peer + // several router hops away. When set to "Disabled", the peer must be + // directly connected. When omitted, multihop is disabled; this default + // is subject to change over time. + // +optional + EBGPMultiHop EBGPMultiHopMode `json:"ebgpMultiHop,omitempty"` + + // holdTimeSeconds is the BGP hold time in seconds, either 0 or between + // 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 + // seconds). When omitted or 0, the FRR default is used; this is subject + // to change over time. When both holdTimeSeconds and + // keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + // least 3 times keepaliveTimeSeconds. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:validation:XValidation:rule="self == 0 || self >= 3",message="holdTimeSeconds must be 0 or at least 3" + // +optional + HoldTimeSeconds *int32 `json:"holdTimeSeconds,omitempty"` + + // keepaliveTimeSeconds is the BGP keepalive interval in seconds, + // between 0 and 65535. When omitted or 0, the FRR default is used; this + // is subject to change over time. When both holdTimeSeconds and + // keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + // least 3 times keepaliveTimeSeconds. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + // +optional + KeepaliveTimeSeconds *int32 `json:"keepaliveTimeSeconds,omitempty"` +} + +// BGPVIPConfigStatus reports the consumers' progress applying the spec. +// +kubebuilder:validation:MinProperties=1 +type BGPVIPConfigStatus struct { + // conditions reports the state of processing the configuration; when + // set, between 1 and 8 entries. Known + // condition types are "Rendered" (the machine-config-operator has + // rendered the per-node peer configuration) and "SessionsConfigured" + // (the cluster-network-operator has rendered the FRR session + // configuration for application). SessionsConfigured does not assert + // that the generated FRRConfiguration was accepted by the frr-k8s + // admission webhook or applied on the nodes. + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // observedGeneration is the generation most recently processed by the + // machine-config-operator, at least 1 when set. The + // cluster-network-operator's progress is reported by the + // observedGeneration of the "SessionsConfigured" condition instead; it + // does not write this field. + // +kubebuilder:validation:Minimum=1 + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` +} + +const ( + // BGPVIPConfigRendered is set by the machine-config-operator when the + // per-node peer configuration reflecting the current spec generation + // has been rendered. + BGPVIPConfigRendered = "Rendered" + // BGPVIPConfigSessionsConfigured is set by the cluster-network-operator + // when the FRR session configuration reflecting the current spec has + // been rendered for application. It does not assert admission-webhook + // acceptance or on-node application of the generated FRRConfiguration. + BGPVIPConfigSessionsConfigured = "SessionsConfigured" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +openshift:compatibility-gen:level=4 + +// BGPVIPConfigList is a list of BGPVIPConfig resources. +// +// Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. +type BGPVIPConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []BGPVIPConfig `json:"items"` +} diff --git a/machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_bgpvipconfigs.crd.yaml b/machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_bgpvipconfigs.crd.yaml new file mode 100644 index 00000000000..a3d1ef5cdb6 --- /dev/null +++ b/machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_bgpvipconfigs.crd.yaml @@ -0,0 +1,484 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2972 + api.openshift.io/merged-by-featuregates: "true" + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + release.openshift.io/feature-set: CustomNoUpgrade,DevPreviewNoUpgrade + labels: + openshift.io/operator-managed: "" + name: bgpvipconfigs.machineconfiguration.openshift.io +spec: + group: machineconfiguration.openshift.io + names: + kind: BGPVIPConfig + listKind: BGPVIPConfigList + plural: bgpvipconfigs + singular: bgpvipconfig + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + BGPVIPConfig carries the BGP peering configuration for BGP-based VIP + management (enhancement openshift/enhancements#1982). It is a singleton + named "cluster", generated by the installer from + platform.baremetal.bgpVIPConfig in the install-config, and may be edited + day-2 to reconfigure peering. + + Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec is the desired BGP VIP peering configuration. + properties: + communities: + description: |- + communities are BGP community strings attached to the VIP + advertisements: "n:n" classic communities (RFC 1997) where each + segment is a 16-bit value between 0 and 65535, or "n:n:n" large + communities (RFC 8092) where each segment is a 32-bit value between + 0 and 4294967295. When omitted, no communities are attached. Each + entry must be colon-separated decimal numbers without leading zeros, + between 3 and 32 characters long; when set, between 1 and 8 entries. + items: + maxLength: 32 + minLength: 3 + pattern: ^(0|[1-9]\d*)(:(0|[1-9]\d*)){1,2}$ + type: string + x-kubernetes-validations: + - message: classic community (n:n) segments must be between 0 and + 65535; large community (n:n:n) segments must be between 0 and + 4294967295 + rule: 'self.split('':'').size() == 2 ? self.split('':'').all(s, + s.size() <= 5 && int(s) <= 65535) : self.split('':'').all(s, + s.size() <= 10 && int(s) <= 4294967295)' + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + defaultPeers: + description: |- + defaultPeers are the BGP peers every node establishes sessions with, + unless the node is named in hostOverrides. Must contain between 1 and + 16 peers, unique by peerAddress. + items: + description: BGPVIPPeer describes one BGP peer. + properties: + bfd: + description: |- + bfd determines whether the session is backed by BFD fast failure + detection. When set to "Enabled", a BFD session is established with + the peer and BGP reacts to BFD failure detection. When set to + "Disabled", failure detection relies on the BGP hold timer alone. + When omitted, BFD is disabled; this default is subject to change over + time. + enum: + - Enabled + - Disabled + type: string + ebgpMultiHop: + description: |- + ebgpMultiHop determines whether the session may cross multiple hops. + When set to "Enabled", the session may be established with a peer + several router hops away. When set to "Disabled", the peer must be + directly connected. When omitted, multihop is disabled; this default + is subject to change over time. + enum: + - Enabled + - Disabled + type: string + holdTimeSeconds: + description: |- + holdTimeSeconds is the BGP hold time in seconds, either 0 or between + 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 + seconds). When omitted or 0, the FRR default is used; this is subject + to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + x-kubernetes-validations: + - message: holdTimeSeconds must be 0 or at least 3 + rule: self == 0 || self >= 3 + keepaliveTimeSeconds: + description: |- + keepaliveTimeSeconds is the BGP keepalive interval in seconds, + between 0 and 65535. When omitted or 0, the FRR default is used; this + is subject to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + passwordSecret: + description: |- + passwordSecret references the Secret carrying the TCP MD5 password + (RFC 2385) for the session. The Secret must be of type + kubernetes.io/basic-auth, live in the openshift-config namespace, and + carry the password in its "password" key (at most 80 bytes, the + kernel's TCP MD5 limit). The Secret type, key, and size requirements + are not validated by the API server; the consumers validate them when + resolving the reference and must never surface the Secret contents in + status, events, or logs. Passwords are never stored in this API. When + omitted, the session is unauthenticated. + properties: + name: + description: |- + name is the metadata.name of the referenced Secret in the + openshift-config namespace. Must be a non-empty RFC 1123 subdomain of + at most 253 characters with dot-separated labels of at most 63 + characters each. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: name must be an RFC 1123 subdomain with labels + of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + required: + - name + type: object + peerASN: + description: |- + peerASN is the autonomous system number of the peer. Must be + between 1 and 4294967295. + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + peerAddress: + description: |- + peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in + canonical form (lowercase, no leading zeros, IPv6 zero-compressed), + between 2 and 45 characters; the session's address family follows the + address family of this value. Canonical form is required so that two + spellings of one address cannot form duplicate peers. + maxLength: 45 + minLength: 2 + type: string + x-kubernetes-validations: + - message: peerAddress must be a valid IP address in canonical + form + rule: isIP(self) && ip.isCanonical(self) + port: + description: |- + port is the TCP port of the BGP session, between 1 and 65535. When + omitted, port 179 is used; this default is applied by the consumers + and is subject to change over time. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - peerASN + - peerAddress + type: object + x-kubernetes-validations: + - message: holdTimeSeconds must be at least 3 times keepaliveTimeSeconds + rule: '!(has(self.holdTimeSeconds) && has(self.keepaliveTimeSeconds)) + || self.holdTimeSeconds == 0 || self.keepaliveTimeSeconds == + 0 || self.holdTimeSeconds >= 3 * self.keepaliveTimeSeconds' + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - peerAddress + x-kubernetes-list-type: map + hostOverrides: + description: |- + hostOverrides replaces (does not merge with) defaultPeers for the + named nodes. Only the per-node peer file rendered by the + machine-config-operator consumes overrides; the cluster-wide session + configuration rendered by the cluster-network-operator uses + defaultPeers. When omitted, all nodes use defaultPeers; when set, + between 1 and 256 entries, unique by hostname. + items: + description: BGPVIPHostPeers is a per-node replacement peer list. + properties: + hostname: + description: |- + hostname of the node this override applies to, as a non-empty RFC + 1123 subdomain of at most 253 characters with dot-separated labels of + at most 63 characters each. It is compared verbatim against + the hostname the node resolves for itself (as rendered into the + per-node peer file), so a short name and its fully qualified form are + distinct entries and only the exact match applies. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: hostname must be an RFC 1123 subdomain with labels + of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + peers: + description: |- + peers replaces defaultPeers for this node. Must contain between 1 and + 16 peers, unique by peerAddress. + items: + description: BGPVIPPeer describes one BGP peer. + properties: + bfd: + description: |- + bfd determines whether the session is backed by BFD fast failure + detection. When set to "Enabled", a BFD session is established with + the peer and BGP reacts to BFD failure detection. When set to + "Disabled", failure detection relies on the BGP hold timer alone. + When omitted, BFD is disabled; this default is subject to change over + time. + enum: + - Enabled + - Disabled + type: string + ebgpMultiHop: + description: |- + ebgpMultiHop determines whether the session may cross multiple hops. + When set to "Enabled", the session may be established with a peer + several router hops away. When set to "Disabled", the peer must be + directly connected. When omitted, multihop is disabled; this default + is subject to change over time. + enum: + - Enabled + - Disabled + type: string + holdTimeSeconds: + description: |- + holdTimeSeconds is the BGP hold time in seconds, either 0 or between + 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 + seconds). When omitted or 0, the FRR default is used; this is subject + to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + x-kubernetes-validations: + - message: holdTimeSeconds must be 0 or at least 3 + rule: self == 0 || self >= 3 + keepaliveTimeSeconds: + description: |- + keepaliveTimeSeconds is the BGP keepalive interval in seconds, + between 0 and 65535. When omitted or 0, the FRR default is used; this + is subject to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + passwordSecret: + description: |- + passwordSecret references the Secret carrying the TCP MD5 password + (RFC 2385) for the session. The Secret must be of type + kubernetes.io/basic-auth, live in the openshift-config namespace, and + carry the password in its "password" key (at most 80 bytes, the + kernel's TCP MD5 limit). The Secret type, key, and size requirements + are not validated by the API server; the consumers validate them when + resolving the reference and must never surface the Secret contents in + status, events, or logs. Passwords are never stored in this API. When + omitted, the session is unauthenticated. + properties: + name: + description: |- + name is the metadata.name of the referenced Secret in the + openshift-config namespace. Must be a non-empty RFC 1123 subdomain of + at most 253 characters with dot-separated labels of at most 63 + characters each. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: name must be an RFC 1123 subdomain with + labels of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + required: + - name + type: object + peerASN: + description: |- + peerASN is the autonomous system number of the peer. Must be + between 1 and 4294967295. + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + peerAddress: + description: |- + peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in + canonical form (lowercase, no leading zeros, IPv6 zero-compressed), + between 2 and 45 characters; the session's address family follows the + address family of this value. Canonical form is required so that two + spellings of one address cannot form duplicate peers. + maxLength: 45 + minLength: 2 + type: string + x-kubernetes-validations: + - message: peerAddress must be a valid IP address in canonical + form + rule: isIP(self) && ip.isCanonical(self) + port: + description: |- + port is the TCP port of the BGP session, between 1 and 65535. When + omitted, port 179 is used; this default is applied by the consumers + and is subject to change over time. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - peerASN + - peerAddress + type: object + x-kubernetes-validations: + - message: holdTimeSeconds must be at least 3 times keepaliveTimeSeconds + rule: '!(has(self.holdTimeSeconds) && has(self.keepaliveTimeSeconds)) + || self.holdTimeSeconds == 0 || self.keepaliveTimeSeconds + == 0 || self.holdTimeSeconds >= 3 * self.keepaliveTimeSeconds' + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - peerAddress + x-kubernetes-list-type: map + required: + - hostname + - peers + type: object + maxItems: 256 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - hostname + x-kubernetes-list-type: map + localASN: + description: |- + localASN is the autonomous system number the cluster's FRR instances + run under. Must be between 1 and 4294967295 (int64 because valid ASNs + exceed int32 range). + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + required: + - defaultPeers + - localASN + type: object + status: + description: status reports the consumers' progress applying the configuration. + minProperties: 1 + properties: + conditions: + description: |- + conditions reports the state of processing the configuration; when + set, between 1 and 8 entries. Known + condition types are "Rendered" (the machine-config-operator has + rendered the per-node peer configuration) and "SessionsConfigured" + (the cluster-network-operator has rendered the FRR session + configuration for application). SessionsConfigured does not assert + that the generated FRRConfiguration was accepted by the frr-k8s + admission webhook or applied on the nodes. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + observedGeneration: + description: |- + observedGeneration is the generation most recently processed by the + machine-config-operator, at least 1 when set. The + cluster-network-operator's progress is reported by the + observedGeneration of the "SessionsConfigured" condition instead; it + does not write this field. + format: int64 + minimum: 1 + type: integer + type: object + required: + - metadata + - spec + type: object + x-kubernetes-validations: + - message: bgpvipconfig is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/machineconfiguration/v1alpha1/zz_generated.deepcopy.go b/machineconfiguration/v1alpha1/zz_generated.deepcopy.go index 72d1d4b32d4..a5ac20bbc7e 100644 --- a/machineconfiguration/v1alpha1/zz_generated.deepcopy.go +++ b/machineconfiguration/v1alpha1/zz_generated.deepcopy.go @@ -10,6 +10,191 @@ 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 *BGPVIPConfig) DeepCopyInto(out *BGPVIPConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPConfig. +func (in *BGPVIPConfig) DeepCopy() *BGPVIPConfig { + if in == nil { + return nil + } + out := new(BGPVIPConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BGPVIPConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPConfigList) DeepCopyInto(out *BGPVIPConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BGPVIPConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPConfigList. +func (in *BGPVIPConfigList) DeepCopy() *BGPVIPConfigList { + if in == nil { + return nil + } + out := new(BGPVIPConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BGPVIPConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPConfigSpec) DeepCopyInto(out *BGPVIPConfigSpec) { + *out = *in + if in.DefaultPeers != nil { + in, out := &in.DefaultPeers, &out.DefaultPeers + *out = make([]BGPVIPPeer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Communities != nil { + in, out := &in.Communities, &out.Communities + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.HostOverrides != nil { + in, out := &in.HostOverrides, &out.HostOverrides + *out = make([]BGPVIPHostPeers, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPConfigSpec. +func (in *BGPVIPConfigSpec) DeepCopy() *BGPVIPConfigSpec { + if in == nil { + return nil + } + out := new(BGPVIPConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPConfigStatus) DeepCopyInto(out *BGPVIPConfigStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPConfigStatus. +func (in *BGPVIPConfigStatus) DeepCopy() *BGPVIPConfigStatus { + if in == nil { + return nil + } + out := new(BGPVIPConfigStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPHostPeers) DeepCopyInto(out *BGPVIPHostPeers) { + *out = *in + if in.Peers != nil { + in, out := &in.Peers, &out.Peers + *out = make([]BGPVIPPeer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPHostPeers. +func (in *BGPVIPHostPeers) DeepCopy() *BGPVIPHostPeers { + if in == nil { + return nil + } + out := new(BGPVIPHostPeers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPPasswordSecret) DeepCopyInto(out *BGPVIPPasswordSecret) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPPasswordSecret. +func (in *BGPVIPPasswordSecret) DeepCopy() *BGPVIPPasswordSecret { + if in == nil { + return nil + } + out := new(BGPVIPPasswordSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPVIPPeer) DeepCopyInto(out *BGPVIPPeer) { + *out = *in + out.PasswordSecret = in.PasswordSecret + if in.HoldTimeSeconds != nil { + in, out := &in.HoldTimeSeconds, &out.HoldTimeSeconds + *out = new(int32) + **out = **in + } + if in.KeepaliveTimeSeconds != nil { + in, out := &in.KeepaliveTimeSeconds, &out.KeepaliveTimeSeconds + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPVIPPeer. +func (in *BGPVIPPeer) DeepCopy() *BGPVIPPeer { + if in == nil { + return nil + } + out := new(BGPVIPPeer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InternalReleaseImage) DeepCopyInto(out *InternalReleaseImage) { *out = *in diff --git a/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests.yaml b/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests.yaml index 57d3ff72ed2..a248e8805e1 100644 --- a/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests.yaml +++ b/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests.yaml @@ -1,3 +1,27 @@ +bgpvipconfigs.machineconfiguration.openshift.io: + Annotations: {} + ApprovedPRNumber: https://github.com/openshift/api/pull/2972 + CRDName: bgpvipconfigs.machineconfiguration.openshift.io + Capability: "" + Category: "" + FeatureGates: + - BGPBasedVIPManagement + FilenameOperatorName: machine-config + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_80" + GroupName: machineconfiguration.openshift.io + HasStatus: true + KindName: BGPVIPConfig + Labels: + openshift.io/operator-managed: "" + PluralName: bgpvipconfigs + PrinterColumns: [] + Scope: Cluster + ShortNames: null + TopLevelFeatureGates: + - BGPBasedVIPManagement + Version: v1alpha1 + internalreleaseimages.machineconfiguration.openshift.io: Annotations: {} ApprovedPRNumber: https://github.com/openshift/api/pull/2510 diff --git a/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml b/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml new file mode 100644 index 00000000000..7fdb70f5e51 --- /dev/null +++ b/machineconfiguration/v1alpha1/zz_generated.featuregated-crd-manifests/bgpvipconfigs.machineconfiguration.openshift.io/BGPBasedVIPManagement.yaml @@ -0,0 +1,484 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2972 + api.openshift.io/filename-cvo-runlevel: "0000_80" + api.openshift.io/filename-operator: machine-config + api.openshift.io/filename-ordering: "01" + feature-gate.release.openshift.io/BGPBasedVIPManagement: "true" + labels: + openshift.io/operator-managed: "" + name: bgpvipconfigs.machineconfiguration.openshift.io +spec: + group: machineconfiguration.openshift.io + names: + kind: BGPVIPConfig + listKind: BGPVIPConfigList + plural: bgpvipconfigs + singular: bgpvipconfig + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + BGPVIPConfig carries the BGP peering configuration for BGP-based VIP + management (enhancement openshift/enhancements#1982). It is a singleton + named "cluster", generated by the installer from + platform.baremetal.bgpVIPConfig in the install-config, and may be edited + day-2 to reconfigure peering. + + Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec is the desired BGP VIP peering configuration. + properties: + communities: + description: |- + communities are BGP community strings attached to the VIP + advertisements: "n:n" classic communities (RFC 1997) where each + segment is a 16-bit value between 0 and 65535, or "n:n:n" large + communities (RFC 8092) where each segment is a 32-bit value between + 0 and 4294967295. When omitted, no communities are attached. Each + entry must be colon-separated decimal numbers without leading zeros, + between 3 and 32 characters long; when set, between 1 and 8 entries. + items: + maxLength: 32 + minLength: 3 + pattern: ^(0|[1-9]\d*)(:(0|[1-9]\d*)){1,2}$ + type: string + x-kubernetes-validations: + - message: classic community (n:n) segments must be between 0 and + 65535; large community (n:n:n) segments must be between 0 and + 4294967295 + rule: 'self.split('':'').size() == 2 ? self.split('':'').all(s, + s.size() <= 5 && int(s) <= 65535) : self.split('':'').all(s, + s.size() <= 10 && int(s) <= 4294967295)' + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + defaultPeers: + description: |- + defaultPeers are the BGP peers every node establishes sessions with, + unless the node is named in hostOverrides. Must contain between 1 and + 16 peers, unique by peerAddress. + items: + description: BGPVIPPeer describes one BGP peer. + properties: + bfd: + description: |- + bfd determines whether the session is backed by BFD fast failure + detection. When set to "Enabled", a BFD session is established with + the peer and BGP reacts to BFD failure detection. When set to + "Disabled", failure detection relies on the BGP hold timer alone. + When omitted, BFD is disabled; this default is subject to change over + time. + enum: + - Enabled + - Disabled + type: string + ebgpMultiHop: + description: |- + ebgpMultiHop determines whether the session may cross multiple hops. + When set to "Enabled", the session may be established with a peer + several router hops away. When set to "Disabled", the peer must be + directly connected. When omitted, multihop is disabled; this default + is subject to change over time. + enum: + - Enabled + - Disabled + type: string + holdTimeSeconds: + description: |- + holdTimeSeconds is the BGP hold time in seconds, either 0 or between + 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 + seconds). When omitted or 0, the FRR default is used; this is subject + to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + x-kubernetes-validations: + - message: holdTimeSeconds must be 0 or at least 3 + rule: self == 0 || self >= 3 + keepaliveTimeSeconds: + description: |- + keepaliveTimeSeconds is the BGP keepalive interval in seconds, + between 0 and 65535. When omitted or 0, the FRR default is used; this + is subject to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + passwordSecret: + description: |- + passwordSecret references the Secret carrying the TCP MD5 password + (RFC 2385) for the session. The Secret must be of type + kubernetes.io/basic-auth, live in the openshift-config namespace, and + carry the password in its "password" key (at most 80 bytes, the + kernel's TCP MD5 limit). The Secret type, key, and size requirements + are not validated by the API server; the consumers validate them when + resolving the reference and must never surface the Secret contents in + status, events, or logs. Passwords are never stored in this API. When + omitted, the session is unauthenticated. + properties: + name: + description: |- + name is the metadata.name of the referenced Secret in the + openshift-config namespace. Must be a non-empty RFC 1123 subdomain of + at most 253 characters with dot-separated labels of at most 63 + characters each. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: name must be an RFC 1123 subdomain with labels + of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + required: + - name + type: object + peerASN: + description: |- + peerASN is the autonomous system number of the peer. Must be + between 1 and 4294967295. + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + peerAddress: + description: |- + peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in + canonical form (lowercase, no leading zeros, IPv6 zero-compressed), + between 2 and 45 characters; the session's address family follows the + address family of this value. Canonical form is required so that two + spellings of one address cannot form duplicate peers. + maxLength: 45 + minLength: 2 + type: string + x-kubernetes-validations: + - message: peerAddress must be a valid IP address in canonical + form + rule: isIP(self) && ip.isCanonical(self) + port: + description: |- + port is the TCP port of the BGP session, between 1 and 65535. When + omitted, port 179 is used; this default is applied by the consumers + and is subject to change over time. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - peerASN + - peerAddress + type: object + x-kubernetes-validations: + - message: holdTimeSeconds must be at least 3 times keepaliveTimeSeconds + rule: '!(has(self.holdTimeSeconds) && has(self.keepaliveTimeSeconds)) + || self.holdTimeSeconds == 0 || self.keepaliveTimeSeconds == + 0 || self.holdTimeSeconds >= 3 * self.keepaliveTimeSeconds' + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - peerAddress + x-kubernetes-list-type: map + hostOverrides: + description: |- + hostOverrides replaces (does not merge with) defaultPeers for the + named nodes. Only the per-node peer file rendered by the + machine-config-operator consumes overrides; the cluster-wide session + configuration rendered by the cluster-network-operator uses + defaultPeers. When omitted, all nodes use defaultPeers; when set, + between 1 and 256 entries, unique by hostname. + items: + description: BGPVIPHostPeers is a per-node replacement peer list. + properties: + hostname: + description: |- + hostname of the node this override applies to, as a non-empty RFC + 1123 subdomain of at most 253 characters with dot-separated labels of + at most 63 characters each. It is compared verbatim against + the hostname the node resolves for itself (as rendered into the + per-node peer file), so a short name and its fully qualified form are + distinct entries and only the exact match applies. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: hostname must be an RFC 1123 subdomain with labels + of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + peers: + description: |- + peers replaces defaultPeers for this node. Must contain between 1 and + 16 peers, unique by peerAddress. + items: + description: BGPVIPPeer describes one BGP peer. + properties: + bfd: + description: |- + bfd determines whether the session is backed by BFD fast failure + detection. When set to "Enabled", a BFD session is established with + the peer and BGP reacts to BFD failure detection. When set to + "Disabled", failure detection relies on the BGP hold timer alone. + When omitted, BFD is disabled; this default is subject to change over + time. + enum: + - Enabled + - Disabled + type: string + ebgpMultiHop: + description: |- + ebgpMultiHop determines whether the session may cross multiple hops. + When set to "Enabled", the session may be established with a peer + several router hops away. When set to "Disabled", the peer must be + directly connected. When omitted, multihop is disabled; this default + is subject to change over time. + enum: + - Enabled + - Disabled + type: string + holdTimeSeconds: + description: |- + holdTimeSeconds is the BGP hold time in seconds, either 0 or between + 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 + seconds). When omitted or 0, the FRR default is used; this is subject + to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + x-kubernetes-validations: + - message: holdTimeSeconds must be 0 or at least 3 + rule: self == 0 || self >= 3 + keepaliveTimeSeconds: + description: |- + keepaliveTimeSeconds is the BGP keepalive interval in seconds, + between 0 and 65535. When omitted or 0, the FRR default is used; this + is subject to change over time. When both holdTimeSeconds and + keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at + least 3 times keepaliveTimeSeconds. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + passwordSecret: + description: |- + passwordSecret references the Secret carrying the TCP MD5 password + (RFC 2385) for the session. The Secret must be of type + kubernetes.io/basic-auth, live in the openshift-config namespace, and + carry the password in its "password" key (at most 80 bytes, the + kernel's TCP MD5 limit). The Secret type, key, and size requirements + are not validated by the API server; the consumers validate them when + resolving the reference and must never surface the Secret contents in + status, events, or logs. Passwords are never stored in this API. When + omitted, the session is unauthenticated. + properties: + name: + description: |- + name is the metadata.name of the referenced Secret in the + openshift-config namespace. Must be a non-empty RFC 1123 subdomain of + at most 253 characters with dot-separated labels of at most 63 + characters each. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: name must be an RFC 1123 subdomain with + labels of at most 63 characters + rule: self.matches('^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$') + required: + - name + type: object + peerASN: + description: |- + peerASN is the autonomous system number of the peer. Must be + between 1 and 4294967295. + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + peerAddress: + description: |- + peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in + canonical form (lowercase, no leading zeros, IPv6 zero-compressed), + between 2 and 45 characters; the session's address family follows the + address family of this value. Canonical form is required so that two + spellings of one address cannot form duplicate peers. + maxLength: 45 + minLength: 2 + type: string + x-kubernetes-validations: + - message: peerAddress must be a valid IP address in canonical + form + rule: isIP(self) && ip.isCanonical(self) + port: + description: |- + port is the TCP port of the BGP session, between 1 and 65535. When + omitted, port 179 is used; this default is applied by the consumers + and is subject to change over time. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - peerASN + - peerAddress + type: object + x-kubernetes-validations: + - message: holdTimeSeconds must be at least 3 times keepaliveTimeSeconds + rule: '!(has(self.holdTimeSeconds) && has(self.keepaliveTimeSeconds)) + || self.holdTimeSeconds == 0 || self.keepaliveTimeSeconds + == 0 || self.holdTimeSeconds >= 3 * self.keepaliveTimeSeconds' + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - peerAddress + x-kubernetes-list-type: map + required: + - hostname + - peers + type: object + maxItems: 256 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - hostname + x-kubernetes-list-type: map + localASN: + description: |- + localASN is the autonomous system number the cluster's FRR instances + run under. Must be between 1 and 4294967295 (int64 because valid ASNs + exceed int32 range). + format: int64 + maximum: 4294967295 + minimum: 1 + type: integer + required: + - defaultPeers + - localASN + type: object + status: + description: status reports the consumers' progress applying the configuration. + minProperties: 1 + properties: + conditions: + description: |- + conditions reports the state of processing the configuration; when + set, between 1 and 8 entries. Known + condition types are "Rendered" (the machine-config-operator has + rendered the per-node peer configuration) and "SessionsConfigured" + (the cluster-network-operator has rendered the FRR session + configuration for application). SessionsConfigured does not assert + that the generated FRRConfiguration was accepted by the frr-k8s + admission webhook or applied on the nodes. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + observedGeneration: + description: |- + observedGeneration is the generation most recently processed by the + machine-config-operator, at least 1 when set. The + cluster-network-operator's progress is reported by the + observedGeneration of the "SessionsConfigured" condition instead; it + does not write this field. + format: int64 + minimum: 1 + type: integer + type: object + required: + - metadata + - spec + type: object + x-kubernetes-validations: + - message: bgpvipconfig is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/machineconfiguration/v1alpha1/zz_generated.model_name.go b/machineconfiguration/v1alpha1/zz_generated.model_name.go index 8a2909bc22e..0f24f5bd144 100644 --- a/machineconfiguration/v1alpha1/zz_generated.model_name.go +++ b/machineconfiguration/v1alpha1/zz_generated.model_name.go @@ -5,6 +5,41 @@ package v1alpha1 +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPConfig) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfig" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPConfigList) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigList" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPConfigSpec) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigSpec" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPConfigStatus) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigStatus" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPHostPeers) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPHostPeers" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPPasswordSecret) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPasswordSecret" +} + +// OpenAPIModelName returns the OpenAPI model name for this type. +func (in BGPVIPPeer) OpenAPIModelName() string { + return "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPeer" +} + // OpenAPIModelName returns the OpenAPI model name for this type. func (in InternalReleaseImage) OpenAPIModelName() string { return "com.github.openshift.api.machineconfiguration.v1alpha1.InternalReleaseImage" diff --git a/machineconfiguration/v1alpha1/zz_generated.swagger_doc_generated.go b/machineconfiguration/v1alpha1/zz_generated.swagger_doc_generated.go index f083032cb8f..0da9103e22c 100644 --- a/machineconfiguration/v1alpha1/zz_generated.swagger_doc_generated.go +++ b/machineconfiguration/v1alpha1/zz_generated.swagger_doc_generated.go @@ -11,6 +11,82 @@ package v1alpha1 // Those methods can be generated by using hack/update-swagger-docs.sh // AUTO-GENERATED FUNCTIONS START HERE +var map_BGPVIPConfig = map[string]string{ + "": "BGPVIPConfig carries the BGP peering configuration for BGP-based VIP management (enhancement openshift/enhancements#1982). It is a singleton named \"cluster\", generated by the installer from platform.baremetal.bgpVIPConfig in the install-config, and may be edited day-2 to reconfigure peering.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "spec": "spec is the desired BGP VIP peering configuration.", + "status": "status reports the consumers' progress applying the configuration.", +} + +func (BGPVIPConfig) SwaggerDoc() map[string]string { + return map_BGPVIPConfig +} + +var map_BGPVIPConfigList = map[string]string{ + "": "BGPVIPConfigList is a list of BGPVIPConfig resources.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", +} + +func (BGPVIPConfigList) SwaggerDoc() map[string]string { + return map_BGPVIPConfigList +} + +var map_BGPVIPConfigSpec = map[string]string{ + "": "BGPVIPConfigSpec describes the BGP peering used to advertise the API and Ingress VIPs.", + "localASN": "localASN is the autonomous system number the cluster's FRR instances run under. Must be between 1 and 4294967295 (int64 because valid ASNs exceed int32 range).", + "defaultPeers": "defaultPeers are the BGP peers every node establishes sessions with, unless the node is named in hostOverrides. Must contain between 1 and 16 peers, unique by peerAddress.", + "communities": "communities are BGP community strings attached to the VIP advertisements: \"n:n\" classic communities (RFC 1997) where each segment is a 16-bit value between 0 and 65535, or \"n:n:n\" large communities (RFC 8092) where each segment is a 32-bit value between 0 and 4294967295. When omitted, no communities are attached. Each entry must be colon-separated decimal numbers without leading zeros, between 3 and 32 characters long; when set, between 1 and 8 entries.", + "hostOverrides": "hostOverrides replaces (does not merge with) defaultPeers for the named nodes. Only the per-node peer file rendered by the machine-config-operator consumes overrides; the cluster-wide session configuration rendered by the cluster-network-operator uses defaultPeers. When omitted, all nodes use defaultPeers; when set, between 1 and 256 entries, unique by hostname.", +} + +func (BGPVIPConfigSpec) SwaggerDoc() map[string]string { + return map_BGPVIPConfigSpec +} + +var map_BGPVIPConfigStatus = map[string]string{ + "": "BGPVIPConfigStatus reports the consumers' progress applying the spec.", + "conditions": "conditions reports the state of processing the configuration; when set, between 1 and 8 entries. Known condition types are \"Rendered\" (the machine-config-operator has rendered the per-node peer configuration) and \"SessionsConfigured\" (the cluster-network-operator has rendered the FRR session configuration for application). SessionsConfigured does not assert that the generated FRRConfiguration was accepted by the frr-k8s admission webhook or applied on the nodes.", + "observedGeneration": "observedGeneration is the generation most recently processed by the machine-config-operator, at least 1 when set. The cluster-network-operator's progress is reported by the observedGeneration of the \"SessionsConfigured\" condition instead; it does not write this field.", +} + +func (BGPVIPConfigStatus) SwaggerDoc() map[string]string { + return map_BGPVIPConfigStatus +} + +var map_BGPVIPHostPeers = map[string]string{ + "": "BGPVIPHostPeers is a per-node replacement peer list.", + "hostname": "hostname of the node this override applies to, as a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each. It is compared verbatim against the hostname the node resolves for itself (as rendered into the per-node peer file), so a short name and its fully qualified form are distinct entries and only the exact match applies.", + "peers": "peers replaces defaultPeers for this node. Must contain between 1 and 16 peers, unique by peerAddress.", +} + +func (BGPVIPHostPeers) SwaggerDoc() map[string]string { + return map_BGPVIPHostPeers +} + +var map_BGPVIPPasswordSecret = map[string]string{ + "": "BGPVIPPasswordSecret references a Secret in the openshift-config namespace by name.", + "name": "name is the metadata.name of the referenced Secret in the openshift-config namespace. Must be a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each.", +} + +func (BGPVIPPasswordSecret) SwaggerDoc() map[string]string { + return map_BGPVIPPasswordSecret +} + +var map_BGPVIPPeer = map[string]string{ + "": "BGPVIPPeer describes one BGP peer.", + "peerAddress": "peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in canonical form (lowercase, no leading zeros, IPv6 zero-compressed), between 2 and 45 characters; the session's address family follows the address family of this value. Canonical form is required so that two spellings of one address cannot form duplicate peers.", + "peerASN": "peerASN is the autonomous system number of the peer. Must be between 1 and 4294967295.", + "passwordSecret": "passwordSecret references the Secret carrying the TCP MD5 password (RFC 2385) for the session. The Secret must be of type kubernetes.io/basic-auth, live in the openshift-config namespace, and carry the password in its \"password\" key (at most 80 bytes, the kernel's TCP MD5 limit). The Secret type, key, and size requirements are not validated by the API server; the consumers validate them when resolving the reference and must never surface the Secret contents in status, events, or logs. Passwords are never stored in this API. When omitted, the session is unauthenticated.", + "port": "port is the TCP port of the BGP session, between 1 and 65535. When omitted, port 179 is used; this default is applied by the consumers and is subject to change over time.", + "bfd": "bfd determines whether the session is backed by BFD fast failure detection. When set to \"Enabled\", a BFD session is established with the peer and BGP reacts to BFD failure detection. When set to \"Disabled\", failure detection relies on the BGP hold timer alone. When omitted, BFD is disabled; this default is subject to change over time.", + "ebgpMultiHop": "ebgpMultiHop determines whether the session may cross multiple hops. When set to \"Enabled\", the session may be established with a peer several router hops away. When set to \"Disabled\", the peer must be directly connected. When omitted, multihop is disabled; this default is subject to change over time.", + "holdTimeSeconds": "holdTimeSeconds is the BGP hold time in seconds, either 0 or between 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 seconds). When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", + "keepaliveTimeSeconds": "keepaliveTimeSeconds is the BGP keepalive interval in seconds, between 0 and 65535. When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", +} + +func (BGPVIPPeer) SwaggerDoc() map[string]string { + return map_BGPVIPPeer +} + var map_InternalReleaseImage = map[string]string{ "": "InternalReleaseImage is used to keep track and manage a set of release bundles (OCP and OLM operators images) that are stored into the control planes nodes.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index fbb8d32f7e7..49f9f39671d 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -999,6 +999,13 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA machinev1beta1.VSphereMachineProviderSpec{}.OpenAPIModelName(): schema_openshift_api_machine_v1beta1_VSphereMachineProviderSpec(ref), machinev1beta1.VSphereMachineProviderStatus{}.OpenAPIModelName(): schema_openshift_api_machine_v1beta1_VSphereMachineProviderStatus(ref), machinev1beta1.Workspace{}.OpenAPIModelName(): schema_openshift_api_machine_v1beta1_Workspace(ref), + machineconfigurationv1alpha1.BGPVIPConfig{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfig(ref), + machineconfigurationv1alpha1.BGPVIPConfigList{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigList(ref), + machineconfigurationv1alpha1.BGPVIPConfigSpec{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigSpec(ref), + machineconfigurationv1alpha1.BGPVIPConfigStatus{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigStatus(ref), + machineconfigurationv1alpha1.BGPVIPHostPeers{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPHostPeers(ref), + machineconfigurationv1alpha1.BGPVIPPasswordSecret{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPPasswordSecret(ref), + machineconfigurationv1alpha1.BGPVIPPeer{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPPeer(ref), machineconfigurationv1alpha1.InternalReleaseImage{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_InternalReleaseImage(ref), machineconfigurationv1alpha1.InternalReleaseImageBundleStatus{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_InternalReleaseImageBundleStatus(ref), machineconfigurationv1alpha1.InternalReleaseImageList{}.OpenAPIModelName(): schema_openshift_api_machineconfiguration_v1alpha1_InternalReleaseImageList(ref), @@ -48529,6 +48536,375 @@ func schema_openshift_api_machine_v1beta1_Workspace(ref common.ReferenceCallback } } +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPConfig carries the BGP peering configuration for BGP-based VIP management (enhancement openshift/enhancements#1982). It is a singleton named \"cluster\", generated by the installer from platform.baremetal.bgpVIPConfig in the install-config, and may be edited day-2 to reconfigure peering.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Default: map[string]interface{}{}, + Ref: ref(metav1.ObjectMeta{}.OpenAPIModelName()), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "spec is the desired BGP VIP peering configuration.", + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPConfigSpec{}.OpenAPIModelName()), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "status reports the consumers' progress applying the configuration.", + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPConfigStatus{}.OpenAPIModelName()), + }, + }, + }, + Required: []string{"metadata", "spec"}, + }, + }, + Dependencies: []string{ + machineconfigurationv1alpha1.BGPVIPConfigSpec{}.OpenAPIModelName(), machineconfigurationv1alpha1.BGPVIPConfigStatus{}.OpenAPIModelName(), metav1.ObjectMeta{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPConfigList is a list of BGPVIPConfig resources.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(metav1.ListMeta{}.OpenAPIModelName()), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPConfig{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + machineconfigurationv1alpha1.BGPVIPConfig{}.OpenAPIModelName(), metav1.ListMeta{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPConfigSpec describes the BGP peering used to advertise the API and Ingress VIPs.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "localASN": { + SchemaProps: spec.SchemaProps{ + Description: "localASN is the autonomous system number the cluster's FRR instances run under. Must be between 1 and 4294967295 (int64 because valid ASNs exceed int32 range).", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "defaultPeers": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "peerAddress", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "defaultPeers are the BGP peers every node establishes sessions with, unless the node is named in hostOverrides. Must contain between 1 and 16 peers, unique by peerAddress.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPPeer{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + "communities": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "communities are BGP community strings attached to the VIP advertisements: \"n:n\" classic communities (RFC 1997) where each segment is a 16-bit value between 0 and 65535, or \"n:n:n\" large communities (RFC 8092) where each segment is a 32-bit value between 0 and 4294967295. When omitted, no communities are attached. Each entry must be colon-separated decimal numbers without leading zeros, between 3 and 32 characters long; when set, between 1 and 8 entries.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "hostOverrides": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "hostname", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "hostOverrides replaces (does not merge with) defaultPeers for the named nodes. Only the per-node peer file rendered by the machine-config-operator consumes overrides; the cluster-wide session configuration rendered by the cluster-network-operator uses defaultPeers. When omitted, all nodes use defaultPeers; when set, between 1 and 256 entries, unique by hostname.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPHostPeers{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + }, + Required: []string{"localASN", "defaultPeers"}, + }, + }, + Dependencies: []string{ + machineconfigurationv1alpha1.BGPVIPHostPeers{}.OpenAPIModelName(), machineconfigurationv1alpha1.BGPVIPPeer{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPConfigStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPConfigStatus reports the consumers' progress applying the spec.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "conditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "type", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "conditions reports the state of processing the configuration; when set, between 1 and 8 entries. Known condition types are \"Rendered\" (the machine-config-operator has rendered the per-node peer configuration) and \"SessionsConfigured\" (the cluster-network-operator has rendered the FRR session configuration for application). SessionsConfigured does not assert that the generated FRRConfiguration was accepted by the frr-k8s admission webhook or applied on the nodes.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(metav1.Condition{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + "observedGeneration": { + SchemaProps: spec.SchemaProps{ + Description: "observedGeneration is the generation most recently processed by the machine-config-operator, at least 1 when set. The cluster-network-operator's progress is reported by the observedGeneration of the \"SessionsConfigured\" condition instead; it does not write this field.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + }, + }, + Dependencies: []string{ + metav1.Condition{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPHostPeers(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPHostPeers is a per-node replacement peer list.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "hostname": { + SchemaProps: spec.SchemaProps{ + Description: "hostname of the node this override applies to, as a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each. It is compared verbatim against the hostname the node resolves for itself (as rendered into the per-node peer file), so a short name and its fully qualified form are distinct entries and only the exact match applies.", + Type: []string{"string"}, + Format: "", + }, + }, + "peers": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "peerAddress", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "peers replaces defaultPeers for this node. Must contain between 1 and 16 peers, unique by peerAddress.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPPeer{}.OpenAPIModelName()), + }, + }, + }, + }, + }, + }, + Required: []string{"hostname", "peers"}, + }, + }, + Dependencies: []string{ + machineconfigurationv1alpha1.BGPVIPPeer{}.OpenAPIModelName()}, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPPasswordSecret(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPPasswordSecret references a Secret in the openshift-config namespace by name.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the metadata.name of the referenced Secret in the openshift-config namespace. Must be a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name"}, + }, + }, + } +} + +func schema_openshift_api_machineconfiguration_v1alpha1_BGPVIPPeer(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BGPVIPPeer describes one BGP peer.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "peerAddress": { + SchemaProps: spec.SchemaProps{ + Description: "peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in canonical form (lowercase, no leading zeros, IPv6 zero-compressed), between 2 and 45 characters; the session's address family follows the address family of this value. Canonical form is required so that two spellings of one address cannot form duplicate peers.", + Type: []string{"string"}, + Format: "", + }, + }, + "peerASN": { + SchemaProps: spec.SchemaProps{ + Description: "peerASN is the autonomous system number of the peer. Must be between 1 and 4294967295.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "passwordSecret": { + SchemaProps: spec.SchemaProps{ + Description: "passwordSecret references the Secret carrying the TCP MD5 password (RFC 2385) for the session. The Secret must be of type kubernetes.io/basic-auth, live in the openshift-config namespace, and carry the password in its \"password\" key (at most 80 bytes, the kernel's TCP MD5 limit). The Secret type, key, and size requirements are not validated by the API server; the consumers validate them when resolving the reference and must never surface the Secret contents in status, events, or logs. Passwords are never stored in this API. When omitted, the session is unauthenticated.", + Default: map[string]interface{}{}, + Ref: ref(machineconfigurationv1alpha1.BGPVIPPasswordSecret{}.OpenAPIModelName()), + }, + }, + "port": { + SchemaProps: spec.SchemaProps{ + Description: "port is the TCP port of the BGP session, between 1 and 65535. When omitted, port 179 is used; this default is applied by the consumers and is subject to change over time.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "bfd": { + SchemaProps: spec.SchemaProps{ + Description: "bfd determines whether the session is backed by BFD fast failure detection. When set to \"Enabled\", a BFD session is established with the peer and BGP reacts to BFD failure detection. When set to \"Disabled\", failure detection relies on the BGP hold timer alone. When omitted, BFD is disabled; this default is subject to change over time.", + Type: []string{"string"}, + Format: "", + }, + }, + "ebgpMultiHop": { + SchemaProps: spec.SchemaProps{ + Description: "ebgpMultiHop determines whether the session may cross multiple hops. When set to \"Enabled\", the session may be established with a peer several router hops away. When set to \"Disabled\", the peer must be directly connected. When omitted, multihop is disabled; this default is subject to change over time.", + Type: []string{"string"}, + Format: "", + }, + }, + "holdTimeSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "holdTimeSeconds is the BGP hold time in seconds, either 0 or between 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 seconds). When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "keepaliveTimeSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "keepaliveTimeSeconds is the BGP keepalive interval in seconds, between 0 and 65535. When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + Required: []string{"peerAddress", "peerASN"}, + }, + }, + Dependencies: []string{ + machineconfigurationv1alpha1.BGPVIPPasswordSecret{}.OpenAPIModelName()}, + } +} + func schema_openshift_api_machineconfiguration_v1alpha1_InternalReleaseImage(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/openapi/openapi.json b/openapi/openapi.json index 2c13f336217..6cb676c5a0f 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -28017,6 +28017,225 @@ } } }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfig": { + "description": "BGPVIPConfig carries the BGP peering configuration for BGP-based VIP management (enhancement openshift/enhancements#1982). It is a singleton named \"cluster\", generated by the installer from platform.baremetal.bgpVIPConfig in the install-config, and may be edited day-2 to reconfigure peering.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", + "type": "object", + "required": [ + "metadata", + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "spec is the desired BGP VIP peering configuration.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigSpec" + }, + "status": { + "description": "status reports the consumers' progress applying the configuration.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigStatus" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigList": { + "description": "BGPVIPConfigList is a list of BGPVIPConfig resources.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", + "type": "object", + "required": [ + "metadata", + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfig" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigSpec": { + "description": "BGPVIPConfigSpec describes the BGP peering used to advertise the API and Ingress VIPs.", + "type": "object", + "required": [ + "localASN", + "defaultPeers" + ], + "properties": { + "communities": { + "description": "communities are BGP community strings attached to the VIP advertisements: \"n:n\" classic communities (RFC 1997) where each segment is a 16-bit value between 0 and 65535, or \"n:n:n\" large communities (RFC 8092) where each segment is a 32-bit value between 0 and 4294967295. When omitted, no communities are attached. Each entry must be colon-separated decimal numbers without leading zeros, between 3 and 32 characters long; when set, between 1 and 8 entries.", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + }, + "defaultPeers": { + "description": "defaultPeers are the BGP peers every node establishes sessions with, unless the node is named in hostOverrides. Must contain between 1 and 16 peers, unique by peerAddress.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPeer" + }, + "x-kubernetes-list-map-keys": [ + "peerAddress" + ], + "x-kubernetes-list-type": "map" + }, + "hostOverrides": { + "description": "hostOverrides replaces (does not merge with) defaultPeers for the named nodes. Only the per-node peer file rendered by the machine-config-operator consumes overrides; the cluster-wide session configuration rendered by the cluster-network-operator uses defaultPeers. When omitted, all nodes use defaultPeers; when set, between 1 and 256 entries, unique by hostname.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPHostPeers" + }, + "x-kubernetes-list-map-keys": [ + "hostname" + ], + "x-kubernetes-list-type": "map" + }, + "localASN": { + "description": "localASN is the autonomous system number the cluster's FRR instances run under. Must be between 1 and 4294967295 (int64 because valid ASNs exceed int32 range).", + "type": "integer", + "format": "int64" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPConfigStatus": { + "description": "BGPVIPConfigStatus reports the consumers' progress applying the spec.", + "type": "object", + "properties": { + "conditions": { + "description": "conditions reports the state of processing the configuration; when set, between 1 and 8 entries. Known condition types are \"Rendered\" (the machine-config-operator has rendered the per-node peer configuration) and \"SessionsConfigured\" (the cluster-network-operator has rendered the FRR session configuration for application). SessionsConfigured does not assert that the generated FRRConfiguration was accepted by the frr-k8s admission webhook or applied on the nodes.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Condition" + }, + "x-kubernetes-list-map-keys": [ + "type" + ], + "x-kubernetes-list-type": "map" + }, + "observedGeneration": { + "description": "observedGeneration is the generation most recently processed by the machine-config-operator, at least 1 when set. The cluster-network-operator's progress is reported by the observedGeneration of the \"SessionsConfigured\" condition instead; it does not write this field.", + "type": "integer", + "format": "int64" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPHostPeers": { + "description": "BGPVIPHostPeers is a per-node replacement peer list.", + "type": "object", + "required": [ + "hostname", + "peers" + ], + "properties": { + "hostname": { + "description": "hostname of the node this override applies to, as a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each. It is compared verbatim against the hostname the node resolves for itself (as rendered into the per-node peer file), so a short name and its fully qualified form are distinct entries and only the exact match applies.", + "type": "string" + }, + "peers": { + "description": "peers replaces defaultPeers for this node. Must contain between 1 and 16 peers, unique by peerAddress.", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPeer" + }, + "x-kubernetes-list-map-keys": [ + "peerAddress" + ], + "x-kubernetes-list-type": "map" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPasswordSecret": { + "description": "BGPVIPPasswordSecret references a Secret in the openshift-config namespace by name.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "name is the metadata.name of the referenced Secret in the openshift-config namespace. Must be a non-empty RFC 1123 subdomain of at most 253 characters with dot-separated labels of at most 63 characters each.", + "type": "string" + } + } + }, + "com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPeer": { + "description": "BGPVIPPeer describes one BGP peer.", + "type": "object", + "required": [ + "peerAddress", + "peerASN" + ], + "properties": { + "bfd": { + "description": "bfd determines whether the session is backed by BFD fast failure detection. When set to \"Enabled\", a BFD session is established with the peer and BGP reacts to BFD failure detection. When set to \"Disabled\", failure detection relies on the BGP hold timer alone. When omitted, BFD is disabled; this default is subject to change over time.", + "type": "string" + }, + "ebgpMultiHop": { + "description": "ebgpMultiHop determines whether the session may cross multiple hops. When set to \"Enabled\", the session may be established with a peer several router hops away. When set to \"Disabled\", the peer must be directly connected. When omitted, multihop is disabled; this default is subject to change over time.", + "type": "string" + }, + "holdTimeSeconds": { + "description": "holdTimeSeconds is the BGP hold time in seconds, either 0 or between 3 and 65535 (RFC 4271 requires a hold time of 0 or at least 3 seconds). When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", + "type": "integer", + "format": "int32" + }, + "keepaliveTimeSeconds": { + "description": "keepaliveTimeSeconds is the BGP keepalive interval in seconds, between 0 and 65535. When omitted or 0, the FRR default is used; this is subject to change over time. When both holdTimeSeconds and keepaliveTimeSeconds are set and non-zero, holdTimeSeconds must be at least 3 times keepaliveTimeSeconds.", + "type": "integer", + "format": "int32" + }, + "passwordSecret": { + "description": "passwordSecret references the Secret carrying the TCP MD5 password (RFC 2385) for the session. The Secret must be of type kubernetes.io/basic-auth, live in the openshift-config namespace, and carry the password in its \"password\" key (at most 80 bytes, the kernel's TCP MD5 limit). The Secret type, key, and size requirements are not validated by the API server; the consumers validate them when resolving the reference and must never surface the Secret contents in status, events, or logs. Passwords are never stored in this API. When omitted, the session is unauthenticated.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.machineconfiguration.v1alpha1.BGPVIPPasswordSecret" + }, + "peerASN": { + "description": "peerASN is the autonomous system number of the peer. Must be between 1 and 4294967295.", + "type": "integer", + "format": "int64" + }, + "peerAddress": { + "description": "peerAddress is the IP address of the BGP peer (IPv4 or IPv6) in canonical form (lowercase, no leading zeros, IPv6 zero-compressed), between 2 and 45 characters; the session's address family follows the address family of this value. Canonical form is required so that two spellings of one address cannot form duplicate peers.", + "type": "string" + }, + "port": { + "description": "port is the TCP port of the BGP session, between 1 and 65535. When omitted, port 179 is used; this default is applied by the consumers and is subject to change over time.", + "type": "integer", + "format": "int32" + } + } + }, "com.github.openshift.api.machineconfiguration.v1alpha1.InternalReleaseImage": { "description": "InternalReleaseImage is used to keep track and manage a set of release bundles (OCP and OLM operators images) that are stored into the control planes nodes.\n\nCompatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.", "type": "object",