Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ linters:
- builtin$
- examples$
- internal/provider/openconfig
- internal/provider/cisco/nxos/genyang

output:
formats:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ install-kustomize: FORCE

fmt: FORCE install-gofumpt
@printf "\e[1;36m>> gofumpt -l -w .\e[0m\n"
@gofumpt -l -w $(shell git ls-files '*.go' | grep -v '^internal/provider/openconfig')
@gofumpt -l -w $(shell git ls-files '*.go' | grep -v '^internal/provider/openconfig|internal/provider/cisco/nxos/genyang')

# Run the e2e tests against a k8s cluster.
test-e2e: FORCE
Expand Down Expand Up @@ -188,7 +188,7 @@ ifeq ($(GO_TESTPKGS),)
GO_TESTPKGS := ./...
endif
# which packages to measure coverage for
GO_COVERPKGS := $(shell go list ./... | grep -E '/internal' | grep -Ev '/internal/provider/openconfig')
GO_COVERPKGS := $(shell go list ./... | grep -E '/internal' | grep -Ev '/internal/provider/openconfig|internal/provider/cisco/nxos/genyang')
# to get around weird Makefile syntax restrictions, we need variables containing nothing, a space and comma
null :=
space := $(null) $(null)
Expand Down
5 changes: 3 additions & 2 deletions Makefile.maker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ controllerGen:

coverageTest:
only: "/internal"
except: "/internal/provider/openconfig"
except: "/internal/provider/openconfig|internal/provider/cisco/nxos/genyang"

dockerfile:
enabled: false
Expand All @@ -28,6 +28,7 @@ golangciLint:
createConfig: true
skipDirs:
- internal/provider/openconfig
- internal/provider/cisco/nxos/genyang
timeout: 10m

goReleaser:
Expand Down Expand Up @@ -80,7 +81,7 @@ verbatim: |

fmt: FORCE install-gofumpt
@printf "\e[1;36m>> gofumpt -l -w .\e[0m\n"
@gofumpt -l -w $(shell git ls-files '*.go' | grep -v '^internal/provider/openconfig')
@gofumpt -l -w $(shell git ls-files '*.go' | grep -v '^internal/provider/openconfig|internal/provider/cisco/nxos/genyang')

# Run the e2e tests against a k8s cluster.
test-e2e: FORCE
Expand Down
4 changes: 3 additions & 1 deletion Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ analytics_settings(False)
allow_k8s_contexts(['minikube', 'kind-network'])

docker_build('controller:latest', '.', ignore=['*/*/zz_generated.deepcopy.go', 'config/crd/bases/*'], only=[
'api/', 'cmd/', 'hack/', 'internal/', 'go.mod', 'go.sum', 'Makefile',
'api/', 'cmd/', 'hack/', 'internal/', 'go.mod', 'go.sum', 'Makefile', 'vendor/', ".force-rebuild"
])

local_resource('controller-gen', 'make generate', ignore=['*/*/zz_generated.deepcopy.go', 'config/crd/bases/*'], deps=[
Expand All @@ -25,6 +25,8 @@ k8s_resource(new_name='lo1', objects=['lo1:interface'], trigger_mode=TRIGGER_MOD
k8s_resource(new_name='eth1-1', objects=['eth1-1:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
k8s_resource(new_name='eth1-2', objects=['eth1-2:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
k8s_resource(new_name='eth1-10', objects=['eth1-10:interface'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)
k8s_yaml('./config/samples/v1alpha1_igp.yaml')
k8s_resource(new_name='underlay-isis-area-0', objects=['underlay-isis-area-0:igp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False)

print('🚀 network-operator development environment')
print('👉 Edit the code inside the api/, cmd/, or internal/ directories')
Expand Down
94 changes: 94 additions & 0 deletions api/v1alpha1/igp_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +kubebuilder:validation:Enum=isis
type IGPType string

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=igps
// +kubebuilder:resource:singular=igp
// +kubebuilder:resource:shortName=igp
// +kubebuilder:printcolumn:name="Process name",type=string,JSONPath=`.spec.name`

// IGP is the Schema for the igp API.
type IGP struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// Specification of the desired state of the resource.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
Spec IGPSpec `json:"spec"`

// Status of the resource. This is set and updated automatically.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
Status IGPStatus `json:"status"`
}

// IGProcessSpec defines the desired state of Interior Gateway Protocol (IGP) process on a device.
type IGPSpec struct {
// The name of the routing instance.
//+kubebuilder:validation:Required
Name string `json:"name"`
//+kubebuilder:validation:Optional
ISIS *ISISSpec `json:"isis,omitempty"`
}

// IGPStatus defines the observed state of an IGP process.
type IGPStatus struct {
// The conditions are a list of status objects that describe the state of the Interface.
//+listType=map
//+listMapKey=type
//+patchStrategy=merge
//+patchMergeKey=type
//+optional
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}

// +kubebuilder:object:root=true

// IGPList contains a list of IGP (processes).
type IGPList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []IGP `json:"items"`
}

// +kubebuilder:validation:Enum=Level1;Level2;Level12
type ISISLevel string

// +kubebuilder:validation:Enum=v4-unicast;v6-unicast
type ISISAF string

type ISISSpec struct {
// The Network Entity Title (NET) for the ISIS instance.
//+kubebuilder:validation:Required
NET string `json:"net"`
// The is-type of the process (the level)
//+kubebuilder:validation:Required
Level ISISLevel `json:"level"`
// Overload bit configuration for this ISIS instance
//+kubebuilder:validation:Optional
OverloadBit *OverloadBit `json:"overloadBit"`
//+kubebuilder:validation:Optional
AddressFamilies []ISISAF `json:"addressFamilies,omitempty"`
}

type OverloadBit struct {
// Duration of the OverloadBit in seconds.
//+kubebuilder:validation:Required
//+kubebuilder:validation:Minimum=576
//+kubebuilder:validation:Maximum=86400
OnStartup uint32 `json:"onStartup"`
}

func init() {
SchemeBuilder.Register(&IGP{}, &IGPList{})
}
141 changes: 141 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 20 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook"

// Import all supported provider implementations.
_ "github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos"
_ "github.com/ironcore-dev/network-operator/internal/provider/openconfig"

"github.com/ironcore-dev/network-operator/api/v1alpha1"
Expand Down Expand Up @@ -79,8 +80,8 @@ func main() {
flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.")
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers")
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))
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(), ", "))
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))
flag.StringVar(&providerName, "provider", "openconfig", "The provider to use for the controllers. If not specified, the default provider is used. Available providers: "+strings.Join(provider.Providers(), ", "))
opts := zap.Options{
Development: true,
TimeEncoder: zapcore.ISO8601TimeEncoder,
Expand Down Expand Up @@ -220,6 +221,23 @@ func main() {
os.Exit(1)
}

prov, err = provider.Get("cisco-nxos-gnmi")
if err != nil {
setupLog.Error(err, "failed to get provider", "provider", providerName)
os.Exit(1)
}

if err = (&controller.IGPReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("igp-controller"),
WatchFilterValue: watchFilterValue,
Provider: prov,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "IGP")
os.Exit(1)
}

// +kubebuilder:scaffold:builder

if metricsCertWatcher != nil {
Expand Down
Loading