Skip to content

Bump k8s.io/* deps to v1.35#489

Draft
Rohit-0505 wants to merge 1 commit intoironcore-dev:mainfrom
opensovereigncloud:osc/feat/update-k8s-1.35
Draft

Bump k8s.io/* deps to v1.35#489
Rohit-0505 wants to merge 1 commit intoironcore-dev:mainfrom
opensovereigncloud:osc/feat/update-k8s-1.35

Conversation

@Rohit-0505
Copy link
Copy Markdown
Contributor

@Rohit-0505 Rohit-0505 commented Apr 23, 2026

Proposed Changes

Summary by CodeRabbit

Release Notes

  • Updates

    • Updated Kubernetes support from v1.34 to v1.35
    • Upgraded Go version requirement to 1.25.1
    • Bumped code generation and linting tool versions
  • New Features

    • Added OpenAPI model metadata for improved schema handling
  • Enhancements

    • Made port field optional in network policy rules for greater flexibility
    • Improved API documentation and field descriptions across core API types

@Rohit-0505 Rohit-0505 requested a review from a team as a code owner April 23, 2026 07:20
@Rohit-0505 Rohit-0505 marked this pull request as draft April 23, 2026 07:20
@github-actions github-actions Bot added size/XXL documentation Improvements or additions to documentation labels Apr 23, 2026
@hardikdr hardikdr added the area/networking Networking-related tasks and improvements. label Apr 23, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Updates Kubernetes API code generation, dependency management, and controller-manager logic: bumps Go tooling versions, upgrades Kubernetes dependencies to v0.35.3, refactors client-go extraction APIs with subresource support, migrates controllers to server-side apply configurations, adds OpenAPI model name generation, changes NetworkPolicyPort.Port to optional pointer type, and wraps informers with watch-list semantics.

Changes

Cohort / File(s) Summary
Tool and Dependency Management
Makefile, go.mod, hack/update-codegen.sh
Updates CONTROLLER_TOOLS_VERSION and GOIMPORTS_VERSION pins; upgrades Kubernetes dependencies from v0.34.x to v0.35.3 and Go directive to 1.25.1; refactors OpenAPI generation to use model name file output and explicit package mapping configuration.
API Types and Code Generation
api/core/v1alpha1/doc.go, api/core/v1alpha1/networkpolicy_types.go, api/core/v1alpha1/zz_generated.*, internal/apis/core/..., internal/controllers/...
Adds OpenAPI model name generation method for 83+ types; changes NetworkPolicyPort.Port from int32 to *int32; updates deep-copy logic; adds OpenAPI generator annotations; refactors conversion logic for network policy fields with explicit nil/slice handling instead of unsafe memory operations.
Client-go Apply Configuration Extraction API Refactoring
client-go/applyconfigurations/core/v1alpha1/{daemonset,instance,ip,ipaddress,ipblock,loadbalancer*,natgateway*,network*,node}.go
Systematically introduces generalized ExtractFrom functions with subresource parameter across 20+ apply-configuration types; refactors existing extractors to delegate to the new functions; removes "Experimental!" markers from documentation; updates internal schema extraction to use managedfields.ExtractInto.
Client-go Apply Configuration Documentation
client-go/applyconfigurations/core/v1alpha1/{*affinity*,*port,*selector,*ip*,*ref,*status,*spec}.go
Adds comprehensive GoDoc comments and field-level documentation to 30+ apply-configuration types describing semantics, constraints, and expected behavior; clarifies defaulting rules, optional field behavior, and list/union semantics.
Client-go Informer Watch-List Semantics
client-go/informers/externalversions/core/v1alpha1/{daemonset,instance,ip,ipaddress,loadbalancer*,natgateway*,nattable,network*,node}.go, client-go/ironcorenet/versioned/fake/clientset_generated.go
Wraps cache.ListWatch with cache.ToListWatcherWithWatchListSemantics(client) in 15+ informer constructors; adds IsWatchListSemanticsUnSupported method to fake clientset.
Client-go Internal Schema Updates
client-go/applyconfigurations/internal/internal.go
Significantly simplifies embedded schema YAML by replacing strongly-typed definitions for 40+ IronCore CRD types with generic scalar: untyped placeholders using __untyped_* named types.
Controller Application Pattern Migration
apinetlet/controllers/{loadbalancer,natgateway,network,networkpolicy}_controller.go, internal/controllers/{loadbalancer,natgateway,scheduler}_controller.go, metalnetlet/controllers/{metalnetnode,networkinterface}_controller.go
Migrates controller reconciliation from Patch(client.Apply) pattern to apply-configuration builders and Apply() calls; switches event recorder types from record.EventRecorder to events.EventRecorder; adds helper functions for port/IP block/object IP conversion in network policy controller.
Event Recorder Type Migrations
cmd/controller-manager/main.go, internal/controllers/controllers_suite_test.go
Updates event recorder acquisition from GetEventRecorderFor() to GetEventRecorder(); switches test suite fake recorders from record.FakeRecorder to events.FakeRecorder.
Test Suite Environment Updates
apinetlet/controllers/controllers_suite_test.go, internal/app/app_suite_test.go, metalnetlet/controllers/controllers_suite_test.go
Bumps BinaryAssetsDirectory Kubernetes version from 1.34.0 to 1.35.0 across three test suites.
Documentation Updates
docs/api-reference/core.md, hack/api-reference/config.json, client-go/informers/externalversions/factory.go
Updates Kubernetes cross-reference anchors from v1.34 to v1.35; adjusts internal documentation hyperlinks; updates example context usage in factory comments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is empty except for a placeholder section header, lacking any explanation of the changes, rationale, testing, or implementation details required by the template. Complete the description by listing proposed changes, explaining migration rationale, and noting any breaking changes or testing performed. Reference the related issue if applicable.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: bumping Kubernetes dependencies to v1.35 across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 94.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch osc/feat/update-k8s-1.35

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@hardikdr hardikdr added this to Roadmap Apr 23, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
docs/api-reference/core.md (1)

4053-4064: ⚠️ Potential issue | 🟡 Minor

Docs are stale w.r.t. the NetworkPolicyPort.Port type change.

The API now declares Port *int32 with omitempty (optional), but this reference doc still shows port as int32 without an (Optional) marker, and the description doesn't mention the "unset matches all ports" semantics that the Go comment now encodes. Please regenerate the API reference so optionality is reflected here (and similarly verify other entries derived from the updated types).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/api-reference/core.md` around lines 4053 - 4064, The docs entry for
NetworkPolicyPort.Port is stale: update the API reference generation so the
field reflects the new type Port *int32 with omitempty by marking the `port`
field as Optional (e.g., “int32 (Optional)”) and amend the description to state
that if the port is unset it matches all ports (e.g., “If this field is not
provided, this matches all port names and numbers; if present, only traffic on
the specified protocol AND port will be matched.”); regenerate the reference for
NetworkPolicyPort.Port and similarly re-run the doc generation for other entries
derived from updated Go types to ensure optional fields are annotated
consistently.
client-go/applyconfigurations/core/v1alpha1/loadbalancerrouting.go (1)

38-71: ⚠️ Potential issue | 🟠 Major

Restore ExtractLoadBalancerRoutingStatus to maintain API backward compatibility.

The exported ExtractLoadBalancerRoutingStatus function that existed on main has been removed, breaking downstream callers. Add it back as a thin wrapper to ExtractLoadBalancerRoutingFrom(..., "status").

Required wrapper
 func ExtractLoadBalancerRouting(loadBalancerRouting *corev1alpha1.LoadBalancerRouting, fieldManager string) (*LoadBalancerRoutingApplyConfiguration, error) {
 	return ExtractLoadBalancerRoutingFrom(loadBalancerRouting, fieldManager, "")
 }
+
+// ExtractLoadBalancerRoutingStatus extracts the applied configuration owned by fieldManager from
+// loadBalancerRouting for the status subresource.
+func ExtractLoadBalancerRoutingStatus(loadBalancerRouting *corev1alpha1.LoadBalancerRouting, fieldManager string) (*LoadBalancerRoutingApplyConfiguration, error) {
+	return ExtractLoadBalancerRoutingFrom(loadBalancerRouting, fieldManager, "status")
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client-go/applyconfigurations/core/v1alpha1/loadbalancerrouting.go` around
lines 38 - 71, A exported wrapper function ExtractLoadBalancerRoutingStatus was
removed and must be restored to keep API compatibility; add back a function
named ExtractLoadBalancerRoutingStatus with signature matching
ExtractLoadBalancerRouting (i.e., func
ExtractLoadBalancerRoutingStatus(loadBalancerRouting
*corev1alpha1.LoadBalancerRouting, fieldManager string)
(*LoadBalancerRoutingApplyConfiguration, error)) that simply calls and returns
ExtractLoadBalancerRoutingFrom(loadBalancerRouting, fieldManager, "status");
place it alongside the other extractor functions so callers expecting this
symbol compile again.
client-go/applyconfigurations/core/v1alpha1/nattable.go (1)

39-72: ⚠️ Potential issue | 🟠 Major

Add back ExtractNATTableStatus as a compatibility wrapper.

Removing the exported ExtractNATTableStatus function is a source-breaking public API change. Callers cannot migrate silently; they face a compile-time error. To maintain backward compatibility while preserving the new architecture, restore it as a wrapper delegating to ExtractNATTableFrom(..., "status"):

 func ExtractNATTable(nATTable *corev1alpha1.NATTable, fieldManager string) (*NATTableApplyConfiguration, error) {
 	return ExtractNATTableFrom(nATTable, fieldManager, "")
 }
+
+// ExtractNATTableStatus extracts the applied configuration owned by fieldManager from
+// nATTable for the status subresource.
+func ExtractNATTableStatus(nATTable *corev1alpha1.NATTable, fieldManager string) (*NATTableApplyConfiguration, error) {
+	return ExtractNATTableFrom(nATTable, fieldManager, "status")
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client-go/applyconfigurations/core/v1alpha1/nattable.go` around lines 39 -
72, Restore the exported compatibility wrapper ExtractNATTableStatus to avoid a
breaking API change: add a new function ExtractNATTableStatus(nATTable
*corev1alpha1.NATTable, fieldManager string) (*NATTableApplyConfiguration,
error) that simply calls and returns ExtractNATTableFrom(nATTable, fieldManager,
"status"); place it alongside ExtractNATTable and ExtractNATTableFrom so callers
can continue using ExtractNATTableStatus while the implementation delegates to
the new ExtractNATTableFrom(..., "status").
cmd/controller-manager/main.go (1)

208-249: ⚠️ Potential issue | 🔴 Critical

Add events.k8s.io RBAC permissions to controller-manager role.

The manager-role in config/controller/rbac/role.yaml is missing event permissions entirely. The reconcilers initializing EventRecorder via GetEventRecorder() at lines 208 and 249 require RBAC permissions to create/patch events. After migration to controller-runtime v0.23, GetEventRecorder() returns an events.EventRecorder that writes to the events.k8s.io API group, not the core group. Add the following rule to config/controller/rbac/role.yaml:

- apiGroups:
  - events.k8s.io
  resources:
  - events
  verbs:
  - create
  - patch

Otherwise, event emission from NATGatewayReconciler, SchedulerReconciler, and other reconcilers will fail at runtime with permission denied errors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/controller-manager/main.go` around lines 208 - 249, The controller
managers use EventRecorder (via mgr.GetEventRecorder()) in reconcilers like
controllers.NATGatewayReconciler and controllers.SchedulerReconciler which now
emit events to the events.k8s.io API group; update the controller-manager RBAC
role (config/controller/rbac/role.yaml) to grant create and patch permissions
for the events resource in the events.k8s.io apiGroup so these reconcilers can
successfully create/patch Kubernetes events at runtime.
apinetlet/controllers/network_controller.go (1)

153-160: ⚠️ Potential issue | 🔴 Critical

Guard the pending-status update when apply returns no APINet network.

applyAPINetNetwork returns nil, err on apply/get failures, but the error path passes that nil into updateNetworkStatus, which dereferences apiNetNetwork.Status and can panic instead of requeueing.

🐛 Proposed fix
 	apiNetNetwork, err := r.applyAPINetNetwork(ctx, log, network)
 	if err != nil {
-		if network.Status.State != networkingv1alpha1.NetworkStateAvailable {
+		if apiNetNetwork != nil && network.Status.State != networkingv1alpha1.NetworkStateAvailable {
 			if err := r.updateNetworkStatus(ctx, log, network, apiNetNetwork, networkingv1alpha1.NetworkStatePending); err != nil {
 				log.Error(err, "Error updating network state")
 			}
+		} else if apiNetNetwork == nil && network.Status.State != networkingv1alpha1.NetworkStatePending {
+			networkBase := network.DeepCopy()
+			network.Status.State = networkingv1alpha1.NetworkStatePending
+			if err := r.Status().Patch(ctx, network, client.MergeFrom(networkBase)); err != nil {
+				log.Error(err, "Error updating network state")
+			}
 		}
 		return ctrl.Result{}, fmt.Errorf("error applying APINet network: %w", err)
 	}

Also applies to: 257-265

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apinetlet/controllers/network_controller.go` around lines 153 - 160, The
error path calls updateNetworkStatus with apiNetNetwork which can be nil when
applyAPINetNetwork returned (nil, err); guard that call by checking
apiNetNetwork != nil before accessing its Status (i.e., only call
updateNetworkStatus(apiNetNetwork, ...) when apiNetNetwork is non-nil), and for
the nil case either skip the update or invoke updateNetworkStatus with a safe
default/zeroed APINetNetwork that does not require dereferencing Status; apply
the same nil-check pattern for the other occurrence (the block around lines that
reference applyAPINetNetwork and updateNetworkStatus later in the file).
🧹 Nitpick comments (2)
go.mod (1)

11-13: Consider tagging ironcore-dev deps to a release before merging.

The three github.com/ironcore-dev/* deps are pinned to pseudo-versions (commit SHAs from April 2026). If tagged releases corresponding to the k8s v1.35 bump exist (or are planned), prefer those for reproducibility and downstream consumability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@go.mod` around lines 11 - 13, The go.mod currently pins
github.com/ironcore-dev/controller-utils, github.com/ironcore-dev/ironcore, and
github.com/ironcore-dev/metalnet to pseudo-versions (commit SHAs); update those
module lines to use corresponding released semver tags (e.g., vX.Y.Z) if
available for the k8s v1.35 bump to improve reproducibility. Edit the entries
for github.com/ironcore-dev/controller-utils, github.com/ironcore-dev/ironcore,
and github.com/ironcore-dev/metalnet to the proper release tags and then run
module resolution (go get <module>@<tag> and go mod tidy) to ensure the go.sum
and dependency graph are consistent. Ensure the chosen tags are compatible with
the k8s v1.35 changes and CI builds.
internal/controllers/natgateway_controller.go (1)

362-366: Minor: collapse the section/IP append loops into variadic calls.

WithSections/WithIPs are variadic, so the intermediate for loops can be replaced with spread for clarity.

♻️ Proposed refactor
-		natIPConf := corev1alpha1apply.NATIP().WithIP(ip)
-		for _, sectionConf := range sectionConfs {
-			natIPConf.WithSections(sectionConf)
-		}
-		natTableIPs = append(natTableIPs, natIPConf)
+		natTableIPs = append(natTableIPs, corev1alpha1apply.NATIP().WithIP(ip).WithSections(sectionConfs...))
@@
-	for _, natIPConf := range natTableIPs {
-		natTableApplyConfig.WithIPs(natIPConf)
-	}
+	natTableApplyConfig.WithIPs(natTableIPs...)

Also applies to: 382-385

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controllers/natgateway_controller.go` around lines 362 - 366, The
code uses explicit loops to add sections and IPs to NATIP and NATTable entries
though WithSections and WithIPs are variadic; replace the per-item for-loops by
passing the whole slice via variadic expansion (e.g., call
corev1alpha1apply.NATIP().WithIP(ip).WithSections(sectionConfs...) and similarly
use WithIPs(someSlice...) when building natTableIPs) so you remove the
intermediate loops and directly append the configured object to natTableIPs
(refer to natIPConf, corev1alpha1apply.NATIP(), WithSections, WithIPs, and
natTableIPs).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/core/v1alpha1/doc.go`:
- Around line 4-7: The file api/core/v1alpha1/zz_generated.defaults.go is a
stale autogenerated artifact (its RegisterDefaults function is empty and not
referenced) left after removing +k8s:defaulter-gen; delete
zz_generated.defaults.go and any references/imports to it, remove or update any
build tags or go:generate lines that expect a defaulter in the api/core/v1alpha1
package, and ensure there are no remaining usages of RegisterDefaults so
compilation and imports remain clean.

In `@api/core/v1alpha1/networkpolicy_types.go`:
- Line 40: The public API NetworkPolicyPort.Port was changed from int32 to
*int32 which breaks callers that take the address of an int field; update the
affected conversion at the site that sets `Port: &port.Port` (in
apinetlet/controllers/conversion.go) to create a proper *int32 from the external
value (e.g. capture the int32 into a local variable `p := port.Port` then use
`Port: &p` or use your pointer helper like `Port: generic.Pointer(port.Port)`),
and scan the repo for other direct `&...Port` usages to similarly convert to a
*int32; ensure nil-checks where appropriate.

In `@apinetlet/controllers/networkpolicy_controller.go`:
- Around line 419-428: The code dereferences apiNetNetworkPolicy.Spec.Priority
unconditionally when calling WithPriority, which can cause an NPE if the pointer
is nil; change the construction of networkPolicyRuleApplyCfg to only call
WithPriority when apiNetNetworkPolicy.Spec.Priority is non-nil (e.g., check if p
:= apiNetNetworkPolicy.Spec.Priority; p != nil then chain .WithPriority(*p)),
leaving all other chained calls (WithLabels, WithNetworkRef, WithTargets,
WithIngressRules, WithEgressRules, WithOwnerReferences) intact so the cfg is
built defensively.

In `@client-go/applyconfigurations/core/v1alpha1/loadbalancerspec.go`:
- Line 26: The comment on the Selector field of LoadBalancerSpec is incorrect
and misleading; update the Selector comment in type LoadBalancerSpec to reflect
load balancer context and pluralize "Instance" (e.g., "Selector selects all
Instances that are targeted/associated with this LoadBalancer" or similar),
ensuring the comment references LoadBalancer rather than "daemon set" and uses
correct pluralization for Instance/Instances.

In `@client-go/applyconfigurations/core/v1alpha1/networkpolicy.go`:
- Around line 62-64: The generated Godoc comment in networkpolicy.go is awkward
and duplicates wording (e.g., "no managed fields were found for because other
field managers..." and "never owned fields any fields"); edit the public comment
that begins with "APIVersion and Kind populated." to remove the duplicated words
and fix grammar so it reads clearly (e.g., "It is possible that no managed
fields were found because other field managers have taken ownership, or because
the fieldManager never owned any fields. APIVersion and Kind are populated.").
Ensure you update the comment associated with the generated extractor in
networkpolicy.go so the public documentation is concise and grammatically
correct.
- Around line 69-70: Add a deprecated compatibility wrapper named
ExtractNetworkPolicyStatus that preserves the original public API and simply
delegates to the new generic helper ExtractNetworkPolicyFrom: implement a
function ExtractNetworkPolicyStatus(networkPolicy *corev1alpha1.NetworkPolicy,
fieldManager string) (*NetworkPolicyApplyConfiguration, error) which calls and
returns ExtractNetworkPolicyFrom(networkPolicy, fieldManager, "status"); include
a deprecation comment on ExtractNetworkPolicyStatus to indicate it forwards to
ExtractNetworkPolicyFrom and must be kept for source compatibility.

In `@client-go/applyconfigurations/core/v1alpha1/topologyspreadconstraint.go`:
- Around line 32-33: Fix the grammatical typo in the WhenUnsatisfiable field
comment: change "a instance" to "an instance" in the comment for
WhenUnsatisfiable in topologyspreadconstraint.go (the documentation directly
above the WhenUnsatisfiable field in the TopologySpreadConstraint
apply-configuration type).

In `@client-go/applyconfigurations/internal/internal.go`:
- Around line 29-178: The generated internal schema lists many resources (e.g.,
DaemonSet, IP, Instance, Network, Node, etc.) as scalar: untyped which breaks
field-level managed-fields extraction used by the Extract*From helpers that call
internal.Parser().Type(...); regenerate
client-go/applyconfigurations/internal/internal.go using applyconfiguration-gen
from the corrected OpenAPI definitions so each resource has full field schema
(not scalar: untyped), then re-run codegen so Extract*From functions reference
the proper parsed types; finally, add extraction regression tests that exercise
Extract<Kind>From for several concrete resources to ensure field ownership and
managed-fields metadata are preserved.

In `@docs/api-reference/core.md`:
- Around line 4243-4244: The API reference generator is emitting full
import-path anchors for types like NetworkPeeringStatus from
github.com/ironcore-dev/ironcore-net/api/core/v1alpha1 because
hack/api-reference/config.json lacks a rule for api/ packages; add a new
typeMatchPrefix entry (regex ^github\.com/ironcore-dev/ironcore-net/api) to the
config.json rules so the generator treats nested api/ package types the same as
other domain-based packages and produces the proper domain-based anchor format
for types such as NetworkPeeringStatus.

In `@hack/update-codegen.sh`:
- Line 24: The script installs two EXIT traps so the later one overrides the
earlier rm -rf "$VIRTUAL_GOPATH" cleanup; fix by consolidating cleanup actions
into a single EXIT handler (e.g., define a cleanup function and call rm -rf
"$VIRTUAL_GOPATH" plus the other cleanup tasks inside it) and replace both
standalone trap '...' EXIT invocations with one trap that references that
cleanup function; ensure VIRTUAL_GOPATH is referenced in that consolidated
handler so the temporary GOPATH is always removed.

In `@internal/apis/core/doc.go`:
- Line 6: The openapi-model-package directive value is pointing to a
non-existent import path; update the directive value from
"com.github.ironcore-dev.ironcore-net.api.core.core" to the correct Go import
path "com.github.ironcore-dev.ironcore-net.internal.apis.core" in the doc.go
file (or remove the // +k8s:openapi-model-package line entirely) so generated
OpenAPI models reference the actual hub package used by your types (ensure you
modify the line containing the openapi-model-package directive).

In `@internal/controllers/loadbalancer_controller.go`:
- Around line 80-96: The DaemonSet constructor call is using the namespace as
the first argument and the name as the second; swap the arguments so
corev1alpha1apply.DaemonSet receives the generated name first (use
v1alpha1.LoadBalancerDaemonSetName(loadBalancer.Name) as the name) and
loadBalancer.Namespace as the second argument, and add WithController(true) to
the OwnerReference chain (the v1.OwnerReference() builder) so the created
OwnerReference marks the LoadBalancer as the controller for proper ownership and
reconciliation with .Owns(&v1alpha1.DaemonSet{}).

In `@internal/controllers/natgateway_controller.go`:
- Around line 323-328: The owner reference on the NATTable created in
NATTable(natGateway.Name, natGateway.Namespace) currently omits Controller and
BlockOwnerDeletion flags; update the OwnerReference builder (the
v1.OwnerReference() chain used when constructing natTableApplyConfig) to include
.WithController(true).WithBlockOwnerDeletion(true) so the NATTable has
Controller=true and BlockOwnerDeletion=true like other reconcilers—this restores
event routing for Owns(&v1alpha1.NATTable{}) and ensures proper cascading
deletion behavior.
- Around line 349-360: The comparator passed to slices.SortFunc for sectionConfs
(elements of type corev1alpha1apply.NATIPSectionApplyConfiguration) must
establish a total order when Port may be nil; change the lambda used in
slices.SortFunc so it treats nil consistently (e.g., consider nil > any non-nil
or nil < any non-nil), by first checking both nils (return 0), then handling
one-nil cases deterministically (return 1 or -1), and only then comparing
*a.Port and *b.Port; update the comparator used in slices.SortFunc to implement
this deterministic ordering so SortFunc receives a strict weak ordering.

In `@internal/controllers/scheduler_controller.go`:
- Around line 470-472: The Eventf call incorrectly puts the full message into
the action parameter and the instance name into the note; update the r.Eventf
invocation so action is a short verb like "SchedulingFailed" (or "Scheduling"),
note is a format string such as "No nodes available to schedule %s on", and pass
the namespaced key (namespace/name) of the instance as the argument to format
the note (use inst.Namespace and inst.Name) so the emitted event reads "No nodes
available to schedule <namespace/name> on" and follows EventRecorder semantics;
locate and change the call to r.Eventf in the scheduler controller where inst is
used.

In `@metalnetlet/controllers/metalnetnode_controller.go`:
- Line 137: The server-side apply call using r.Apply(ctx, nodeApplyCfg,
PartitionFieldOwner(r.PartitionName)) must include client.ForceOwnership so
pre-existing fields owned by other managers are taken over; update the call to
pass client.ForceOwnership alongside PartitionFieldOwner (e.g., r.Apply(ctx,
nodeApplyCfg, client.ForceOwnership, PartitionFieldOwner(r.PartitionName))) and
ensure the client symbol is available in scope; reference r.Apply, nodeApplyCfg,
PartitionFieldOwner, and client.ForceOwnership when making the change.

In `@metalnetlet/controllers/networkinterface_controller.go`:
- Around line 243-248: The switch that dereferences port.Protocol must be
guarded to avoid nil panic: wrap the existing switch that uses *port.Protocol
with an if port.Protocol != nil { switch *port.Protocol { ... } } else { treat
as the TCP branch (i.e., apply the same logic as the ProtocolTCP case) }; update
references inside the switch to use the same branch logic for TCP, UDP, SCTP as
before and ensure baseFirewallRule.ProtocolMatch is set consistently when
port.Protocol is nil by defaulting to TCP.

---

Outside diff comments:
In `@apinetlet/controllers/network_controller.go`:
- Around line 153-160: The error path calls updateNetworkStatus with
apiNetNetwork which can be nil when applyAPINetNetwork returned (nil, err);
guard that call by checking apiNetNetwork != nil before accessing its Status
(i.e., only call updateNetworkStatus(apiNetNetwork, ...) when apiNetNetwork is
non-nil), and for the nil case either skip the update or invoke
updateNetworkStatus with a safe default/zeroed APINetNetwork that does not
require dereferencing Status; apply the same nil-check pattern for the other
occurrence (the block around lines that reference applyAPINetNetwork and
updateNetworkStatus later in the file).

In `@client-go/applyconfigurations/core/v1alpha1/loadbalancerrouting.go`:
- Around line 38-71: A exported wrapper function
ExtractLoadBalancerRoutingStatus was removed and must be restored to keep API
compatibility; add back a function named ExtractLoadBalancerRoutingStatus with
signature matching ExtractLoadBalancerRouting (i.e., func
ExtractLoadBalancerRoutingStatus(loadBalancerRouting
*corev1alpha1.LoadBalancerRouting, fieldManager string)
(*LoadBalancerRoutingApplyConfiguration, error)) that simply calls and returns
ExtractLoadBalancerRoutingFrom(loadBalancerRouting, fieldManager, "status");
place it alongside the other extractor functions so callers expecting this
symbol compile again.

In `@client-go/applyconfigurations/core/v1alpha1/nattable.go`:
- Around line 39-72: Restore the exported compatibility wrapper
ExtractNATTableStatus to avoid a breaking API change: add a new function
ExtractNATTableStatus(nATTable *corev1alpha1.NATTable, fieldManager string)
(*NATTableApplyConfiguration, error) that simply calls and returns
ExtractNATTableFrom(nATTable, fieldManager, "status"); place it alongside
ExtractNATTable and ExtractNATTableFrom so callers can continue using
ExtractNATTableStatus while the implementation delegates to the new
ExtractNATTableFrom(..., "status").

In `@cmd/controller-manager/main.go`:
- Around line 208-249: The controller managers use EventRecorder (via
mgr.GetEventRecorder()) in reconcilers like controllers.NATGatewayReconciler and
controllers.SchedulerReconciler which now emit events to the events.k8s.io API
group; update the controller-manager RBAC role
(config/controller/rbac/role.yaml) to grant create and patch permissions for the
events resource in the events.k8s.io apiGroup so these reconcilers can
successfully create/patch Kubernetes events at runtime.

In `@docs/api-reference/core.md`:
- Around line 4053-4064: The docs entry for NetworkPolicyPort.Port is stale:
update the API reference generation so the field reflects the new type Port
*int32 with omitempty by marking the `port` field as Optional (e.g., “int32
(Optional)”) and amend the description to state that if the port is unset it
matches all ports (e.g., “If this field is not provided, this matches all port
names and numbers; if present, only traffic on the specified protocol AND port
will be matched.”); regenerate the reference for NetworkPolicyPort.Port and
similarly re-run the doc generation for other entries derived from updated Go
types to ensure optional fields are annotated consistently.

---

Nitpick comments:
In `@go.mod`:
- Around line 11-13: The go.mod currently pins
github.com/ironcore-dev/controller-utils, github.com/ironcore-dev/ironcore, and
github.com/ironcore-dev/metalnet to pseudo-versions (commit SHAs); update those
module lines to use corresponding released semver tags (e.g., vX.Y.Z) if
available for the k8s v1.35 bump to improve reproducibility. Edit the entries
for github.com/ironcore-dev/controller-utils, github.com/ironcore-dev/ironcore,
and github.com/ironcore-dev/metalnet to the proper release tags and then run
module resolution (go get <module>@<tag> and go mod tidy) to ensure the go.sum
and dependency graph are consistent. Ensure the chosen tags are compatible with
the k8s v1.35 changes and CI builds.

In `@internal/controllers/natgateway_controller.go`:
- Around line 362-366: The code uses explicit loops to add sections and IPs to
NATIP and NATTable entries though WithSections and WithIPs are variadic; replace
the per-item for-loops by passing the whole slice via variadic expansion (e.g.,
call corev1alpha1apply.NATIP().WithIP(ip).WithSections(sectionConfs...) and
similarly use WithIPs(someSlice...) when building natTableIPs) so you remove the
intermediate loops and directly append the configured object to natTableIPs
(refer to natIPConf, corev1alpha1apply.NATIP(), WithSections, WithIPs, and
natTableIPs).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 15be1f6f-9974-48d7-8755-9c3112430488

📥 Commits

Reviewing files that changed from the base of the PR and between 2229dae and 6f79e6e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (104)
  • Makefile
  • api/core/v1alpha1/doc.go
  • api/core/v1alpha1/networkpolicy_types.go
  • api/core/v1alpha1/zz_generated.deepcopy.go
  • api/core/v1alpha1/zz_generated.model_name.go
  • apinetlet/controllers/controllers_suite_test.go
  • apinetlet/controllers/loadbalancer_controller.go
  • apinetlet/controllers/natgateway_controller.go
  • apinetlet/controllers/network_controller.go
  • apinetlet/controllers/networkpolicy_controller.go
  • client-go/applyconfigurations/core/v1alpha1/daemonset.go
  • client-go/applyconfigurations/core/v1alpha1/daemonsetspec.go
  • client-go/applyconfigurations/core/v1alpha1/instance.go
  • client-go/applyconfigurations/core/v1alpha1/instanceaffinityterm.go
  • client-go/applyconfigurations/core/v1alpha1/instanceantiaffinity.go
  • client-go/applyconfigurations/core/v1alpha1/instancespec.go
  • client-go/applyconfigurations/core/v1alpha1/ip.go
  • client-go/applyconfigurations/core/v1alpha1/ipaddress.go
  • client-go/applyconfigurations/core/v1alpha1/ipblock.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancer.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerdestination.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerip.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerport.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerrouting.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerspec.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancerstatus.go
  • client-go/applyconfigurations/core/v1alpha1/loadbalancertargetref.go
  • client-go/applyconfigurations/core/v1alpha1/localuidreference.go
  • client-go/applyconfigurations/core/v1alpha1/natgateway.go
  • client-go/applyconfigurations/core/v1alpha1/natgatewayautoscaler.go
  • client-go/applyconfigurations/core/v1alpha1/natgatewayautoscalerspec.go
  • client-go/applyconfigurations/core/v1alpha1/natgatewayip.go
  • client-go/applyconfigurations/core/v1alpha1/natgatewayspec.go
  • client-go/applyconfigurations/core/v1alpha1/natgatewaystatus.go
  • client-go/applyconfigurations/core/v1alpha1/natip.go
  • client-go/applyconfigurations/core/v1alpha1/natipsection.go
  • client-go/applyconfigurations/core/v1alpha1/nattable.go
  • client-go/applyconfigurations/core/v1alpha1/nattableiptargetref.go
  • client-go/applyconfigurations/core/v1alpha1/network.go
  • client-go/applyconfigurations/core/v1alpha1/networkid.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterface.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterfacenat.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterfacenatclaimref.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterfacepublicip.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterfacespec.go
  • client-go/applyconfigurations/core/v1alpha1/networkinterfacestatus.go
  • client-go/applyconfigurations/core/v1alpha1/networkpeering.go
  • client-go/applyconfigurations/core/v1alpha1/networkpeeringstatus.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicy.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicyegressrule.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicyingressrule.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicypeer.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicyport.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicyrule.go
  • client-go/applyconfigurations/core/v1alpha1/networkpolicyspec.go
  • client-go/applyconfigurations/core/v1alpha1/networkspec.go
  • client-go/applyconfigurations/core/v1alpha1/networkstatus.go
  • client-go/applyconfigurations/core/v1alpha1/node.go
  • client-go/applyconfigurations/core/v1alpha1/nodeselector.go
  • client-go/applyconfigurations/core/v1alpha1/nodeselectorrequirement.go
  • client-go/applyconfigurations/core/v1alpha1/nodeselectorterm.go
  • client-go/applyconfigurations/core/v1alpha1/objectip.go
  • client-go/applyconfigurations/core/v1alpha1/objectselector.go
  • client-go/applyconfigurations/core/v1alpha1/pciaddress.go
  • client-go/applyconfigurations/core/v1alpha1/peeringprefix.go
  • client-go/applyconfigurations/core/v1alpha1/rule.go
  • client-go/applyconfigurations/core/v1alpha1/tapdevice.go
  • client-go/applyconfigurations/core/v1alpha1/targetnetworkinterface.go
  • client-go/applyconfigurations/core/v1alpha1/topologyspreadconstraint.go
  • client-go/applyconfigurations/internal/internal.go
  • client-go/informers/externalversions/core/v1alpha1/daemonset.go
  • client-go/informers/externalversions/core/v1alpha1/instance.go
  • client-go/informers/externalversions/core/v1alpha1/ip.go
  • client-go/informers/externalversions/core/v1alpha1/ipaddress.go
  • client-go/informers/externalversions/core/v1alpha1/loadbalancer.go
  • client-go/informers/externalversions/core/v1alpha1/loadbalancerrouting.go
  • client-go/informers/externalversions/core/v1alpha1/natgateway.go
  • client-go/informers/externalversions/core/v1alpha1/natgatewayautoscaler.go
  • client-go/informers/externalversions/core/v1alpha1/nattable.go
  • client-go/informers/externalversions/core/v1alpha1/network.go
  • client-go/informers/externalversions/core/v1alpha1/networkid.go
  • client-go/informers/externalversions/core/v1alpha1/networkinterface.go
  • client-go/informers/externalversions/core/v1alpha1/networkpolicy.go
  • client-go/informers/externalversions/core/v1alpha1/networkpolicyrule.go
  • client-go/informers/externalversions/core/v1alpha1/node.go
  • client-go/informers/externalversions/factory.go
  • client-go/ironcorenet/versioned/fake/clientset_generated.go
  • client-go/openapi/zz_generated.openapi.go
  • cmd/controller-manager/main.go
  • docs/api-reference/core.md
  • go.mod
  • hack/api-reference/config.json
  • hack/update-codegen.sh
  • internal/apis/core/doc.go
  • internal/apis/core/v1alpha1/zz_generated.conversion.go
  • internal/app/app_suite_test.go
  • internal/controllers/controllers_suite_test.go
  • internal/controllers/loadbalancer_controller.go
  • internal/controllers/natgateway_controller.go
  • internal/controllers/scheduler_controller.go
  • metalnetlet/controllers/controllers_suite_test.go
  • metalnetlet/controllers/metalnetnode_controller.go
  • metalnetlet/controllers/networkinterface_controller.go
  • metalnetlet/controllers/networkinterface_controller_test.go

Comment thread api/core/v1alpha1/doc.go
Comment on lines 4 to 7
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +k8s:protobuf-gen=package
// +k8s:openapi-model-package=com.github.ironcore-dev.ironcore-net.api.core.v1alpha1
// +groupName=core.apinet.ironcore.dev
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -t f 'zz_generated.defaults.go|generated.pb.go|generated.proto' api/core/v1alpha1
rg -nP 'defaulter-gen|go-to-protobuf|protobuf-gen' hack/ -g '!**/vendor/**'

Repository: ironcore-dev/ironcore-net

Length of output: 111


🏁 Script executed:

cat -n api/core/v1alpha1/zz_generated.defaults.go | head -30

Repository: ironcore-dev/ironcore-net

Length of output: 788


🏁 Script executed:

rg -n 'zz_generated|defaults\.' --type go api/core/v1alpha1/ | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

rg -rn 'from.*zz_generated\.defaults|import.*defaults' . --type go | grep -v vendor | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 51


Delete the stale zz_generated.defaults.go artifact.

The file api/core/v1alpha1/zz_generated.defaults.go exists but is a stale autogenerated stub—its RegisterDefaults() function is empty and the file is never imported or referenced anywhere in the codebase. Since the +k8s:defaulter-gen marker has been removed from doc.go and code generation no longer occurs (confirmed by absence of defaulter-gen directives in hack/ scripts), this file should be deleted in this PR to keep the repository clean.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/core/v1alpha1/doc.go` around lines 4 - 7, The file
api/core/v1alpha1/zz_generated.defaults.go is a stale autogenerated artifact
(its RegisterDefaults function is empty and not referenced) left after removing
+k8s:defaulter-gen; delete zz_generated.defaults.go and any references/imports
to it, remove or update any build tags or go:generate lines that expect a
defaulter in the api/core/v1alpha1 package, and ensure there are no remaining
usages of RegisterDefaults so compilation and imports remain clean.

// all port names and numbers.
// If present, only traffic on the specified protocol AND port will be matched.
Port int32 `json:"port,omitempty"`
Port *int32 `json:"port,omitempty"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all uses of NetworkPolicyPort.Port field access or struct literals
rg -nP -C3 '\bNetworkPolicyPort\b' --type=go
echo "---"
rg -nP -C2 '\.Port\b' --type=go -g '!**/zz_generated*' -g '!vendor/**' | rg -n 'networkpolicy|NetworkPolicyPort|policy\.Port|ports\[' | head -100
echo "---"
# Check conversion / validation files
fd -t f -e go | xargs rg -nP -l 'NetworkPolicyPort' 2>/dev/null

Repository: ironcore-dev/ironcore-net

Length of output: 41547


🏁 Script executed:

# Check the validation code more carefully - this has pointer comparisons
cat -n internal/apis/core/validation/networkpolicy.go | sed -n '113,135p'

Repository: ironcore-dev/ironcore-net

Length of output: 1113


🏁 Script executed:

# Check the apinetlet test code assignments
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '93,105p'
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '128,140p'
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '389,405p'
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '425,440p'

Repository: ironcore-dev/ironcore-net

Length of output: 2460


🏁 Script executed:

# Check both apinetlet and metalnetlet controller usages
cat -n apinetlet/controllers/networkpolicy_controller.go | sed -n '236,276p'
cat -n metalnetlet/controllers/networkinterface_controller.go | sed -n '1,50p' | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 2300


🏁 Script executed:

# Find the apinetv1alpha1 NetworkPolicyPort definition
fd -t f -e go -path '*/apinetv1alpha1*' | xargs rg -l 'type NetworkPolicyPort' 2>/dev/null | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 402


🏁 Script executed:

# Check what Port type is in the target struct (apinetv1alpha1)
rg -A5 'type NetworkPolicyPort struct' api/ --type=go | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 591


🏁 Script executed:

# Verify the metalnetlet controller properly uses pointers
cat -n metalnetlet/controllers/networkinterface_controller_test.go | sed -n '134,165p'

Repository: ironcore-dev/ironcore-net

Length of output: 1224


🏁 Script executed:

# Find apinetv1alpha1 NetworkPolicyPort definition
fd -t f -name '*.go' | xargs rg -l 'apinetv1alpha1' | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 529


🏁 Script executed:

# Look for api/core/v1alpha1 Rule and NetworkPolicyPort types
rg -A8 'type Rule struct' api/core/v1alpha1/ --type go

Repository: ironcore-dev/ironcore-net

Length of output: 858


🏁 Script executed:

# Check the conversion code to understand the transformation
cat -n apinetlet/controllers/conversion.go | sed -n '183,195p'

Repository: ironcore-dev/ironcore-net

Length of output: 604


🏁 Script executed:

# Check if the test code actually compiles - look for Port field type issues
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '96,110p'

Repository: ironcore-dev/ironcore-net

Length of output: 627


🏁 Script executed:

# Look at the full validation function to see all the issues
cat -n internal/apis/core/validation/networkpolicy.go | sed -n '113,145p'

Repository: ironcore-dev/ironcore-net

Length of output: 1402


🏁 Script executed:

# Check the generated conversion functions
cat -n internal/apis/core/v1alpha1/zz_generated.conversion.go | sed -n '2638,2665p'

Repository: ironcore-dev/ironcore-net

Length of output: 1754


🏁 Script executed:

# Check the source type in apinetlet controller - what is np.Spec.Ingress.Ports element type?
cat -n apinetlet/controllers/networkpolicy_controller.go | sed -n '236,245p'
# Get more context on what type np is
cat -n apinetlet/controllers/networkpolicy_controller.go | sed -n '225,240p'

Repository: ironcore-dev/ironcore-net

Length of output: 1009


🏁 Script executed:

# Check internal/apis/core NetworkPolicyPort definition to see Port type there
cat -n internal/apis/core/networkpolicy_types.go | sed -n '28,42p'

Repository: ironcore-dev/ironcore-net

Length of output: 714


🏁 Script executed:

# Check what type apinetv1alpha1.NetworkPolicyPort.Port is
fd -t f -name '*.go' -path '*/api/core/v1alpha1/*' | xargs grep -l 'type NetworkPolicyPort' | head -1 | xargs cat | grep -A10 'type NetworkPolicyPort struct'

Repository: ironcore-dev/ironcore-net

Length of output: 299


🏁 Script executed:

# Verify line 128 in validation is actually comparing pointer to value (compilation error)
cat -n internal/apis/core/validation/networkpolicy.go | sed -n '123,132p'

Repository: ironcore-dev/ironcore-net

Length of output: 526


🏁 Script executed:

# Find api/core/v1alpha1 NetworkPolicyPort to see if Port is pointer there
find . -name "networkpolicy_types.go" -path "*/api/core/v1alpha1/*" -exec cat {} \; | head -50

Repository: ironcore-dev/ironcore-net

Length of output: 2406


🏁 Script executed:

# Check the apinetlet conversion.go to understand the Port field handling
cat -n apinetlet/controllers/conversion.go | sed -n '183,194p'

Repository: ironcore-dev/ironcore-net

Length of output: 604


🏁 Script executed:

# Check apinetlet controller imports to understand what apinetv1alpha1 is
head -30 apinetlet/controllers/networkpolicy_controller.go | grep -E 'import|apinetv1alpha1'

Repository: ironcore-dev/ironcore-net

Length of output: 251


🏁 Script executed:

# Search for where apinetv1alpha1.NetworkPolicyPort is defined
rg 'type NetworkPolicyPort struct' --type go | grep -v zz_generated | grep -v applyconfigurations

Repository: ironcore-dev/ironcore-net

Length of output: 215


🏁 Script executed:

# Check line 188 in conversion.go more carefully - this looks like a bug
cat -n apinetlet/controllers/conversion.go | sed -n '183,195p'

Repository: ironcore-dev/ironcore-net

Length of output: 604


🏁 Script executed:

# Verify what the issue is - Port is now *int32 so &port.Port would be **int32
# Let me check the full context of the conversion function
cat -n apinetlet/controllers/conversion.go | sed -n '175,200p'

Repository: ironcore-dev/ironcore-net

Length of output: 948


🏁 Script executed:

# Check what networkingv1alpha1 is - this is the public API v1alpha1
head -30 apinetlet/controllers/conversion.go | grep -E 'networkingv1alpha1|import' -A20

Repository: ironcore-dev/ironcore-net

Length of output: 1079


🏁 Script executed:

# Verify the exact type mismatch at line 188 - Port should already be *int32
cat -n apinetlet/controllers/conversion.go | sed -n '1,30p' | grep -E 'import|networkingv1alpha1'

Repository: ironcore-dev/ironcore-net

Length of output: 376


🏁 Script executed:

# Now let me check: is networkingv1alpha1 (external ironcore) Port value or pointer?
# Look at the conversion registration to understand the type mappings
rg 'Convert_.*NetworkPolicyPort' internal/apis/core/v1alpha1/zz_generated.conversion.go | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 696


🏁 Script executed:

# Check if the test code compiles - look at Port assignment with literal int32
cat -n apinetlet/controllers/networkpolicy_controller_test.go | sed -n '95,106p'
# Compare with metalnetlet which uses generic.Pointer
cat -n metalnetlet/controllers/networkinterface_controller_test.go | sed -n '137,143p'

Repository: ironcore-dev/ironcore-net

Length of output: 740


🏁 Script executed:

# Let me check what the actual Port field type is in the external ironcore package
# by checking if there's any ironcore dependency definition or checking the actual error
rg 'type NetworkPolicyPort' --type go -B2 -A8 | grep -E 'api/core/v1alpha1|internal/apis/core' -A10

Repository: ironcore-dev/ironcore-net

Length of output: 2955


🏁 Script executed:

# Check if there are any build errors or test failures mentioned
fd -t f -name 'go.mod' | xargs cat | grep ironcore

Repository: ironcore-dev/ironcore-net

Length of output: 299


🏁 Script executed:

# Verify the actual consumers of api/core/v1alpha1.NetworkPolicyPort - look at apinetlet controller again
# The key is: does it use api/core/v1alpha1 or networkingv1alpha1?
rg 'np \*.*NetworkPolicy|np := ' apinetlet/controllers/networkpolicy_controller.go -B5 | head -30

Repository: ironcore-dev/ironcore-net

Length of output: 934


🏁 Script executed:

# Verify which NetworkPolicyPort the validation function uses
cat -n internal/apis/core/validation/networkpolicy.go | sed -n '1,20p'

Repository: ironcore-dev/ironcore-net

Length of output: 821


🏁 Script executed:

# Check if there's also a validation file for the public API
find . -name "*.go" -path "*/validation/*" | xargs grep -l 'NetworkPolicyPort' 2>/dev/null

Repository: ironcore-dev/ironcore-net

Length of output: 117


🏁 Script executed:

# Compare the two Port field types side by side
echo "=== internal/apis/core ===" && \
cat internal/apis/core/networkpolicy_types.go | grep -A2 'Port ' | head -5 && \
echo "=== api/core/v1alpha1 ===" && \
cat api/core/v1alpha1/networkpolicy_types.go | grep -A2 'Port ' | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 525


🏁 Script executed:

# Identify the exact issues - check what happens with the conversion between internal and api types
cat -n internal/apis/core/v1alpha1/zz_generated.conversion.go | sed -n '2638,2665p'

Repository: ironcore-dev/ironcore-net

Length of output: 1754


🏁 Script executed:

# Specifically check line 2640 - what does Convert_Pointer_int32_To_int32 do?
# This shows the conversion from api (pointer) to internal (value) type
# So the internal/apis/core still has Port int32 - the public API changed!
# Verify this is the actual current state
grep -A1 'Port ' internal/apis/core/networkpolicy_types.go | head -6
grep -A1 'Port ' api/core/v1alpha1/networkpolicy_types.go | head -6

Repository: ironcore-dev/ironcore-net

Length of output: 469


Breaking API change: Port in public API api/core/v1alpha1/networkpolicy_types.go is now a pointer.

Changing Port int32Port *int32 in the public API is a source-breaking change for consumers of api/core/v1alpha1.NetworkPolicyPort. However, the internal API type (internal/apis/core.NetworkPolicyPort) still uses Port int32 and is unaffected; proper conversion functions are generated to bridge the two.

The breaking change affects:

  • Direct struct literal construction in public API code (consumers must use generic.Pointer(int32(...)))
  • Code accessing the field must now dereference or nil-check

The in-tree consumers show mixed migration status:

  • metalnetlet/controllers/networkinterface_controller_test.go ✓ correctly uses generic.Pointer(int32(...))
  • apinetlet/controllers/networkpolicy_controller_test.go uses external networkingv1alpha1.NetworkPolicyPort (unaffected by this change)
  • apinetlet/controllers/conversion.go line 188 may have a type issue: Port: &port.Port where port.Port appears to be from the external package
  • internal/apis/core/validation/networkpolicy.go is unaffected (uses internal value type Port int32)

Confirm that serialization behavior is intentional: with omitempty, a *int32 pointing to 0 will be omitted (same as before), so port 0 cannot round-trip, but this is likely acceptable since port 0 is typically invalid anyway.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/core/v1alpha1/networkpolicy_types.go` at line 40, The public API
NetworkPolicyPort.Port was changed from int32 to *int32 which breaks callers
that take the address of an int field; update the affected conversion at the
site that sets `Port: &port.Port` (in apinetlet/controllers/conversion.go) to
create a proper *int32 from the external value (e.g. capture the int32 into a
local variable `p := port.Port` then use `Port: &p` or use your pointer helper
like `Port: generic.Pointer(port.Port)`), and scan the repo for other direct
`&...Port` usages to similarly convert to a *int32; ensure nil-checks where
appropriate.

Comment on lines +419 to +428
networkPolicyRuleApplyCfg := apinetv1alpha1ac.NetworkPolicyRule(apiNetNetworkPolicy.Name, apiNetNetworkPolicy.Namespace).
WithLabels(apinetletclient.SourceLabels(r.Scheme(), r.RESTMapper(), networkPolicy)).
WithNetworkRef(apinetv1alpha1ac.LocalUIDReference().
WithName(network.Name).
WithUID(network.UID)).
WithPriority(*apiNetNetworkPolicy.Spec.Priority).
WithTargets(targetCfgs...).
WithIngressRules(ingressRuleCfgs...).
WithEgressRules(egressRuleCfgs...).
WithOwnerReferences(ownerRef)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard against nil Spec.Priority before dereferencing.

apiNetNetworkPolicy.Spec.Priority is an *int32 and is dereferenced unconditionally at line 424. Although applyAPINetNetworkPolicy sets a default of 1000, a future change (or a partial server response) could leave it nil and crash the reconciler with a NPE.

🛡️ Proposed defensive fix
-		WithPriority(*apiNetNetworkPolicy.Spec.Priority).
+		WithPriority(ptr.Deref(apiNetNetworkPolicy.Spec.Priority, 1000)).

(or inline a short if p := apiNetNetworkPolicy.Spec.Priority; p != nil { cfg = cfg.WithPriority(*p) })

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apinetlet/controllers/networkpolicy_controller.go` around lines 419 - 428,
The code dereferences apiNetNetworkPolicy.Spec.Priority unconditionally when
calling WithPriority, which can cause an NPE if the pointer is nil; change the
construction of networkPolicyRuleApplyCfg to only call WithPriority when
apiNetNetworkPolicy.Spec.Priority is non-nil (e.g., check if p :=
apiNetNetworkPolicy.Spec.Priority; p != nil then chain .WithPriority(*p)),
leaving all other chained calls (WithLabels, WithNetworkRef, WithTargets,
WithIngressRules, WithEgressRules, WithOwnerReferences) intact so the cfg is
built defensively.

// Ports are the ports the load balancer should allow.
// If empty, the load balancer allows all ports.
Ports []LoadBalancerPortApplyConfiguration `json:"ports,omitempty"`
// Selector selects all Instance that are managed by this daemon set.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix incorrect selector comment context on Line 26.

“managed by this daemon set” appears unrelated to LoadBalancerSpec, and “Instance” should be pluralized. This is misleading API documentation.

Suggested doc fix
-	// Selector selects all Instance that are managed by this daemon set.
+	// Selector selects all Instances matching the given labels.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client-go/applyconfigurations/core/v1alpha1/loadbalancerspec.go` at line 26,
The comment on the Selector field of LoadBalancerSpec is incorrect and
misleading; update the Selector comment in type LoadBalancerSpec to reflect load
balancer context and pluralize "Instance" (e.g., "Selector selects all Instances
that are targeted/associated with this LoadBalancer" or similar), ensuring the
comment references LoadBalancer rather than "daemon set" and uses correct
pluralization for Instance/Instances.

Comment on lines +62 to +64
// APIVersion and Kind populated. It is possible that no managed fields were found for because other
// field managers have taken ownership of all the fields previously owned by fieldManager, or because
// the fieldManager never owned fields any fields.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clean up the generated extractor Godoc grammar.

This public Godoc currently reads awkwardly and has duplicated wording.

📝 Proposed generated-doc fix
-// APIVersion and Kind populated. It is possible that no managed fields were found for because other
+// APIVersion and Kind populated. It is possible that no managed fields were found because other
 // field managers have taken ownership of all the fields previously owned by fieldManager, or because
-// the fieldManager never owned fields any fields.
+// the fieldManager never owned any fields.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// APIVersion and Kind populated. It is possible that no managed fields were found for because other
// field managers have taken ownership of all the fields previously owned by fieldManager, or because
// the fieldManager never owned fields any fields.
// APIVersion and Kind populated. It is possible that no managed fields were found because other
// field managers have taken ownership of all the fields previously owned by fieldManager, or because
// the fieldManager never owned any fields.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client-go/applyconfigurations/core/v1alpha1/networkpolicy.go` around lines 62
- 64, The generated Godoc comment in networkpolicy.go is awkward and duplicates
wording (e.g., "no managed fields were found for because other field
managers..." and "never owned fields any fields"); edit the public comment that
begins with "APIVersion and Kind populated." to remove the duplicated words and
fix grammar so it reads clearly (e.g., "It is possible that no managed fields
were found because other field managers have taken ownership, or because the
fieldManager never owned any fields. APIVersion and Kind are populated.").
Ensure you update the comment associated with the generated extractor in
networkpolicy.go so the public documentation is concise and grammatically
correct.

Comment on lines +323 to +328
natTableApplyConfig := corev1alpha1apply.NATTable(natGateway.Name, natGateway.Namespace).
WithOwnerReferences(v1.OwnerReference().
WithAPIVersion(v1alpha1.SchemeGroupVersion.String()).
WithKind("NATGateway").
WithName(natGateway.Name).
WithUID(natGateway.UID))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing Controller/BlockOwnerDeletion on NATTable owner reference — behavioral regression.

Every other reconciler in this PR sets WithController(true).WithBlockOwnerDeletion(true) on its metav1apply.OwnerReference, and the previous implementation almost certainly used ctrl.SetControllerReference (which sets both). Two concrete consequences here:

  1. SetupWithManager uses .Owns(&v1alpha1.NATTable{}) (line 478). Owns routes events to the parent via the controller owner reference — without Controller=true, NATTable changes will not re-enqueue the owning NATGateway.
  2. Without BlockOwnerDeletion, the NATTable can be GC'd before/separately from the NATGateway during cascading delete, inverting prior guarantees.
🛠️ Proposed fix
 	natTableApplyConfig := corev1alpha1apply.NATTable(natGateway.Name, natGateway.Namespace).
 		WithOwnerReferences(v1.OwnerReference().
 			WithAPIVersion(v1alpha1.SchemeGroupVersion.String()).
 			WithKind("NATGateway").
 			WithName(natGateway.Name).
-			WithUID(natGateway.UID))
+			WithUID(natGateway.UID).
+			WithController(true).
+			WithBlockOwnerDeletion(true))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
natTableApplyConfig := corev1alpha1apply.NATTable(natGateway.Name, natGateway.Namespace).
WithOwnerReferences(v1.OwnerReference().
WithAPIVersion(v1alpha1.SchemeGroupVersion.String()).
WithKind("NATGateway").
WithName(natGateway.Name).
WithUID(natGateway.UID))
natTableApplyConfig := corev1alpha1apply.NATTable(natGateway.Name, natGateway.Namespace).
WithOwnerReferences(v1.OwnerReference().
WithAPIVersion(v1alpha1.SchemeGroupVersion.String()).
WithKind("NATGateway").
WithName(natGateway.Name).
WithUID(natGateway.UID).
WithController(true).
WithBlockOwnerDeletion(true))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controllers/natgateway_controller.go` around lines 323 - 328, The
owner reference on the NATTable created in NATTable(natGateway.Name,
natGateway.Namespace) currently omits Controller and BlockOwnerDeletion flags;
update the OwnerReference builder (the v1.OwnerReference() chain used when
constructing natTableApplyConfig) to include
.WithController(true).WithBlockOwnerDeletion(true) so the NATTable has
Controller=true and BlockOwnerDeletion=true like other reconcilers—this restores
event routing for Owns(&v1alpha1.NATTable{}) and ensures proper cascading
deletion behavior.

Comment on lines +349 to 360
slices.SortFunc(sectionConfs, func(a, b *corev1alpha1apply.NATIPSectionApplyConfiguration) int {
if a.Port == nil || b.Port == nil {
return 0
}
if *a.Port < *b.Port {
return -1
}
if *a.Port > *b.Port {
return 1
}
return 0
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

SortFunc comparator violates the total-order contract when exactly one Port is nil.

Returning 0 whenever either operand is nil makes the comparator non-transitive: e.g. with items A(Port=1), B(Port=nil), C(Port=2), cmp(A,B)=0 and cmp(B,C)=0 but cmp(A,C)=-1. slices.SortFunc requires a strict weak ordering; this produces nondeterministic output and can cause spurious diffs in the server-side-apply payload (churn/ownership flips). Sort nils to a consistent side.

🛠️ Proposed fix
 		slices.SortFunc(sectionConfs, func(a, b *corev1alpha1apply.NATIPSectionApplyConfiguration) int {
-			if a.Port == nil || b.Port == nil {
-				return 0
-			}
-			if *a.Port < *b.Port {
-				return -1
-			}
-			if *a.Port > *b.Port {
-				return 1
-			}
-			return 0
+			switch {
+			case a.Port == nil && b.Port == nil:
+				return 0
+			case a.Port == nil:
+				return 1
+			case b.Port == nil:
+				return -1
+			}
+			return cmp.Compare(*a.Port, *b.Port)
 		})

(add "cmp" to imports)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
slices.SortFunc(sectionConfs, func(a, b *corev1alpha1apply.NATIPSectionApplyConfiguration) int {
if a.Port == nil || b.Port == nil {
return 0
}
if *a.Port < *b.Port {
return -1
}
if *a.Port > *b.Port {
return 1
}
return 0
})
slices.SortFunc(sectionConfs, func(a, b *corev1alpha1apply.NATIPSectionApplyConfiguration) int {
switch {
case a.Port == nil && b.Port == nil:
return 0
case a.Port == nil:
return 1
case b.Port == nil:
return -1
}
return cmp.Compare(*a.Port, *b.Port)
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controllers/natgateway_controller.go` around lines 349 - 360, The
comparator passed to slices.SortFunc for sectionConfs (elements of type
corev1alpha1apply.NATIPSectionApplyConfiguration) must establish a total order
when Port may be nil; change the lambda used in slices.SortFunc so it treats nil
consistently (e.g., consider nil > any non-nil or nil < any non-nil), by first
checking both nils (return 0), then handling one-nil cases deterministically
(return 1 or -1), and only then comparing *a.Port and *b.Port; update the
comparator used in slices.SortFunc to implement this deterministic ordering so
SortFunc receives a strict weak ordering.

Comment on lines 470 to 472
if len(nodes) == 0 {
r.Event(inst, corev1.EventTypeNormal, outOfCapacity, "No nodes available to schedule instance on")
r.Eventf(inst, nil, corev1.EventTypeNormal, outOfCapacity, "No nodes available to schedule %v on", inst.Name)
return ctrl.Result{}, nil
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

k8s.io/client-go/tools/events EventRecorder Eventf action note parameter semantics

💡 Result:

In k8s.io/client-go/tools/events, the EventRecorder interface (specifically implementations like recorderImpl and recorderImplLogger, and the EventBroadcasterAdapter via tools/record) provides an Eventf method with signature: func Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) This method formats 'note' using fmt.Sprintf(note, args...) to produce the event message, constructs an events.k8s.io/v1 Event object, and asynchronously records it via the broadcaster (as watch.Added). Parameter semantics, grounded in source code and events/v1 API docs: - regarding: Primary object the event concerns (populates Event.Regarding ObjectReference). - related: Optional secondary object (populates Event.Related ObjectReference). - eventtype: Event type, typically "Normal" or "Warning" (populates Event.Type; validated via util.ValidateEventType). - reason: Machine-readable reason/code for the event (UpperCamelCase; populates Event.Reason; max 128 chars). - action: Machine-readable description of the action taken/failed on the regarding object (e.g., "Created", "Updated", "Deleted"; populates Event.Action directly; max 128 chars, required/non-empty for new events). - note: Human-readable format string for the event description (formatted to Event.Note; max 1kB, prepare for 64kB). The event also sets EventTime (microsecond precision first observation time), ReportingController/Instance, and generates a unique name/namespace from regarding. This contrasts with the simpler tools/record.EventRecorder.Eventf(object, eventtype, reason, messageFmt string, args...), which lacks action/note/related and targets core/v1 Events (where message is unstructured). The events package targets the newer structured events.k8s.io/v1 API.

Citations:


🏁 Script executed:

# First, locate the scheduler_controller.go file
find . -name "scheduler_controller.go" -type f

Repository: ironcore-dev/ironcore-net

Length of output: 115


🏁 Script executed:

# Check the specific lines mentioned in the review
sed -n '460,480p' ./internal/controllers/scheduler_controller.go | cat -n

Repository: ironcore-dev/ironcore-net

Length of output: 790


🏁 Script executed:

# Check imports to see which EventRecorder is being used
head -50 ./internal/controllers/scheduler_controller.go | cat -n

Repository: ironcore-dev/ironcore-net

Length of output: 2070


🏁 Script executed:

# Search for all Eventf calls in the scheduler_controller.go file
rg "Eventf" ./internal/controllers/scheduler_controller.go -n

Repository: ironcore-dev/ironcore-net

Length of output: 184


🏁 Script executed:

# Check the v1alpha1.Instance type definition to verify it has Namespace and Name fields
find . -path "*/api/core/v1alpha1/*instance*" -type f -name "*.go" | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 106


🏁 Script executed:

# Check the Instance type definition for Namespace and Name fields
head -100 ./api/core/v1alpha1/instance_types.go | cat -n

Repository: ironcore-dev/ironcore-net

Length of output: 5329


🏁 Script executed:

# Find the Instance struct definition
rg "type Instance struct" ./api/core/v1alpha1/instance_types.go -A 20

Repository: ironcore-dev/ironcore-net

Length of output: 679


Eventf arguments are misaligned with the k8s.io/client-go/tools/events.EventRecorder signature — instance name is not interpolated into the message.

The EventRecorder.Eventf signature from k8s.io/client-go/tools/events is:

Eventf(regarding, related runtime.Object, eventtype, reason, action, note string, args ...interface{})

where action is a short UpperCamelCase verb (e.g., "Scheduling", "Updated"), note is a format string, and args are substituted into note via fmt.Sprintf(note, args...).

The current call at line 471:

r.Eventf(inst, nil, corev1.EventTypeNormal, outOfCapacity, "No nodes available to schedule %v on", inst.Name)

incorrectly passes:

  • action: "No nodes available to schedule %v on" (a full sentence, not a verb)
  • note: inst.Name (a plain string, not a format string)
  • args: (empty)

This causes two problems:

  1. The %v placeholder is never substituted; the emitted event message is literally just the instance name instead of "No nodes available to schedule <name> on".
  2. action semantics are violated (expected to be a short verb, not a full sentence), breaking event filtering and classification.

Additionally, using the namespaced key namespace/name is more useful in scheduler contexts than the bare name alone.

Proposed fix
-		r.Eventf(inst, nil, corev1.EventTypeNormal, outOfCapacity, "No nodes available to schedule %v on", inst.Name)
+		r.Eventf(inst, nil, corev1.EventTypeNormal, outOfCapacity, "Scheduling", "No nodes available to schedule %s/%s on", inst.Namespace, inst.Name)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/controllers/scheduler_controller.go` around lines 470 - 472, The
Eventf call incorrectly puts the full message into the action parameter and the
instance name into the note; update the r.Eventf invocation so action is a short
verb like "SchedulingFailed" (or "Scheduling"), note is a format string such as
"No nodes available to schedule %s on", and pass the namespaced key
(namespace/name) of the instance as the argument to format the note (use
inst.Namespace and inst.Name) so the emitted event reads "No nodes available to
schedule <namespace/name> on" and follows EventRecorder semantics; locate and
change the call to r.Eventf in the scheduler controller where inst is used.

r.NodeLabels,
))

if err := r.Apply(ctx, nodeApplyCfg, PartitionFieldOwner(r.PartitionName)); err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "metalnetnode_controller.go" | head -5

Repository: ironcore-dev/ironcore-net

Length of output: 119


🏁 Script executed:

find . -name "metalnetnode_controller.go" -type f

Repository: ironcore-dev/ironcore-net

Length of output: 121


🏁 Script executed:

cat -n metalnetlet/controllers/metalnetnode_controller.go | sed -n '1,20p'

Repository: ironcore-dev/ironcore-net

Length of output: 926


🏁 Script executed:

cat -n metalnetlet/controllers/metalnetnode_controller.go | sed -n '120,145p'

Repository: ironcore-dev/ironcore-net

Length of output: 905


🏁 Script executed:

cat -n metalnetlet/controllers/metalnetnode_controller.go | sed -n '1,50p'

Repository: ironcore-dev/ironcore-net

Length of output: 2427


🏁 Script executed:

rg "func.*Apply" metalnetlet/controllers/metalnetnode_controller.go -A 3

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

rg "type.*Reconciler" metalnetlet/controllers/metalnetnode_controller.go -A 5

Repository: ironcore-dev/ironcore-net

Length of output: 209


🏁 Script executed:

rg "func PartitionFieldOwner" metalnetlet/controllers/ -B 2 -A 5

Repository: ironcore-dev/ironcore-net

Length of output: 586


🏁 Script executed:

rg "PartitionFieldOwner" metalnetlet/controllers/metalnetnode_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 158


🏁 Script executed:

rg "func PartitionFieldOwner" . -B 2 -A 5

Repository: ironcore-dev/ironcore-net

Length of output: 602


🏁 Script executed:

git log --oneline -n 20 -- metalnetlet/controllers/metalnetnode_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 104


🏁 Script executed:

git show HEAD:metalnetlet/controllers/metalnetnode_controller.go 2>/dev/null | sed -n '120,145p'

Repository: ironcore-dev/ironcore-net

Length of output: 723


🏁 Script executed:

rg "func.*Apply.*\(" metalnetlet/controllers/ -B 2 -A 8 | head -50

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

rg "\.Apply\(" metalnetlet/controllers/metalnetnode_controller.go -B 2 -A 2

Repository: ironcore-dev/ironcore-net

Length of output: 234


🏁 Script executed:

rg "func.*Apply" . --type go -B 1 -A 5 | grep -A 5 "func.*Apply"

Repository: ironcore-dev/ironcore-net

Length of output: 50382


🏁 Script executed:

fd -t f "*.go" | xargs rg "func.*Apply.*ctx.*ApplyConfiguration" | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 352


🏁 Script executed:

fd -t f "*.go" -p "*clientutils*"

Repository: ironcore-dev/ironcore-net

Length of output: 169


🏁 Script executed:

rg "package clientutils" . -A 20

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

rg "func Apply" . --type go -B 2 -A 8

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

rg "\.Apply\(" metalnetlet/controllers/ -B 1 -A 1

Repository: ironcore-dev/ironcore-net

Length of output: 379


🏁 Script executed:

git log --all --source -S "ForceOwnership" -- metalnetlet/controllers/ | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 422


🏁 Script executed:

rg "ForceOwnership" . --type go | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 1355


🏁 Script executed:

rg "client\.(Apply|ForceOwnership)" . --type go

Repository: ironcore-dev/ironcore-net

Length of output: 1355


🏁 Script executed:

rg "func.*Apply.*ctx.*ApplyConfiguration.*FieldOwner" . --type go -A 3 | head -30

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

cat -n metalnetlet/controllers/common.go | sed -n '1,30p'

Repository: ironcore-dev/ironcore-net

Length of output: 1150


Add missing client.ForceOwnership to the server-side apply call.

Line 137 applies without client.ForceOwnership, unlike all other Apply calls across the codebase (natgateway_controller, loadbalancer_controller, networkpolicy_controller, etc.). Without force ownership, pre-existing fields owned by another manager will cause conflicts and block reconciliation.

🐛 Proposed fix
-	if err := r.Apply(ctx, nodeApplyCfg, PartitionFieldOwner(r.PartitionName)); err != nil {
+	if err := r.Apply(ctx, nodeApplyCfg, PartitionFieldOwner(r.PartitionName), client.ForceOwnership); err != nil {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err := r.Apply(ctx, nodeApplyCfg, PartitionFieldOwner(r.PartitionName)); err != nil {
if err := r.Apply(ctx, nodeApplyCfg, PartitionFieldOwner(r.PartitionName), client.ForceOwnership); err != nil {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@metalnetlet/controllers/metalnetnode_controller.go` at line 137, The
server-side apply call using r.Apply(ctx, nodeApplyCfg,
PartitionFieldOwner(r.PartitionName)) must include client.ForceOwnership so
pre-existing fields owned by other managers are taken over; update the call to
pass client.ForceOwnership alongside PartitionFieldOwner (e.g., r.Apply(ctx,
nodeApplyCfg, client.ForceOwnership, PartitionFieldOwner(r.PartitionName))) and
ensure the client symbol is available in scope; reference r.Apply, nodeApplyCfg,
PartitionFieldOwner, and client.ForceOwnership when making the change.

Comment on lines +243 to 248
if port.Port != nil {
if direction == metalnetv1alpha1.FirewallRuleDirectionIngress {
baseFirewallRule.ProtocolMatch.PortRange = &metalnetv1alpha1.PortMatch{SrcPort: &port.Port}
baseFirewallRule.ProtocolMatch.PortRange = &metalnetv1alpha1.PortMatch{SrcPort: port.Port}
} else {
baseFirewallRule.ProtocolMatch.PortRange = &metalnetv1alpha1.PortMatch{DstPort: &port.Port}
baseFirewallRule.ProtocolMatch.PortRange = &metalnetv1alpha1.PortMatch{DstPort: port.Port}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP -C2 'Protocol\s+\*?\s*corev1\.Protocol|Protocol\s+\*corev1\.Protocol' --type=go
ast-grep --pattern 'type NetworkPolicyPort struct { $$$ }'

Repository: ironcore-dev/ironcore-net

Length of output: 4500


🏁 Script executed:

cd metalnetlet/controllers && sed -n '230,250p' networkinterface_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 1044


🏁 Script executed:

cd metalnetlet/controllers && sed -n '200,240p' networkinterface_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 1716


🏁 Script executed:

cd metalnetlet/controllers && sed -n '200,220p' networkinterface_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 777


🏁 Script executed:

cd api/core/v1alpha1 && grep -n "type Rule struct" -A 20 *.go

Repository: ironcore-dev/ironcore-net

Length of output: 1516


🏁 Script executed:

rg -n "SetDefaults|func.*default" --type=go metalnetlet/controllers/networkinterface_controller.go

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

find . -name "*.go" -type f | xargs grep -l "SetDefaults.*NetworkPolicyPort\|Protocol.*default" | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 112


🏁 Script executed:

find api -name "*webhook*" -o -name "*default*" -o -name "*validation*" | head -20

Repository: ironcore-dev/ironcore-net

Length of output: 111


🏁 Script executed:

grep -n "NetworkPolicyPort\|Protocol" api/core/v1alpha1/zz_generated.defaults.go | head -30

Repository: ironcore-dev/ironcore-net

Length of output: 51


🏁 Script executed:

grep -A 15 "type NetworkPolicyPort struct" api/core/v1alpha1/networkpolicy_types.go

Repository: ironcore-dev/ironcore-net

Length of output: 809


Add nil-check for port.Protocol before the switch statement to prevent potential panic.

The concern is valid: Protocol is an optional field (*corev1.Protocol with omitempty JSON tag) per the API definition, but the switch statement at line 235 dereferences it without checking for nil. While the API comment states the field "defaults to TCP if not specified," no defaulting logic is implemented in the codebase. If Protocol is nil, the code will panic. This needs the same nil-guard protection that Port now has:

if port.Protocol != nil {
	switch *port.Protocol {
	// ... existing cases
	}
} else {
	// handle or default to TCP
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@metalnetlet/controllers/networkinterface_controller.go` around lines 243 -
248, The switch that dereferences port.Protocol must be guarded to avoid nil
panic: wrap the existing switch that uses *port.Protocol with an if
port.Protocol != nil { switch *port.Protocol { ... } } else { treat as the TCP
branch (i.e., apply the same logic as the ProtocolTCP case) }; update references
inside the switch to use the same branch logic for TCP, UDP, SCTP as before and
ensure baseFirewallRule.ProtocolMatch is set consistently when port.Protocol is
nil by defaulting to TCP.

@Rohit-0505
Copy link
Copy Markdown
Contributor Author

Current blocker metalnet

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

Labels

area/networking Networking-related tasks and improvements. documentation Improvements or additions to documentation size/XXL

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants