Skip to content

Add internal/apistatus package with typed terminal errors#325

Merged
felix-kaestner merged 4 commits into
mainfrom
feat/unsupported-fields
May 21, 2026
Merged

Add internal/apistatus package with typed terminal errors#325
felix-kaestner merged 4 commits into
mainfrom
feat/unsupported-fields

Conversation

@felix-kaestner
Copy link
Copy Markdown
Contributor

@felix-kaestner felix-kaestner commented Apr 27, 2026

Introduces internal/apistatus, a package that gives provider implementations a structured way to return non-retryable errors to controllers without coupling directly to reconcile.TerminalError.

The package defines a Code enum (CodeInvalidArgument, CodeUnsupportedField, CodeFailedPrecondition) with String() and Valid() methods, a StatusError struct carrying a Code, an optional Message, and optional FieldViolations, and constructor functions for each code. StatusError implements Is() so that errors.Is can be used for type detection across error chains. WrapTerminalError wraps any error containing a *StatusError as a reconcile.TerminalError, leaving all other errors unchanged.

conditions.FromError is extended to detect *StatusError before the existing gRPC status path, mapping the code to the condition Reason and the formatted message to the condition Message field.

The stub internal/controllerutil package, which this supersedes, has been removed as no code imported it.

@felix-kaestner felix-kaestner requested a review from a team as a code owner April 27, 2026 07:57
@felix-kaestner felix-kaestner changed the title Add internal/apistatus package with typed terminal errors Add internal/apistatus package with typed terminal errors Apr 27, 2026
@hardikdr hardikdr added the area/switch-automation Automation processes for network switch management and operations. label Apr 28, 2026
@hardikdr hardikdr added this to Roadmap Apr 28, 2026
@felix-kaestner felix-kaestner force-pushed the feat/unsupported-fields branch 4 times, most recently from 9d34c07 to f7c97e3 Compare May 11, 2026 08:26
@felix-kaestner felix-kaestner force-pushed the feat/unsupported-fields branch from f7c97e3 to 74b89da Compare May 11, 2026 09:08
Comment thread internal/apistatus/apistatus.go Outdated
Comment thread internal/apistatus/apistatus.go
Comment thread internal/apistatus/apistatus.go
@felix-kaestner felix-kaestner force-pushed the feat/unsupported-fields branch from 74b89da to 6472af5 Compare May 18, 2026 08:47
@felix-kaestner felix-kaestner force-pushed the feat/unsupported-fields branch from 6472af5 to f87cad7 Compare May 18, 2026 09:07
Introduces internal/apistatus, a leaf package that gives provider
implementations a structured way to return non-retryable errors to
controllers without coupling directly to reconcile.TerminalError.

The package defines a Code enum (CodeInvalidArgument, CodeUnsupportedField,
CodeFailedPrecondition) with String() and Valid() methods, a StatusError
struct carrying a Code, an optional Message, and optional FieldViolations,
and constructor functions for each code. StatusError implements Is() so
that errors.Is can be used for type detection across error chains.
WrapTerminalError wraps any error containing a *StatusError as a
reconcile.TerminalError, leaving all other errors unchanged.

conditions.FromError is extended to detect *StatusError before the
existing gRPC status path, mapping the code to the condition Reason
and the formatted message to the condition Message field.

The stub internal/controllerutil package, which this supersedes, has
been removed as no code imported it.

Signed-off-by: Felix Kästner <felix.kaestner@sap.com>
Each controller's Reconcile method now passes provider errors through
apistatus.WrapTerminalError before returning them to controller-runtime.

This ensures that any *StatusError returned by a provider implementation
— signalling an unsupported field, an invalid argument, or an unmet
precondition — suppresses retry backoff and is treated as a terminal
error by the reconciler. Transient errors and Kubernetes-level
precondition failures are returned unchanged, preserving existing
retry behaviour for those cases.

Signed-off-by: Felix Kästner <felix.kaestner@sap.com>
Replace plain fmt.Errorf/errors.New calls in the NX-OS provider and
name.go with typed apistatus errors so non-retryable failures surface
as structured Kubernetes status conditions with a stable Reason field.

Signed-off-by: Felix Kästner <felix.kaestner@sap.com>
WrapTerminalError now only promotes CodeInvalidArgument and
CodeUnsupportedField to reconcile.TerminalError. CodeFailedPrecondition
errors pass through unchanged so controller-runtime exponential backoff
can requeue them — the precondition (e.g. a BGP process) may become
true on a future attempt.

Update docs and tests to reflect the new behaviour.

Signed-off-by: Felix Kästner <felix.kaestner@sap.com>
@felix-kaestner felix-kaestner force-pushed the feat/unsupported-fields branch from f87cad7 to 7c61fc3 Compare May 20, 2026 12:19
@github-actions
Copy link
Copy Markdown

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

Impacted Packages Coverage Δ 🤖
github.com/ironcore-dev/network-operator/internal/apistatus 96.30% (+96.30%) 🌟
github.com/ironcore-dev/network-operator/internal/conditions 75.38% (-4.94%) 👎
github.com/ironcore-dev/network-operator/internal/controller/cisco/nx 64.87% (-0.18%) 👎
github.com/ironcore-dev/network-operator/internal/controller/core 62.48% (-0.06%) 👎
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos 9.95% (ø)

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/ironcore-dev/network-operator/internal/apistatus/apistatus.go 96.30% (+96.30%) 27 (+27) 26 (+26) 1 (+1) 🌟
github.com/ironcore-dev/network-operator/internal/conditions/conditions.go 75.38% (-4.94%) 65 (+4) 49 16 (+4) 👎
github.com/ironcore-dev/network-operator/internal/controller/cisco/nx/bordergateway_controller.go 52.54% (-0.42%) 236 124 (-1) 112 (+1) 👎
github.com/ironcore-dev/network-operator/internal/controller/cisco/nx/system_controller.go 65.52% (ø) 116 76 40
github.com/ironcore-dev/network-operator/internal/controller/cisco/nx/vpcdomain_controller.go 78.64% (ø) 206 162 44
github.com/ironcore-dev/network-operator/internal/controller/core/acl_controller.go 58.16% (ø) 141 82 59
github.com/ironcore-dev/network-operator/internal/controller/core/banner_controller.go 57.99% (ø) 169 98 71
github.com/ironcore-dev/network-operator/internal/controller/core/bgp_controller.go 68.53% (ø) 232 159 73
github.com/ironcore-dev/network-operator/internal/controller/core/bgp_peer_controller.go 57.01% (ø) 314 179 135
github.com/ironcore-dev/network-operator/internal/controller/core/certificate_controller.go 58.71% (ø) 155 91 64
github.com/ironcore-dev/network-operator/internal/controller/core/dhcprelay_controller.go 65.89% (ø) 258 170 88
github.com/ironcore-dev/network-operator/internal/controller/core/dns_controller.go 57.97% (ø) 138 80 58
github.com/ironcore-dev/network-operator/internal/controller/core/evpninstance_controller.go 66.35% (ø) 208 138 70
github.com/ironcore-dev/network-operator/internal/controller/core/interface_controller.go 65.88% (ø) 551 363 188
github.com/ironcore-dev/network-operator/internal/controller/core/isis_controller.go 60.12% (ø) 173 104 69
github.com/ironcore-dev/network-operator/internal/controller/core/lldp_controller.go 69.59% (ø) 217 151 66
github.com/ironcore-dev/network-operator/internal/controller/core/managementaccess_controller.go 57.97% (ø) 138 80 58
github.com/ironcore-dev/network-operator/internal/controller/core/ntp_controller.go 57.97% (ø) 138 80 58
github.com/ironcore-dev/network-operator/internal/controller/core/nve_controller.go 67.59% (-0.46%) 216 146 (-1) 70 (+1) 👎
github.com/ironcore-dev/network-operator/internal/controller/core/ospf_controller.go 59.80% (ø) 204 122 82
github.com/ironcore-dev/network-operator/internal/controller/core/pim_controller.go 60.12% (ø) 173 104 69
github.com/ironcore-dev/network-operator/internal/controller/core/prefixset_controller.go 61.70% (ø) 141 87 54
github.com/ironcore-dev/network-operator/internal/controller/core/routingpolicy_controller.go 67.54% (ø) 191 129 62
github.com/ironcore-dev/network-operator/internal/controller/core/snmp_controller.go 57.97% (ø) 138 80 58
github.com/ironcore-dev/network-operator/internal/controller/core/syslog_controller.go 58.16% (ø) 141 82 59
github.com/ironcore-dev/network-operator/internal/controller/core/user_controller.go 56.80% (-1.18%) 169 96 (-2) 73 (+2) 👎
github.com/ironcore-dev/network-operator/internal/controller/core/vlan_controller.go 62.00% (ø) 150 93 57
github.com/ironcore-dev/network-operator/internal/controller/core/vrf_controller.go 62.32% (ø) 138 86 52
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/name.go 61.54% (ø) 26 16 10
github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/provider.go 0.06% (ø) 1779 1 1778

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/apistatus/apistatus_test.go

Copy link
Copy Markdown
Contributor

@sven-rosenzweig sven-rosenzweig left a comment

Choose a reason for hiding this comment

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

Happy to use this package also for IOS XR. Thanks for that :).

@felix-kaestner felix-kaestner merged commit 74a86ad into main May 21, 2026
20 checks passed
@github-project-automation github-project-automation Bot moved this to Done in Roadmap May 21, 2026
@felix-kaestner felix-kaestner deleted the feat/unsupported-fields branch May 21, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/switch-automation Automation processes for network switch management and operations. size/L

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants