Skip to content

Commit 96a320a

Browse files
committed
rfc: IGP resource, controller, and provider
Add a Custom Resource for Interior Gateway Protocol (IGP) spec. While we plan support for ISIS and OSPF, we consider only ISIS here. We also include a `cisco-nxos-gnmi` provider with an `isis` pkg to configure ISIS over gNMI using ygot objects from openconfig. This provider does not implement yet the `interface` resource. Both the resource and the provider implementation DO NOT support multiple IGP processes on the same device.
1 parent 3e98cbf commit 96a320a

25 files changed

+1158
-114
lines changed

Tiltfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ load('ext://cert_manager', 'deploy_cert_manager')
1313
deploy_cert_manager(version='v1.18.2')
1414

1515
docker_build('controller:latest', '.', ignore=['*/*/zz_generated.deepcopy.go', 'config/crd/bases/*'], only=[
16-
'api/', 'cmd/', 'hack/', 'internal/', 'go.mod', 'go.sum', 'Makefile',
16+
'api/', 'cmd/', 'hack/', 'internal/', 'go.mod', 'go.sum', 'Makefile'
1717
])
1818

1919
local_resource('controller-gen', 'make generate', ignore=['*/*/zz_generated.deepcopy.go', 'config/crd/bases/*'], deps=[
@@ -37,6 +37,9 @@ k8s_resource(new_name='eth1-1', objects=['eth1-1:interface'], trigger_mode=TRIGG
3737
k8s_resource(new_name='eth1-2', objects=['eth1-2:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
3838
k8s_resource(new_name='eth1-10', objects=['eth1-10:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
3939

40+
k8s_yaml('./config/samples/v1alpha1_igp.yaml')
41+
k8s_resource(new_name='underlay-isis-area-0', objects=['underlay-isis-area-0:igp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
42+
4043
print('🚀 network-operator development environment')
4144
print('👉 Edit the code inside the api/, cmd/, or internal/ directories')
4245
print('👉 Tilt will automatically rebuild and redeploy when changes are detected')

api/v1alpha1/igp_types.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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+
)
9+
10+
// +kubebuilder:validation:Enum=isis
11+
type IGPType string
12+
13+
// +kubebuilder:object:root=true
14+
// +kubebuilder:subresource:status
15+
// +kubebuilder:resource:path=igps
16+
// +kubebuilder:resource:singular=igp
17+
// +kubebuilder:resource:shortName=igp
18+
// +kubebuilder:printcolumn:name="Process name",type=string,JSONPath=`.spec.name`
19+
20+
// IGP is the Schema for the igp API.
21+
type IGP struct {
22+
metav1.TypeMeta `json:",inline"`
23+
metav1.ObjectMeta `json:"metadata,omitempty"`
24+
25+
// Specification of the desired state of the resource.
26+
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
27+
Spec IGPSpec `json:"spec"`
28+
29+
// Status of the resource. This is set and updated automatically.
30+
// Read-only.
31+
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
32+
Status IGPStatus `json:"status"`
33+
}
34+
35+
// IGProcessSpec defines the desired state of Interior Gateway Protocol (IGP) process on a device.
36+
type IGPSpec struct {
37+
// The name of the routing instance.
38+
//+kubebuilder:validation:Required
39+
Name string `json:"name"`
40+
//+kubebuilder:validation:Required
41+
ISIS *ISISSpec `json:"isis,omitempty"`
42+
}
43+
44+
// IGPStatus defines the observed state of an IGP process.
45+
type IGPStatus struct {
46+
// The conditions are a list of status objects that describe the state of the Interface.
47+
//+listType=map
48+
//+listMapKey=type
49+
//+patchStrategy=merge
50+
//+patchMergeKey=type
51+
//+optional
52+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
53+
}
54+
55+
// +kubebuilder:object:root=true
56+
57+
// IGPList contains a list of IGP (processes).
58+
type IGPList struct {
59+
metav1.TypeMeta `json:",inline"`
60+
metav1.ListMeta `json:"metadata,omitempty"`
61+
Items []IGP `json:"items"`
62+
}
63+
64+
// +kubebuilder:validation:Enum=Level1;Level2;Level12
65+
type ISISLevel string
66+
67+
const (
68+
Level1 ISISLevel = "Level1"
69+
Level2 ISISLevel = "Level2"
70+
Level12 ISISLevel = "Level12"
71+
)
72+
73+
// +kubebuilder:validation:Enum=v4-unicast;v6-unicast
74+
type ISISAF string
75+
76+
const (
77+
IPv4Unicast ISISAF = "v4-unicast"
78+
IPv6Unicast ISISAF = "v6-unicast"
79+
)
80+
81+
type ISISSpec struct {
82+
// The Network Entity Title (NET) for the ISIS instance.
83+
//+kubebuilder:validation:Required
84+
NET string `json:"net"`
85+
// The is-type of the process (the level)
86+
//+kubebuilder:validation:Required
87+
Level ISISLevel `json:"level"`
88+
// Overload bit configuration for this ISIS instance
89+
//+kubebuilder:validation:Optional
90+
OverloadBit *OverloadBit `json:"overloadBit"`
91+
//+kubebuilder:validation:Required
92+
//+kubebuilder:validation:MinItems=1
93+
//+kubebuilder:validation:MaxItems=2
94+
AddressFamilies []ISISAF `json:"addressFamilies,omitempty"`
95+
}
96+
97+
type OverloadBit struct {
98+
// Duration of the OverloadBit in seconds.
99+
//+kubebuilder:validation:Required
100+
//+kubebuilder:validation:Minimum=576
101+
//+kubebuilder:validation:Maximum=86400
102+
OnStartup uint32 `json:"onStartup"`
103+
}
104+
105+
func init() {
106+
SchemeBuilder.Register(&IGP{}, &IGPList{})
107+
}

api/v1alpha1/zz_generated.deepcopy.go

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

cmd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ func main() {
8080
flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.")
8181
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
8282
flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers")
83-
flag.StringVar(&watchFilterValue, "watch-filter", "", fmt.Sprintf("Label value that the controller watches to reconcile api objects. Label key is always %q. If unspecified, the controller watches for all api objects.", v1alpha1.WatchLabel))
84-
flag.StringVar(&providerName, "provider", "openconfig", "The provider to use for the controller. If not specified, the default provider is used. Available providers: "+strings.Join(provider.Providers(), ", "))
83+
flag.StringVar(&watchFilterValue, "watch-filter", "", fmt.Sprintf("Label value that the controllers watch to reconcile api objects. Label key is always %q. If unspecified, the controller watches for all api objects.", v1alpha1.WatchLabel))
84+
flag.StringVar(&providerName, "provider", "cisco-nxos-gnmi", "The provider to use for the controllers. If not specified, the default provider is used. Available providers: "+strings.Join(provider.Providers(), ", "))
8585
opts := zap.Options{
8686
Development: true,
8787
TimeEncoder: zapcore.ISO8601TimeEncoder,

0 commit comments

Comments
 (0)