Skip to content

Commit a4d2c6f

Browse files
committed
feat: define CRDs for VRF type
A VRF is composed by a single route distinguisher (RD), and a set of route targets (RTs). This set might be empty. Each route target is composed by the address families it affects and an action for it (e.g., import or export). The ipv4-evpn and ipv6-evpn will apply the route target actions to the EVPN context of the device.
1 parent bdc24c5 commit a4d2c6f

14 files changed

+647
-4
lines changed

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ resources:
2828
kind: Device
2929
path: github.com/ironcore-dev/network-operator/api/v1alpha1
3030
version: v1alpha1
31+
- api:
32+
crdVersion: v1
33+
namespaced: true
34+
controller: true
35+
domain: cloud.sap
36+
group: networking
37+
kind: VRF
38+
path: github.com/ironcore-dev/network-operator/api/v1alpha1
39+
version: v1alpha1
3140
version: "3"

api/v1alpha1/vrf_types.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
ctrl "sigs.k8s.io/controller-runtime"
9+
)
10+
11+
// VRFSpec defines the basic structure of a Virtual Routing and Forwarding (VRF) instance/context. A VRF has one single Route
12+
// Distinguisher (RD) and a set of Route Targets (RTs), which can be empty. RTs control the import and export of routes among
13+
//
14+
// different VRFs.
15+
type VRFSpec struct {
16+
// DeviceName is a ref to the device owning this VRF. Device must exist in the same namespace as the VRF.
17+
//
18+
// +required
19+
// +kubebuilder:validation:MinLength=1
20+
// +kubebuilder:validation:MaxLength=63
21+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="deviceName is immutable"
22+
DeviceName string `json:"deviceName,omitempty"`
23+
24+
// Name defines the name of the VRF.
25+
//
26+
// +required
27+
// +kubebuilder:validation:MaxLength=32
28+
// +kubebuilder:validation:MinLength=1
29+
// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]+$`
30+
Name string `json:"name,omitempty"`
31+
32+
// AdminState defines the administrative state of the VRF.
33+
//
34+
// +required
35+
// +kubebuilder:validation:Enum=Up;Down
36+
AdminState AdminState `json:"adminState,omitempty"`
37+
38+
// RD defines the Route Distinguisher (RD) for the VRF as per RFC 4364
39+
//
40+
// +kubebuilder:validation:Pattern=`^([0-9]+:[0-9]+|([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]+)$`
41+
// +required
42+
RD string `json:"routeDistinguisher,omitempty"`
43+
44+
// RTs defines the list of Route Targets (RTs) associated with the VRF.
45+
//
46+
// +optional
47+
RTs []RouteTarget `json:"routeTargets,omitempty"`
48+
49+
// TODO(nikatza): Discuss in weekly, depends on #30
50+
// ProviderConfigRef is a reference to a resource holding the provider-specific configuration of this VRF
51+
// (e.g., a layer-3 VNI on cisco).
52+
//
53+
// +optional
54+
// ProviderConfigRef *any `json:"providerConfigRef,omitempty"` // TODO: any is a placeholder until we discuss #30
55+
}
56+
57+
// VRFStatus defines the observed state of VRF.
58+
type VRFStatus struct {
59+
// The conditions are a list of status objects that describe the state of the D.
60+
// +listType=map
61+
// +listMapKey=type
62+
// +patchStrategy=merge
63+
// +patchMergeKey=type
64+
// +optional
65+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
66+
}
67+
68+
// +kubebuilder:object:root=true
69+
// +kubebuilder:subresource:status
70+
// +kubebuilder:resource:path=vrfs
71+
// +kubebuilder:resource:singular=vrf
72+
// +kubebuilder:resource:shortName=vrf
73+
// +kubebuilder:printcolumn:name="VRF",type=string,JSONPath=`.spec.name`
74+
// +kubebuilder:printcolumn:name="Admin State",type=string,JSONPath=`.spec.adminState`
75+
// +kubebuilder:printcolumn:name="Device",type=string,JSONPath=`.spec.deviceName`
76+
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
77+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
78+
//
79+
// VRF is the Schema for the VRFs API
80+
type VRF struct {
81+
metav1.TypeMeta `json:",inline"`
82+
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
83+
84+
Spec VRFSpec `json:"spec,omitempty"`
85+
Status VRFStatus `json:"status,omitempty"`
86+
}
87+
88+
// +kubebuilder:object:root=true
89+
90+
// VRFList contains a list of VRF
91+
type VRFList struct {
92+
metav1.TypeMeta `json:",inline"`
93+
metav1.ListMeta `json:"metadata,omitempty"`
94+
Items []VRF `json:"items"`
95+
}
96+
97+
// RouteTarget defines the structure for a single route target in a VRF. A RT is essentially an extended BGP
98+
// community used to control route import/export between VRFs. RTs may be also be associated with address
99+
// families (IPv4, IPv6), and might be also added to the EVPN via the ipv4-evpn and ipv6-evpn address families.
100+
type RouteTarget struct {
101+
// Value specifies the Route Target (RT) value as per RFC 4364.
102+
//
103+
// +kubebuilder:validation:Pattern=`^([0-9]+:[0-9]+|([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]+)$`
104+
Value string `json:"value,omitempty"`
105+
106+
// AddressFamily specifies the address families for the Route Target. Families ipv4-evpn and ipv6-evpn indicate
107+
// that the RT should be applied to the EVPN contexts (see RFC 7432).
108+
//
109+
// +kubebuilder:validation:MinItems=1
110+
AddressFamilies []AddressFamily `json:"addressFamilies,omitempty"`
111+
112+
// Action specifies how this RT should be used within the VRF.
113+
//
114+
// +kubebuilder:validation:Enum=none;import;export;both
115+
Action RTAction `json:"action,omitempty"`
116+
}
117+
118+
// +kubebuilder:validation:Enum=ipv4;ipv6;ipv4-evpn;ipv6-evpn
119+
type AddressFamily string
120+
121+
const (
122+
AddressFamilyIPv4 AddressFamily = "ipv4"
123+
AddressFamilyIPv6 AddressFamily = "ipv6"
124+
AddressFamilyIPv4EVPN AddressFamily = "ipv4-evpn"
125+
AddressFamilyIPv6EVPN AddressFamily = "ipv6-evpn"
126+
)
127+
128+
type RTAction string
129+
130+
const (
131+
RTNone RTAction = "none"
132+
RTImport RTAction = "import"
133+
RTExport RTAction = "export"
134+
RTBoth RTAction = "both"
135+
)
136+
137+
func init() {
138+
SchemeBuilder.Register(&VRF{}, &VRFList{})
139+
}
140+
141+
func (r *VRF) SetupWebhookWithManager(mgr ctrl.Manager) error {
142+
return ctrl.NewWebhookManagedBy(mgr).
143+
For(r).
144+
Complete()
145+
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 123 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/networking.cloud.sap_devices.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: devices.networking.cloud.sap
88
spec:
99
group: networking.cloud.sap

config/crd/bases/networking.cloud.sap_interfaces.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: interfaces.networking.cloud.sap
88
spec:
99
group: networking.cloud.sap

0 commit comments

Comments
 (0)