Skip to content

Commit 0b789b3

Browse files
committed
Add controller to NXOSVPC
1 parent 57755c4 commit 0b789b3

File tree

11 files changed

+459
-121
lines changed

11 files changed

+459
-121
lines changed

Tiltfile

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ local_resource('controller-gen', 'make generate', ignore=['*/*/zz_generated.deep
2222

2323
docker_build('ghcr.io/ironcore-dev/gnmi-test-server:latest', './test/gnmi')
2424

25-
provider = os.getenv('PROVIDER', 'openconfig')
25+
provider = os.getenv('PROVIDER', 'cisco-nxos-gnmi')
2626

2727
manager = kustomize('config/develop')
2828
manager = str(manager).replace('--provider=openconfig', '--provider={}'.format(provider))
@@ -41,42 +41,47 @@ def device_yaml():
4141
k8s_yaml(device_yaml())
4242
k8s_resource(new_name='leaf1', objects=['leaf1:device', 'secret-basic-auth:secret'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
4343

44-
k8s_yaml('./config/samples/v1alpha1_interface.yaml')
45-
k8s_resource(new_name='lo0', objects=['lo0:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
46-
k8s_resource(new_name='lo1', objects=['lo1:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
47-
k8s_resource(new_name='eth1-1', objects=['eth1-1:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
48-
k8s_resource(new_name='eth1-2', objects=['eth1-2:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
49-
k8s_resource(new_name='eth1-10', objects=['eth1-10:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
44+
# k8s_yaml('./config/samples/v1alpha1_interface.yaml')
45+
# k8s_resource(new_name='lo0', objects=['lo0:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
46+
# k8s_resource(new_name='lo1', objects=['lo1:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
47+
# k8s_resource(new_name='eth1-1', objects=['eth1-1:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
48+
# k8s_resource(new_name='eth1-2', objects=['eth1-2:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
49+
# k8s_resource(new_name='eth1-10', objects=['eth1-10:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
5050

51-
k8s_yaml('./config/samples/v1alpha1_banner.yaml')
52-
k8s_resource(new_name='banner', objects=['banner:banner'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
51+
# k8s_yaml('./config/samples/v1alpha1_banner.yaml')
52+
# k8s_resource(new_name='banner', objects=['banner:banner'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
5353

54-
k8s_yaml('./config/samples/v1alpha1_user.yaml')
55-
k8s_resource(new_name='user', objects=['user:user', 'user-password:secret', 'user-ssh-key:secret'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
54+
# k8s_yaml('./config/samples/v1alpha1_user.yaml')
55+
# k8s_resource(new_name='user', objects=['user:user', 'user-password:secret', 'user-ssh-key:secret'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
5656

57-
k8s_yaml('./config/samples/v1alpha1_dns.yaml')
58-
k8s_resource(new_name='dns', objects=['dns:dns'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
57+
# k8s_yaml('./config/samples/v1alpha1_dns.yaml')
58+
# k8s_resource(new_name='dns', objects=['dns:dns'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
5959

60-
k8s_yaml('./config/samples/v1alpha1_ntp.yaml')
61-
k8s_resource(new_name='ntp', objects=['ntp:ntp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
60+
# k8s_yaml('./config/samples/v1alpha1_ntp.yaml')
61+
# k8s_resource(new_name='ntp', objects=['ntp:ntp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
6262

63-
k8s_yaml('./config/samples/v1alpha1_acl.yaml')
64-
k8s_resource(new_name='acl', objects=['acl:accesscontrollist'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
63+
# k8s_yaml('./config/samples/v1alpha1_acl.yaml')
64+
# k8s_resource(new_name='acl', objects=['acl:accesscontrollist'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
6565

66-
k8s_yaml('./config/samples/v1alpha1_certificate.yaml')
67-
k8s_resource(new_name='trustpoint', objects=['network-operator:issuer', 'network-operator-ca:certificate', 'trustpoint:certificate'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
66+
# k8s_yaml('./config/samples/v1alpha1_certificate.yaml')
67+
# k8s_resource(new_name='trustpoint', objects=['network-operator:issuer', 'network-operator-ca:certificate', 'trustpoint:certificate'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
6868

69-
k8s_yaml('./config/samples/v1alpha1_snmp.yaml')
70-
k8s_resource(new_name='snmp', objects=['snmp:snmp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
69+
# k8s_yaml('./config/samples/v1alpha1_snmp.yaml')
70+
# k8s_resource(new_name='snmp', objects=['snmp:snmp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
7171

72-
k8s_yaml('./config/samples/v1alpha1_syslog.yaml')
73-
k8s_resource(new_name='syslog', objects=['syslog:syslog'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
72+
# k8s_yaml('./config/samples/v1alpha1_syslog.yaml')
73+
# k8s_resource(new_name='syslog', objects=['syslog:syslog'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
7474

75-
k8s_yaml('./config/samples/v1alpha1_managementaccess.yaml')
76-
k8s_resource(new_name='managementaccess', objects=['managementaccess:managementaccess'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
75+
# k8s_yaml('./config/samples/v1alpha1_managementaccess.yaml')
76+
# k8s_resource(new_name='managementaccess', objects=['managementaccess:managementaccess'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
77+
78+
# k8s_yaml('./config/samples/v1alpha1_isis.yaml')
79+
# k8s_resource(new_name='underlay', objects=['underlay:isis'], resource_deps=['lo0', 'lo1', 'eth1-1', 'eth1-2'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
80+
81+
# TODO: add resource_deps=['po1', 'po2'] when port-channel resource is implemented
82+
k8s_yaml('./config/samples/v1alpha1_nxosvpc.yaml')
83+
k8s_resource(new_name='vpc', objects=['nxosvpc:nxosvpc'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
7784

78-
k8s_yaml('./config/samples/v1alpha1_isis.yaml')
79-
k8s_resource(new_name='underlay', objects=['underlay:isis'], resource_deps=['lo0', 'lo1', 'eth1-1', 'eth1-2'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
8085

8186
print('🚀 network-operator development environment')
8287
print('👉 Edit the code inside the api/, cmd/, or internal/ directories')

api/v1alpha1/nxosvpc_types.go

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,6 @@ import (
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
)
99

10-
// kind: NXOSVirtualPortchannel
11-
12-
// spec:
13-
// id: 69
14-
// rolePriority: 100
15-
// systemPriority: 10
16-
// delayRestore: 150
17-
18-
// peer:
19-
// switch:
20-
// enabled: true
21-
// gateway:
22-
// enabled: true
23-
// router: # layer3 peer-router
24-
// enabled: true
25-
// keepalive:
26-
// source: 10.114.235.155
27-
// destination: 10.114.235.156
28-
// autoRecovery:
29-
// reloadDelay: 360
30-
// fastConvergence:
31-
// enabled: true
32-
// peerLinkRef: # could also go into peer.linkRef
33-
// - name: ora-sw1101a-bb101-po104
34-
3510
// NXOSVPCSpec defines the desired state of NXOSVPC (Cisco's NXOS Virtual Port Channel)
3611
type NXOSVPCSpec struct {
3712
// DeviceName is the name of the Device this object belongs to. The Device object must exist in the same namespace.
@@ -40,46 +15,47 @@ type NXOSVPCSpec struct {
4015
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="DeviceRef is immutable"
4116
DeviceRef LocalObjectReference `json:"deviceRef"`
4217

43-
// ID is the vPC domain ID.
18+
// DomainID is the vPC domain ID.
4419
// +required
4520
// +kubebuilder:validation:Minimum=1
4621
// +kubebuilder:validation:Maximum=1000
4722
DomainID int32 `json:"domainId"`
4823

4924
// AdminState is the administrative state of the vPC domain.
50-
// +optional
25+
// +required
5126
// +kubebuilder:default="enabled"
27+
// +kubebuilder:validation:Enum=enabled;disabled
5228
AdminState string `json:"adminState,omitempty"`
5329

5430
// RolePriority is the role priority for this vPC domain.
55-
// +optional
31+
// +required
5632
// +kubebuilder:validation:Minimum=1
5733
// +kubebuilder:validation:Maximum=65535
58-
RolePriority int32 `json:"rolePriority,omitempty"`
34+
RolePriority uint16 `json:"rolePriority"`
5935

6036
// SystemPriority is the system priority for this vPC domain.
61-
// +optional
37+
// +required
6238
// +kubebuilder:validation:Minimum=1
6339
// +kubebuilder:validation:Maximum=65535
64-
SystemPriority int32 `json:"systemPriority,omitempty"`
40+
SystemPriority uint16 `json:"systemPriority"`
6541

6642
// DelayRestoreSVI is the delay in bringing up bringing-up the interface-vlan
67-
// +optional
43+
// +required
6844
// +kubebuilder:validation:Minimum=1
6945
// +kubebuilder:validation:Maximum=3600
70-
DelayRestoreSVI int32 `json:"delayRestoreSVI,omitempty"`
46+
DelayRestoreSVI uint16 `json:"delayRestoreSVI"`
7147

7248
// DelayRestoreVPC is the delay in bringing up the vPC links after restoring the peer-link
73-
// +optional
49+
// +required
7450
// +kubebuilder:validation:Minimum=1
7551
// +kubebuilder:validation:Maximum=3600
76-
DelayRestoreVPC int32 `json:"delayRestoreVPC,omitempty"`
52+
DelayRestoreVPC uint16 `json:"delayRestoreVPC"`
7753

78-
// +optional
79-
FastConvergence AdminSt `json:"fastConvergence,omitzero"`
54+
// +required
55+
FastConvergence AdminSt `json:"fastConvergence"`
8056

81-
// +optional
82-
Peer Peer `json:"peer,omitzero"`
57+
// +required
58+
Peer Peer `json:"peer"`
8359
}
8460

8561
// AdminSt represents administrative state (enabled/disabled)
@@ -89,30 +65,43 @@ type AdminSt struct {
8965
}
9066

9167
type Peer struct {
92-
// TODO
93-
//LinkRef []LocalObjectReference `json:"linkRef,omitempty"`
94-
// +optional
95-
KeepAlive KeepAlive `json:"keepalive,omitzero"`
68+
// +required
69+
KeepAlive KeepAlive `json:"keepalive"`
70+
// +required
71+
9672
AutoRecovery AutoRecovery `json:"autoRecovery"`
97-
PeerSwitch AdminSt `json:"peerSwitch"`
98-
PeerGateway AdminSt `json:"peerGateway"`
73+
// +required
74+
75+
Switch AdminSt `json:"switch"`
76+
// +required
77+
78+
Gateway AdminSt `json:"gateway"`
79+
9980
// Router defines layer3 peer-router settings
81+
// +required
10082
Router AdminSt `json:"router"`
10183
}
10284

10385
type KeepAlive struct {
104-
// Source IP address for keepalive messages
105-
// +kubebuilder:validation:MinLength=1
106-
// +kubebuilder:validation:MaxLength=253
107-
Source string `json:"source,omitempty"`
108-
// Destination IP address for keepalive messages
109-
// +kubebuilder:validation:MinLength=1
110-
// +kubebuilder:validation:MaxLength=253
111-
Destination string `json:"destination,omitempty"`
86+
// Destination is the destination IP address
87+
// +required
88+
Destination string `json:"destination"`
89+
90+
// Source is the source IP address
91+
// +required
92+
Source string `json:"source"`
93+
94+
// +optional
95+
VRF string `json:"vrf,omitempty"`
11296
}
11397

98+
// AutoRecovery holds autorecovery settings.
99+
// reloadDelay must be set when enabled=true, and must be absent when enabled=false.
100+
// +kubebuilder:validation:XValidation:rule="self.enabled ? has(self.reloadDelay) : !has(self.reloadDelay)",message="reloadDelay must be set when enabled and absent when disabled"
114101
type AutoRecovery struct {
102+
// +required
115103
Enabled bool `json:"enabled,omitempty"`
104+
116105
// +optional
117106
// +kubebuilder:validation:Minimum=60
118107
// +kubebuilder:validation:Maximum=3600

api/v1alpha1/zz_generated.deepcopy.go

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

cmd/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,11 @@ func main() {
341341
}
342342

343343
if err := (&controller.NXOSVPCReconciler{
344-
Client: mgr.GetClient(),
345-
Scheme: mgr.GetScheme(),
344+
Client: mgr.GetClient(),
345+
Scheme: mgr.GetScheme(),
346+
Recorder: mgr.GetEventRecorderFor("nxosvpc-controller"),
347+
WatchFilterValue: watchFilterValue,
348+
Provider: prov,
346349
}).SetupWithManager(mgr); err != nil {
347350
setupLog.Error(err, "unable to create controller", "controller", "NXOSVPC")
348351
os.Exit(1)

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

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,19 @@ spec:
6060
adminState:
6161
default: enabled
6262
description: AdminState is the administrative state of the vPC domain.
63+
enum:
64+
- enabled
65+
- disabled
6366
type: string
6467
delayRestoreSVI:
6568
description: DelayRestoreSVI is the delay in bringing up bringing-up
6669
the interface-vlan
67-
format: int32
6870
maximum: 3600
6971
minimum: 1
7072
type: integer
7173
delayRestoreVPC:
7274
description: DelayRestoreVPC is the delay in bringing up the vPC links
7375
after restoring the peer-link
74-
format: int32
7576
maximum: 3600
7677
minimum: 1
7778
type: integer
@@ -111,6 +112,9 @@ spec:
111112
peer:
112113
properties:
113114
autoRecovery:
115+
description: |-
116+
AutoRecovery holds autorecovery settings.
117+
reloadDelay must be set when enabled=true, and must be absent when enabled=false.
114118
properties:
115119
enabled:
116120
type: boolean
@@ -119,39 +123,48 @@ spec:
119123
maximum: 3600
120124
minimum: 60
121125
type: integer
126+
required:
127+
- enabled
128+
type: object
129+
x-kubernetes-validations:
130+
- message: reloadDelay must be set when enabled and absent when
131+
disabled
132+
rule: 'self.enabled ? has(self.reloadDelay) : !has(self.reloadDelay)'
133+
gateway:
134+
description: AdminSt represents administrative state (enabled/disabled)
135+
properties:
136+
enabled:
137+
type: boolean
138+
required:
139+
- enabled
122140
type: object
123141
keepalive:
124142
description: LinkRef []LocalObjectReference `json:"linkRef,omitempty"`
125143
properties:
126144
destination:
127145
description: Destination IP address for keepalive messages
128-
maxLength: 253
129-
minLength: 1
146+
(with run-time check)
130147
type: string
131148
source:
132-
description: Source IP address for keepalive messages
133-
maxLength: 253
134-
minLength: 1
149+
description: Source IP address for keepalive messages (with
150+
run-time check)
151+
type: string
152+
vrf:
135153
type: string
136-
type: object
137-
peerGateway:
138-
description: AdminSt represents administrative state (enabled/disabled)
139-
properties:
140-
enabled:
141-
type: boolean
142154
required:
143-
- enabled
155+
- destination
156+
- source
144157
type: object
145-
peerSwitch:
146-
description: AdminSt represents administrative state (enabled/disabled)
158+
router:
159+
description: Router defines layer3 peer-router settings
147160
properties:
148161
enabled:
149162
type: boolean
150163
required:
151164
- enabled
152165
type: object
153-
router:
154-
description: Router defines layer3 peer-router settings
166+
switch:
167+
description: AdminSt represents administrative state (enabled/disabled)
155168
properties:
156169
enabled:
157170
type: boolean
@@ -160,25 +173,31 @@ spec:
160173
type: object
161174
required:
162175
- autoRecovery
163-
- peerGateway
164-
- peerSwitch
176+
- gateway
177+
- keepalive
165178
- router
179+
- switch
166180
type: object
167181
rolePriority:
168182
description: RolePriority is the role priority for this vPC domain.
169-
format: int32
170183
maximum: 65535
171184
minimum: 1
172185
type: integer
173186
systemPriority:
174187
description: SystemPriority is the system priority for this vPC domain.
175-
format: int32
176188
maximum: 65535
177189
minimum: 1
178190
type: integer
179191
required:
192+
- adminState
193+
- delayRestoreSVI
194+
- delayRestoreVPC
180195
- deviceRef
181196
- domainId
197+
- fastConvergence
198+
- peer
199+
- rolePriority
200+
- systemPriority
182201
type: object
183202
status:
184203
description: status defines the observed state of NXOSVPC

0 commit comments

Comments
 (0)