Skip to content

feat: Static Route Controller - #435

Open
sven-rosenzweig wants to merge 1 commit into
mainfrom
feat/static_routes
Open

feat: Static Route Controller#435
sven-rosenzweig wants to merge 1 commit into
mainfrom
feat/static_routes

Conversation

@sven-rosenzweig

Copy link
Copy Markdown
Contributor

Implement IOS-XR provider.

@github-actions github-actions Bot added the size/L label Jul 7, 2026
@github-actions github-actions Bot added size/XXL and removed size/L labels Jul 7, 2026
@sven-rosenzweig
sven-rosenzweig force-pushed the feat/static_routes branch 2 times, most recently from 9a2e31b to 8545345 Compare July 7, 2026 16:54
Implement IOS-XR provider.

Signed-off-by: Sven Rosenzweig <sven.rosenzweig@sap.com>
@sven-rosenzweig
sven-rosenzweig marked this pull request as ready for review July 22, 2026 12:41
@github-actions

Copy link
Copy Markdown

Merging this branch changes the coverage (1 decrease, 1 increase)

Impacted Packages Coverage Δ 🤖
github.com/ironcore-dev/network-operator/api/core/v1alpha1 0.00% (ø)
github.com/ironcore-dev/network-operator/cmd 0.00% (ø)
github.com/ironcore-dev/network-operator/internal/controller/core 62.32% (+0.30%) 👍
github.com/ironcore-dev/network-operator/internal/provider 52.00% (ø)
github.com/ironcore-dev/network-operator/internal/provider/cisco/iosxr 32.54% (-3.53%) 👎
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos 9.25% (-0.01%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/ironcore-dev/network-operator/api/core/v1alpha1/groupversion_info.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/api/core/v1alpha1/staticroute_types.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/api/core/v1alpha1/zz_generated.deepcopy.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/cmd/main.go 0.00% (ø) 0 0 0
github.com/ironcore-dev/network-operator/internal/controller/core/interface_controller.go 72.34% (-0.17%) 582 421 (-1) 161 (+1) 👎
github.com/ironcore-dev/network-operator/internal/controller/core/staticroute_controller.go 70.94% (+70.94%) 203 (+203) 144 (+144) 59 (+59) 🌟
github.com/ironcore-dev/network-operator/internal/controller/core/vrf_controller.go 62.14% (-0.18%) 140 (+2) 87 (+1) 53 (+1) 👎
github.com/ironcore-dev/network-operator/internal/provider/cisco/iosxr/provider.go 20.43% (-2.27%) 230 (+23) 47 183 (+23) 👎
github.com/ironcore-dev/network-operator/internal/provider/cisco/iosxr/static_route.go 0.00% (ø) 14 (+14) 0 14 (+14)
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/provider.go 0.05% (-0.00%) 2036 (+2) 1 2035 (+2) 👎
github.com/ironcore-dev/network-operator/internal/provider/provider.go 52.00% (ø) 25 13 12

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/ironcore-dev/network-operator/internal/controller/core/staticroute_controller_test.go
  • github.com/ironcore-dev/network-operator/internal/controller/core/suite_test.go

@felix-kaestner felix-kaestner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice stuff! 🚀


// StaticRouteLabel is a label applied to VRFs to indicate
// the name of the StaticRoute that references them.
const StaticRouteLabel = "networking.metal.ironcore.dev/static-route-name"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will this work when there are multiple StaticRoutes in a VRF? Based on the way we structure the StaticRoute CRD this would be possible, no?

// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Name is immutable"
Name string `json:"name"`

// +optional

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have a very brief comment, as all other fields.


// StaticRouteStatus defines the observed state of StaticRoute.
type StaticRouteStatus struct {
// The conditions are a list of status objects that describe the state of the Interface.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The conditions are a list of status objects that describe the state of the Interface.
// The conditions are a list of status objects that describe the state of the StaticRoute.

copy+pasta


// IPPrefix is the destination IP prefix for the static route.
// +required
Prefix IPPrefix `json:"prefix,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Prefix IPPrefix `json:"prefix,omitempty"`
Prefix IPPrefix `json:"prefix"`

omitempty is unused if the field is required. Also applies to the NextHops.

name: networking-staticroute-admin-role
rules:
- apiGroups:
- networking.networking.metal.ironcore.dev

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- networking.networking.metal.ironcore.dev
- networking.metal.ironcore.dev

This is wrong. Probably a grep over the codebase reveals other places that are also effected.

Comment on lines +609 to +614
if req.VRF != nil && req.VRF.Spec.Name != "" {
vrf := req.VRF.Spec.Name
prefix.VRFName = vrf
return p.client.Update(ctx, &prefix)
}
return p.client.Update(ctx, &prefix)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if req.VRF != nil && req.VRF.Spec.Name != "" {
vrf := req.VRF.Spec.Name
prefix.VRFName = vrf
return p.client.Update(ctx, &prefix)
}
return p.client.Update(ctx, &prefix)
if req.VRF != nil && req.VRF.Spec.Name != "" {
prefix.VRFName = req.VRF.Spec.Name
}
return p.client.Update(ctx, &prefix)

Doesn't need to make it so complicated.

Comment on lines +593 to +607
if prefixIP.Addr().Is4() {
prefix = Prefix{
PrefixAddress: prefixIP.Addr().String(),
PrefixLength: prefixIP.Bits(),
NextHopAddress: &nexthopAddress,
IsIpv4: true,
}
} else if prefixIP.Addr().Is6() {
prefix = Prefix{
PrefixAddress: prefixIP.Addr().String(),
PrefixLength: prefixIP.Bits(),
NextHopAddress: &nexthopAddress,
IsIpv4: false,
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if prefixIP.Addr().Is4() {
prefix = Prefix{
PrefixAddress: prefixIP.Addr().String(),
PrefixLength: prefixIP.Bits(),
NextHopAddress: &nexthopAddress,
IsIpv4: true,
}
} else if prefixIP.Addr().Is6() {
prefix = Prefix{
PrefixAddress: prefixIP.Addr().String(),
PrefixLength: prefixIP.Bits(),
NextHopAddress: &nexthopAddress,
IsIpv4: false,
}
}
prefix = Prefix{
PrefixAddress: prefixIP.Addr().String(),
PrefixLength: prefixIP.Bits(),
NextHopAddress: &nexthopAddress,
IsIpv4: prefixIP.Addr().Is4(),
}

Comment on lines +9 to +12
basePath := "Cisco-IOS-XR-um-router-static-cfg:router/static/vrfs/vrf[vrf-name=" + s.VRFName + "]/address-family/"
if s.VRFName == "" {
basePath = "Cisco-IOS-XR-um-router-static-cfg:router/static/address-family/"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
basePath := "Cisco-IOS-XR-um-router-static-cfg:router/static/vrfs/vrf[vrf-name=" + s.VRFName + "]/address-family/"
if s.VRFName == "" {
basePath = "Cisco-IOS-XR-um-router-static-cfg:router/static/address-family/"
}
basePath := "Cisco-IOS-XR-um-router-static-cfg:router/static/address-family/"
if s.VRFName != "" {
basePath = "Cisco-IOS-XR-um-router-static-cfg:router/static/vrfs/vrf[vrf-name=" + s.VRFName + "]/address-family/"
}

nit: the other way around feels more logical to me.

}

func (p *Provider) EnsureStaticRoute(ctx context.Context, req *provider.StaticRouteRequest) error {
// TODO(sven-rosenzweig): implement static route configuration

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an open Ticket for this? Otherwise I think leaving these methods out would be better, as the controller already checks if the provider implements this interface (which it now does, because it has these methods). Not having these functions means the controller sees that the provider doesn't implement the contract and correctly updates the kubernetes resource status.

Comment thread PROJECT
crdVersion: v1
namespaced: true
domain: networking.metal.ironcore.dev
group: core

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
group: core

not correct.

Watches(
&v1alpha1.VRF{},
handler.EnqueueRequestsFromMapFunc(r.vrfToStaticRoute),
builder.WithPredicates(predicate.Funcs{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to trigger reconcilation on updates to the vrf, as we are basically only interested in the .spec.name and that is immutable. So I would expect that we have a

			UpdateFunc: func(e event.UpdateEvent) bool {
				return false
			},

Comment on lines +322 to +329
ready := false
for _, cond := range resource.Status.Conditions {
if cond.Type == v1alpha1.ReadyCondition {
ready = true
g.Expect(cond.Status).To(Equal(metav1.ConditionFalse))
}
}
g.Expect(ready).To(BeTrue(), "ReadyCondition should be present")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to adhere to the same pattern for condition checks as in the other controller tests (e.g. to use the metav1.FindStatusCondition).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants