Skip to content

USHIFT-6795: C2CC: Router controller#6599

Open
pmtk wants to merge 35 commits intoopenshift:mainfrom
pmtk:c2cc/routes
Open

USHIFT-6795: C2CC: Router controller#6599
pmtk wants to merge 35 commits intoopenshift:mainfrom
pmtk:c2cc/routes

Conversation

@pmtk
Copy link
Copy Markdown
Member

@pmtk pmtk commented Apr 28, 2026

When reviewing, skip Vendor libovsdb & knftables commit

Summary by CodeRabbit

  • New Features

    • Added Cluster-to-Cluster Connectivity (C2CC) controller integrated into startup: automated cross-cluster route management (policy & service routes), nftables masquerade-bypass rules, OVN static route sync, node SNAT-exclude tracking with reconciliation and cleanup, and a managed NetworkPolicy to allow remote pods.
  • Tests

    • Added comprehensive test coverage and assets: unit tests, integration/reconciliation suites, end-to-end connectivity/infrastructure/sanity/cleanup scenarios, presubmit scenario, and test workloads/manifests.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 28, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Apr 28, 2026

@pmtk: This pull request references USHIFT-6795 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 28, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 28, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Caution

Review failed

An error occurred during the review process. Please try again later.

Walkthrough

Adds a Cluster-to-Cluster (C2CC) route manager to MicroShift: OVN NB integration, Linux policy & service routing, nftables bypass rules, node SNAT annotation management, a C2CC NetworkPolicy, startup/service registration, unit tests, and Robot Framework end-to-end tests and scenarios.

Changes

Cohort / File(s) Summary
Core Dependencies
go.mod
Adds direct dependencies: github.com/ovn-kubernetes/libovsdb, sigs.k8s.io/knftables, github.com/cenkalti/backoff/v4, and related transitive modules.
Service Registration & Config
pkg/cmd/run.go, pkg/config/c2cc.go
Registers C2CCRouteManager in MicroShift ServiceManager and adds C2CC.AllRemoteCIDRs() helper.
Top-level Controller
pkg/controllers/c2cc/controller.go
Adds exported C2CCRouteManager with start/ready/stop lifecycle, orchestration of subsystems, event-driven + periodic reconcile, and cleanup logic.
OVN NB Integration
pkg/controllers/c2cc/nbdb.go, pkg/controllers/c2cc/nbdb_test.go, pkg/controllers/c2cc/ovn.go, pkg/controllers/c2cc/ovn_test.go
Implements OVN NB client/models, connect/monitor flows, deterministic UUIDs, transactional create/delete of Logical_Router_Static_Route rows and router references, and tests.
Node Annotation Manager
pkg/controllers/c2cc/annotation.go, pkg/controllers/c2cc/annotation_test.go
Manages OVN SNAT-exclude and tracking annotations on Node: deterministic JSON, merge semantics preserving foreign entries, reconcile/cleanup, Node watch with backoff and non-blocking reconcile signals, and tests.
Linux Policy Routing Helpers
pkg/controllers/c2cc/policy_routes.go, pkg/controllers/c2cc/policy_routes_test.go
Implements policyRouteTable abstraction: list/compare/apply/delete kernel routes, rule deletion helpers, ipFamilyOf, netlink subscribe and tests.
Linux Route Manager
pkg/controllers/c2cc/routes.go, pkg/controllers/c2cc/routes_test.go
Adds linuxRouteManager: desired routes from remotes, reconcile kernel routes and IP rules, cleanup, and tests for desired state.
Service Route Manager
pkg/controllers/c2cc/service_routes.go, pkg/controllers/c2cc/service_routes_test.go
Adds serviceRouteManager: management-port gateway discovery, service CIDR route reconciliation, paired ip rule reconciliation across remote/local service CIDRs, cleanup, and tests.
nftables Manager
pkg/controllers/c2cc/nftables.go, pkg/controllers/c2cc/nftables_test.go
Manages nft table/chain rules annotated with CIDR comments, detects/creates/deletes rules, subscribes to netlink nft events with debounced reconcile signals, cleanup, and tests (IPv4/IPv6 behavior).
NetworkPolicy
pkg/controllers/c2cc/networkpolicy.go
Creates/updates/deletes a C2CC NetworkPolicy that allows ingress from remote pod CIDRs; reconciliation preserves ResourceVersion, and deletion ignores NotFound.
Policy & route helpers (reuse)
pkg/controllers/c2cc/policy_routes.go
Shared helpers for route/rule reconciliation, subscription, cleanup, and family detection.
Tests & Test Helpers
pkg/controllers/c2cc/helpers_test.go, other _test.go files
Adds multiple unit tests and test helpers covering manager construction, nftables/route logic, OVN model behavior, annotation parsing, and ip family detection.
Test Manifests
test/assets/c2cc/curl-pod.yaml, test/assets/c2cc/hello-microshift.yaml
Adds Pod and Service manifests used by Robot tests.
Test Infra & Scenarios
test/resources/c2cc.resource, test/bin/scenario.sh, test/scenarios-bootc/...el98-src@c2cc.sh
Adds Robot Framework resource keywords for multi-cluster tests, extends scenario variable population to include sibling VMs, and a presubmit script to provision/configure two VMs for C2CC.
Robot Test Suites
test/suites/c2cc/...
Adds Robot suites: sanity, infrastructure, connectivity, reconciliation, and cleanup — covering readiness, route/rule/nft/OVN annotation verification, connectivity, fault-injection reconciliation tests, and teardown.

Sequence Diagram(s)

sequenceDiagram
    participant MS as MicroShift
    participant CM as C2CCRouteManager
    participant OVN as OVN_NB (OVSDB)
    participant K8s as Kubernetes_API
    participant NL as Linux_Netlink
    participant NFT as nftables

    MS->>CM: Start manager (NewC2CCRouteManager / Run)
    CM->>OVN: Connect & Monitor NB (unix socket, backoff)
    CM->>K8s: Init kube client
    CM->>NL: Subscribe routes/rules events
    CM->>NFT: Subscribe nft events
    CM->>CM: Start reconcile loop (periodic + event-driven)

    alt On reconcile (tick or event)
        CM->>OVN: List/Create/Delete Logical_Router_Static_Route
        CM->>K8s: Get/Patch Node annotations, Reconcile NetworkPolicy
        CM->>NL: Reconcile kernel policy routes and ip rules
        CM->>NFT: Reconcile nftables bypass rules (add/remove)
        OVN-->>CM: state / events
        K8s-->>CM: state / events
        NL-->>CM: state / events
        NFT-->>CM: state / events
    end

    MS->>CM: Shutdown
    CM->>OVN: Cleanup routes
    CM->>NL: Cleanup routes/rules
    CM->>NFT: Cleanup nft rules
    CM->>K8s: Delete NetworkPolicy / clear annotations
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

🚥 Pre-merge checks | ✅ 10 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ❓ Inconclusive PR contains standard Go testing.T tests with testify assertions and Robot Framework tests, not Ginkgo tests. Ginkgo-specific quality criteria cannot be evaluated against non-Ginkgo test code. Clarify if check applies to all test frameworks or only Ginkgo. If all frameworks, revise criteria for Go testing.T table-driven patterns and Robot Framework keywords instead of Ginkgo syntax.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: addition of a C2CC Router controller. It directly relates to the changeset's primary contribution across multiple new files implementing the C2CC routing system.
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.
Stable And Deterministic Test Names ✅ Passed PR uses Go's standard testing package and Robot Framework; all test names are static and deterministic with no dynamic identifiers.
Microshift Test Compatibility ✅ Passed Pull request adds only Robot Framework test files (.robot) in test/suites/c2cc/, not Ginkgo e2e tests. Custom check applies only to Ginkgo e2e tests.
Single Node Openshift (Sno) Test Compatibility ✅ Passed This PR does not add any Ginkgo e2e tests. New tests are Go unit tests using standard testing package and Robot Framework integration tests, not Ginkgo patterns.
Topology-Aware Scheduling Compatibility ✅ Passed PR introduces C2CC router controller and test infrastructure without topology-sensitive scheduling constraints or workload specifications.
Ote Binary Stdout Contract ✅ Passed The c2cc controller code contains no process-level entry points that could violate the OTE Binary Stdout Contract. All logging uses klog with stderr default, and test suites are Robot Framework tests not subject to this contract.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR contains no Ginkgo e2e tests; only standard Go unit tests, Robot Framework tests, and bash scripts.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 28, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: pmtk

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 28, 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: 11

🧹 Nitpick comments (4)
pkg/controllers/c2cc/nbdb_test.go (1)

16-41: FieldTags tests are currently tautological.

These assertions only re-check values set in the same struct literal, so they won’t catch ovsdb tag/schema regressions. Please validate tag mappings directly (e.g., reflection on struct tags or model metadata checks).

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

In `@pkg/controllers/c2cc/nbdb_test.go` around lines 16 - 41, The tests
TestLogicalRouterStaticRoute_FieldTags and TestLogicalRouter_FieldTags are
tautological because they only re-assert values set in struct literals; replace
these with reflection-based assertions that verify the actual struct field tags
(e.g., the ovsdb/model tags) on the types instead of field values. Use
reflect.TypeOf(LogicalRouterStaticRoute{}) and reflect.TypeOf(LogicalRouter{})
to inspect fields UUID, IPPrefix, Nexthop, ExternalIDs, Policy and UUID, Name,
StaticRoutes respectively, and assert that Tag.Get("ovsdb") (or the correct tag
key used by your OVSDB mapping) equals the expected tag/schema name for each
field; update the test expectations to the correct tag strings so the tests fail
on tag/schema regressions. Ensure you keep the original test names and replace
value assertions with these tag checks.
test/suites/c2cc/reconciliation.robot (1)

19-21: 30s timeout may be tight for some reconciliation scenarios.

The controller's periodic reconcile is 10s (reconcileInterval). With 5s retry, you get ~6 attempts. Should be sufficient, but event-driven reconciliation should trigger faster.

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

In `@test/suites/c2cc/reconciliation.robot` around lines 19 - 21, The test's
reconciliation timeout (${RECONCILE_TIMEOUT}) is likely too short for slower
environments; increase ${RECONCILE_TIMEOUT} (or adjust ${RECONCILE_RETRY}) so
the suite allows more attempts given the controller's reconcileInterval (~10s).
Update the Variables block to set a larger ${RECONCILE_TIMEOUT} (for example to
60s or more) or reduce ${RECONCILE_RETRY} gap to ensure enough reconciliation
attempts relative to reconcileInterval and event-driven triggers.
pkg/controllers/c2cc/ovn.go (1)

25-28: Consider URL-safe encoding for named UUIDs.

The replacer handles common characters but ., /, :, - may not be exhaustive for all CIDR formats. IPv6 CIDRs could introduce other characters.

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

In `@pkg/controllers/c2cc/ovn.go` around lines 25 - 28, The current buildNamedUUID
uses strings.NewReplacer to sanitize a few characters but misses other
characters (e.g., from IPv6 CIDRs); change buildNamedUUID to produce a URL-safe
deterministic token by encoding the combined prefix+suffix with a safe encoder:
e.g., compute a SHA-256 (or other stable) hash of prefix+suffix and return its
URL-safe base64 (base64.RawURLEncoding.EncodeToString(hash[:])) or, if
readability is desired, return url.PathEscape(prefix+suffix) to percent-encode
all unsafe characters; update the buildNamedUUID function to use one of these
approaches so all possible characters are handled safely.
test/resources/c2cc.resource (1)

174-180: Python inline script for JSON parsing works but is fragile.

Consider using oc get node -o jsonpath with the annotation key directly, similar to line 186. The current approach handles edge cases but adds complexity.

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

In `@test/resources/c2cc.resource` around lines 174 - 180, Replace the fragile
Python inline in the "Verify Node SNAT Annotation" check: instead of piping oc
JSON to python3 -c, call Oc On Cluster to run oc get node with a jsonpath that
directly extracts the annotation key
'k8s.ovn.org/node-ingress-snat-exclude-subnets' (for example using oc get node
-o
jsonpath="{.items[0].metadata.annotations['k8s.ovn.org/node-ingress-snat-exclude-subnets']}")
so ${stdout} contains the annotation value reliably; update the command that
currently uses python3 -c in the test to use this jsonpath form and keep the
subsequent Should Contain assertions unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controllers/c2cc/annotation.go`:
- Around line 74-97: The node watch loop currently can leak watches and spin on
reconnects; ensure each watcher is explicitly stopped and that unexpected
channel closure backs off: after successfully creating watcher (from
a.kubeClient.CoreV1().Nodes().Watch with FieldSelector
"metadata.name="+a.nodeName) defer or call watcher.Stop() when you exit that
watch scope, iterate using: ch, ok := <-watcher.ResultChan() and if !ok break
the inner loop and sleep/backoff (e.g., time.Sleep(10*time.Second)) before
continuing, and keep the existing ctx.Done() checks and reconcileCh send
(reconcileCh <- "node-annotation-changed") behavior unchanged so the loop won't
rapidly spin or leak goroutines.

In `@pkg/controllers/c2cc/nbdb.go`:
- Around line 56-58: The current loop around os.Stat(ovnNBSocketPath) treats
every error as "not found" and keeps retrying; update the check so that if
os.Stat returns an error that is not os.IsNotExist(err) you immediately return
that error (or wrap/propagate it) instead of retrying, and only continue retry
logic when os.IsNotExist(err) is true; locate the os.Stat(ovnNBSocketPath) call
in nbdb.go and change the conditional to explicitly handle non-`not exists`
errors (using os.IsNotExist) and return them promptly.

In `@pkg/controllers/c2cc/networkpolicy.go`:
- Around line 27-53: newNetworkPolicyManager currently builds an ingress rule
from ingressPeers which, if remotePodCIDRs is empty, results in an ingress rule
with an empty From (matching all sources); change the logic so you only add the
ingress rule and set networkingv1.PolicyTypeIngress when ingressPeers is
non-empty: compute ingressPeers as before, then conditionally populate
policy.Spec.Ingress and policy.Spec.PolicyTypes only when len(ingressPeers) > 0
(otherwise leave Spec.Ingress nil/empty and omit PolicyTypeIngress) so the
NetworkPolicy does not accidentally allow all ingress; update references to
ingressPeers, newNetworkPolicyManager, policy.Spec.Ingress, and PolicyTypes
accordingly.
- Around line 65-96: The reconcile/update and cleanup paths are mutating a
fixed-named NetworkPolicy without verifying ownership; before
Create/Update/Delete, fetch the existing object (existing from client.Get in the
reconcile flow and the object returned by Delete error handling in cleanup) and
check its labels (specifically "app.kubernetes.io/managed-by") against the
controller's expected manager value (compare
existing.Labels["app.kubernetes.io/managed-by"] to the value used for your
managed resources—e.g., the label on m.desired); if the label exists and does
not match, do not Update or Delete (instead log and return nil or a
non-destructive result), and when creating ensure you set the managed-by label
on m.desired so ownership is explicit; apply this logic inside the
reconcile/update code paths where client.Get, client.Create, client.Update are
used and inside networkPolicyManager.cleanup before deleting the named policy.

In `@pkg/controllers/c2cc/nftables.go`:
- Around line 161-206: The debounce goroutine is leaked because rawCh is never
closed when unsubscribing; change the returned unsubscribe to a closure that
closes rawCh and then calls sock.Close (use a sync.Once to ensure idempotence)
so the receive goroutine unblocks and the debounce goroutine can exit (refer to
rawCh, reconcileCh, the anonymous debounce goroutine, and sock.Close in your
change).

In `@pkg/controllers/c2cc/policy_routes.go`:
- Around line 41-45: The route reconcile code currently only logs
netlink.RouteReplace/RouteDel failures and always returns nil; update
reconcileRoutes to collect and propagate errors so callers
(linuxRouteManager.reconcile and serviceRouteManager.reconcile) see failures:
inside reconcileRoutes (and the block handling netlink.RouteReplace and
netlink.RouteDel) accumulate any failures (e.g., append to a slice or use
multierror) and return a non-nil error if any netlink operation fails, and
adjust callers that expect reconcileRoutes to return error so they propagate
that error instead of treating reconciliation as success.
- Around line 38-45: The equality check that skips RouteReplace only compares
gateways (actual.Gw == route.Gw) but must also compare the interface index;
update the condition that uses actualByDst/actual to require both
actual.Gw.Equal(route.Gw) AND actual.LinkIndex == route.LinkIndex (or
equivalent) before skipping; this ensures stale routes with a changed ifindex
(e.g., ovn-k8s-mp0 recreated) will be replaced by netlink.RouteReplace and
matches how routes are programmed in service_routes.go.

In `@pkg/controllers/c2cc/service_routes.go`:
- Around line 57-72: The loop is using the single IPv4 gateway returned by
getMgmtPortGateway() for every svc CIDR in m.localSvcCIDRs, which breaks
IPv6/dual‑stack; update the logic to pick a gateway that matches the address
family of each svc CIDR (or have getMgmtPortGateway return gateways per family)
before creating netlink.Route entries: for each svcCIDR in m.localSvcCIDRs,
determine whether dst is IPv4 or IPv6 and use the matching gateway IP (or leave
Gw nil if no same‑family gateway exists) when constructing the netlink.Route
(fields Dst, Gw, Table, Protocol, LinkIndex), so only same‑family next hops are
applied.

In `@test/bin/scenario.sh`:
- Line 1242: The local declaration combines with command substitution (local
var_name="${var_prefix}_$(echo "${prop}" | tr '[:lower:]' '[:upper:]')") which
can hide failures under set -e; fix by splitting into two statements: first
declare the variable (local var_name) and then perform the assignment to
var_name using the command substitution (var_name="${var_prefix}_$(echo
"${prop}" | tr '[:lower:]' '[:upper:]')"), referencing the same var_prefix and
prop variables and the var_name identifier so command-substitution failures
correctly propagate.

In `@test/scenarios-bootc/el9/presubmits/el98-src`@c2cc.sh:
- Around line 132-133: The script copies the cluster-admin kubeadmin kubeconfig
to /tmp and makes it world-readable (chmod 644), which exposes credentials;
change the flow so the kubeconfig remains owned by redhat and only readable by
its owner (mode 0600) or avoid the shared temp file entirely. Update the
run_command_on_vm call that creates /tmp/kubeconfig-b to either set ownership
and permissions (chown redhat && chmod 600) instead of chmod 644, or skip
writing to /tmp and have the scp call pull directly from the source path
(/var/lib/microshift/resources/kubeadmin/${host2_ip}/kubeconfig) so you remove
the temporary shared file; reference the run_command_on_vm invocation and the
scp line that uses "${kubeconfig_b}" when making the change.

In `@test/suites/c2cc/reconciliation.robot`:
- Around line 117-123: Replace the non-disruptive lookup with a disruptive
command to avoid a race between discovery and deletion: change the step that
sets ${handle} which currently uses "Command On Cluster" (running `nft list
chain inet ovn-kubernetes ovn-kube-pod-subnet-masq -a | grep
'c2cc-no-masq:${cidr}' | awk '/# handle/{print $NF}'`) to use "Disruptive
Command On Cluster" instead, so the handle discovery and the subsequent
"Disruptive Command On Cluster    ...    nft delete rule ... handle ${handle}"
both use the disruptive execution path (and consider adding a check for an empty
${handle} before attempting deletion).

---

Nitpick comments:
In `@pkg/controllers/c2cc/nbdb_test.go`:
- Around line 16-41: The tests TestLogicalRouterStaticRoute_FieldTags and
TestLogicalRouter_FieldTags are tautological because they only re-assert values
set in struct literals; replace these with reflection-based assertions that
verify the actual struct field tags (e.g., the ovsdb/model tags) on the types
instead of field values. Use reflect.TypeOf(LogicalRouterStaticRoute{}) and
reflect.TypeOf(LogicalRouter{}) to inspect fields UUID, IPPrefix, Nexthop,
ExternalIDs, Policy and UUID, Name, StaticRoutes respectively, and assert that
Tag.Get("ovsdb") (or the correct tag key used by your OVSDB mapping) equals the
expected tag/schema name for each field; update the test expectations to the
correct tag strings so the tests fail on tag/schema regressions. Ensure you keep
the original test names and replace value assertions with these tag checks.

In `@pkg/controllers/c2cc/ovn.go`:
- Around line 25-28: The current buildNamedUUID uses strings.NewReplacer to
sanitize a few characters but misses other characters (e.g., from IPv6 CIDRs);
change buildNamedUUID to produce a URL-safe deterministic token by encoding the
combined prefix+suffix with a safe encoder: e.g., compute a SHA-256 (or other
stable) hash of prefix+suffix and return its URL-safe base64
(base64.RawURLEncoding.EncodeToString(hash[:])) or, if readability is desired,
return url.PathEscape(prefix+suffix) to percent-encode all unsafe characters;
update the buildNamedUUID function to use one of these approaches so all
possible characters are handled safely.

In `@test/resources/c2cc.resource`:
- Around line 174-180: Replace the fragile Python inline in the "Verify Node
SNAT Annotation" check: instead of piping oc JSON to python3 -c, call Oc On
Cluster to run oc get node with a jsonpath that directly extracts the annotation
key 'k8s.ovn.org/node-ingress-snat-exclude-subnets' (for example using oc get
node -o
jsonpath="{.items[0].metadata.annotations['k8s.ovn.org/node-ingress-snat-exclude-subnets']}")
so ${stdout} contains the annotation value reliably; update the command that
currently uses python3 -c in the test to use this jsonpath form and keep the
subsequent Should Contain assertions unchanged.

In `@test/suites/c2cc/reconciliation.robot`:
- Around line 19-21: The test's reconciliation timeout (${RECONCILE_TIMEOUT}) is
likely too short for slower environments; increase ${RECONCILE_TIMEOUT} (or
adjust ${RECONCILE_RETRY}) so the suite allows more attempts given the
controller's reconcileInterval (~10s). Update the Variables block to set a
larger ${RECONCILE_TIMEOUT} (for example to 60s or more) or reduce
${RECONCILE_RETRY} gap to ensure enough reconciliation attempts relative to
reconcileInterval and event-driven triggers.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 66502359-d58b-4535-b110-837f5171a8be

📥 Commits

Reviewing files that changed from the base of the PR and between 6add7bd and 2834fb9.

⛔ Files ignored due to path filters (179)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cenkalti/backoff/v4/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/backoff.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/context.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/exponential.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/retry.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/ticker.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/timer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/tries.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/hub.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/codec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/debug.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/jsonrpc/jsonrpc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/state.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/.gitattributes is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/.golangci.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/charset/charset.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/csv/parser.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/audio.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/document.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/font.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/geo.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/image.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/netpbm.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ogg.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/markup/markup.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/mime.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/mimetype.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/tree.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/currency/currency.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/rules.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/errors.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/import_export.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/translator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/universal_translator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/MAINTAINERS.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/baked_in.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/cache.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/country_codes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/currency_codes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/errors.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/field_level.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/postcode_regexes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/regexes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/struct_level.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/translations.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/util.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/validator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/validator_instance.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/kind.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/machine.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/machine.go.rl is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/parsing_mode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/scim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/scim/schema/type.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/urn.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/urn8141.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/NOTICE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/cache.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/uuidset.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/api.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/api_test_model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/condition.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/metrics.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/monitor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/validation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/references.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/mapper/info.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/mapper/mapper.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/bindings.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/condition.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/error.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/monitor_select.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/mutation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/named_uuid.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/notation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/row.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/rpc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/schema.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/set.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/update3.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/updates.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/updates2.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/uuid.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/difference.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/merge.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/mutate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/references.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/updates/updates.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/crypto/sha3/hashes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/crypto/sha3/legacy_hash.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/crypto/sha3/legacy_keccakf.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/crypto/sha3/shake.go is excluded by !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/CHANGELOG.md is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/CONTRIBUTING.md is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/OWNERS is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/SECURITY_CONTACTS is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/code-of-conduct.md is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/error.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/exec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/fake.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/nftables.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/objects.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/transaction.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/sigs.k8s.io/knftables/util.go is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (29)
  • go.mod
  • pkg/cmd/run.go
  • pkg/config/c2cc.go
  • pkg/controllers/c2cc/annotation.go
  • pkg/controllers/c2cc/annotation_test.go
  • pkg/controllers/c2cc/controller.go
  • pkg/controllers/c2cc/helpers_test.go
  • pkg/controllers/c2cc/nbdb.go
  • pkg/controllers/c2cc/nbdb_test.go
  • pkg/controllers/c2cc/networkpolicy.go
  • pkg/controllers/c2cc/nftables.go
  • pkg/controllers/c2cc/nftables_test.go
  • pkg/controllers/c2cc/ovn.go
  • pkg/controllers/c2cc/ovn_test.go
  • pkg/controllers/c2cc/policy_routes.go
  • pkg/controllers/c2cc/policy_routes_test.go
  • pkg/controllers/c2cc/routes.go
  • pkg/controllers/c2cc/routes_test.go
  • pkg/controllers/c2cc/service_routes.go
  • pkg/controllers/c2cc/service_routes_test.go
  • test/assets/c2cc/curl-pod.yaml
  • test/assets/c2cc/hello-microshift.yaml
  • test/bin/scenario.sh
  • test/resources/c2cc.resource
  • test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh
  • test/suites/c2cc/connectivity.robot
  • test/suites/c2cc/infrastructure.robot
  • test/suites/c2cc/reconciliation.robot
  • test/suites/c2cc/sanity.robot

Comment thread pkg/controllers/c2cc/annotation.go
Comment thread pkg/controllers/c2cc/nbdb.go Outdated
Comment thread pkg/controllers/c2cc/networkpolicy.go
Comment thread pkg/controllers/c2cc/networkpolicy.go
Comment thread pkg/controllers/c2cc/nftables.go
Comment thread pkg/controllers/c2cc/policy_routes.go
Comment thread pkg/controllers/c2cc/service_routes.go Outdated
Comment thread test/bin/scenario.sh Outdated
Comment thread test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh Outdated
Comment thread test/suites/c2cc/reconciliation.robot
@pmtk
Copy link
Copy Markdown
Member Author

pmtk commented Apr 28, 2026

/test ?

@pmtk
Copy link
Copy Markdown
Member Author

pmtk commented Apr 28, 2026

/test pull-ci-openshift-microshift-main-e2e-aws-tests-bootc-el9

@pmtk
Copy link
Copy Markdown
Member Author

pmtk commented Apr 28, 2026

/test e2e-aws-tests-bootc-arm-el9

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: 2

🧹 Nitpick comments (1)
pkg/controllers/c2cc/nftables.go (1)

187-201: Use a resettable timer for the debounce loop.

time.After creates a new timer for every event and can't be canceled when a newer event arrives. A reusable time.Timer would cut timer churn and make shutdown cleaner.

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

In `@pkg/controllers/c2cc/nftables.go` around lines 187 - 201, Replace the
time.After-based debounce in the goroutine that watches rawCh/reconcileCh with a
reusable time.Timer: create a timer variable (e.g., debounceTimer *time.Timer)
initially nil, on receiving a rawCh event start the timer if nil
(time.NewTimer(2*time.Second)) or call debounceTimer.Reset(2*time.Second) if
already exists, on the timer channel fire send the "nftables-change" to
reconcileCh, and on goroutine shutdown stop the timer and drain its channel if
needed (use debounceTimer.Stop() and drain to avoid races). Ensure you reference
the existing rawCh and reconcileCh identifiers and replace uses of the local
debounce <-chan time.Time with this resettable timer logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controllers/c2cc/nftables.go`:
- Around line 164-167: The current handler tears down the nftables watcher by
returning on a single sock.Receive() error; change it to keep the watcher alive
by replacing the immediate return with a retry/backoff loop that either
continues on transient errors or attempts to recreate the netlink socket (the
sock used for sock.Receive()) and resume receiving; update the logic around
msgs, _, err := sock.Receive() so errors are logged, waited-on with exponential
backoff, and the socket is reinitialized when necessary instead of returning,
ensuring the watcher goroutine does not exit on the first read error.

In `@pkg/controllers/c2cc/policy_routes.go`:
- Around line 67-98: cleanupRoutes and cleanupRules currently swallow deletion
errors (they log but always return nil); change both functions to collect errors
from netlink.RouteDel and netlink.RuleDel (e.g., store the first error or
aggregate multiple errors) and return a non-nil error when any deletion fails.
Specifically, in cleanupRoutes iterate over routes and on netlink.RouteDel
append or wrap the error (include context like route.Dst, t.table) instead of
only klog.Errorf, and similarly in cleanupRules capture errors from
netlink.RuleDel for rules matching t.priority and t.table and return an
aggregated/wrapped error at the end so callers see cleanup failures.

---

Nitpick comments:
In `@pkg/controllers/c2cc/nftables.go`:
- Around line 187-201: Replace the time.After-based debounce in the goroutine
that watches rawCh/reconcileCh with a reusable time.Timer: create a timer
variable (e.g., debounceTimer *time.Timer) initially nil, on receiving a rawCh
event start the timer if nil (time.NewTimer(2*time.Second)) or call
debounceTimer.Reset(2*time.Second) if already exists, on the timer channel fire
send the "nftables-change" to reconcileCh, and on goroutine shutdown stop the
timer and drain its channel if needed (use debounceTimer.Stop() and drain to
avoid races). Ensure you reference the existing rawCh and reconcileCh
identifiers and replace uses of the local debounce <-chan time.Time with this
resettable timer logic.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: ca3c2996-c214-452b-92cd-c6c0af3d6b18

📥 Commits

Reviewing files that changed from the base of the PR and between 2834fb9 and dbf1c5f.

📒 Files selected for processing (5)
  • pkg/controllers/c2cc/annotation.go
  • pkg/controllers/c2cc/nbdb.go
  • pkg/controllers/c2cc/nftables.go
  • pkg/controllers/c2cc/policy_routes.go
  • pkg/controllers/c2cc/service_routes.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/controllers/c2cc/annotation.go
  • pkg/controllers/c2cc/service_routes.go

Comment thread pkg/controllers/c2cc/nftables.go
Comment thread pkg/controllers/c2cc/policy_routes.go
@pmtk
Copy link
Copy Markdown
Member Author

pmtk commented Apr 29, 2026

/test e2e-aws-tests-bootc-arm-el9

pmtk and others added 17 commits April 29, 2026 14:34
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
pmtk and others added 4 commits April 29, 2026 14:34
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@pmtk
Copy link
Copy Markdown
Member Author

pmtk commented Apr 29, 2026

/test e2e-aws-tests-bootc-arm-el9

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: 4

🧹 Nitpick comments (1)
pkg/config/c2cc.go (1)

52-59: Use Resolved for the annotation CIDR list.

Line 52 flattens RemoteClusters, but pkg/controllers/c2cc/controller.go:136-159 feeds every other reconciler from c.Resolved. Inputs like 10.45.1.7/16 get normalized for routes/rules while this annotation still publishes the original string, so the annotation can drift from what the controller actually programs.

Suggested change
 func (c *C2CC) AllRemoteCIDRs() []string {
 	var cidrs []string
-	for _, rc := range c.RemoteClusters {
-		cidrs = append(cidrs, rc.ClusterNetwork...)
-		cidrs = append(cidrs, rc.ServiceNetwork...)
+	for _, rc := range c.Resolved {
+		for _, cidr := range rc.ClusterNetwork {
+			cidrs = append(cidrs, cidr.String())
+		}
+		for _, cidr := range rc.ServiceNetwork {
+			cidrs = append(cidrs, cidr.String())
+		}
 	}
 	return cidrs
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/config/c2cc.go` around lines 52 - 59, The AllRemoteCIDRs method currently
flattens c.RemoteClusters (using rc.ClusterNetwork/ServiceNetwork) which can
differ from the normalized CIDRs the controller actually programs; update
AllRemoteCIDRs to iterate over c.Resolved (the normalized/resolved CIDR entries)
and return those strings instead so the annotation matches what the reconciler
uses (refer to C2CC.AllRemoteCIDRs and the c.Resolved field used by
pkg/controllers/c2cc/controller.go).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controllers/c2cc/controller.go`:
- Around line 161-163: initForCleanup must not ignore errors from
initKubeClient; capture the returned error from initKubeClient() inside
C2CCRouteManager.initForCleanup, and if it fails log the error (use the
controller's logger) and return a safe no-op cleanup function that does not
assume c.annotation or c.netpol were set; only set c.annotation and c.netpol
when initKubeClient succeeds so cleanupAll() is only used when kube setup
completed. Ensure you reference initForCleanup, initKubeClient, c.annotation,
c.netpol and cleanupAll when making the change.

In `@pkg/controllers/c2cc/service_routes.go`:
- Around line 125-150: reconcileRules() currently logs failures from
netlink.RuleAdd and netlink.RuleDel but always returns nil; collect these
failures into an errors slice (e.g., errs := []error{}) when netlink.RuleAdd
returns a non-syscall.EEXIST error and when netlink.RuleDel returns an error,
append the errors and at the end return errors.Join(errs...) (matching the
pattern used in routes.go). Keep existing behavior of skipping EEXIST in the
RuleAdd branch and preserve logging, but ensure the function returns the
aggregated error instead of nil so callers see reconciliation failures;
reference symbols: reconcileRules, netlink.RuleAdd, netlink.RuleDel, ruleKey,
actualKeys, desiredKeys.

In `@test/resources/c2cc.resource`:
- Around line 136-154: The tests Verify IP Rules For Table 200 and Verify
Service IP Rules should assert the controller-managed rule priorities instead of
only checking lookup tables; update the assertions to require the priority
number emitted by `ip rule show` (controller uses priority 100 in
pkg/controllers/c2cc/routes.go for lookup 200 and priority 99 in
pkg/controllers/c2cc/service_routes.go for lookup 201), i.e., ensure the lines
include the priority (100 for rules pointing to lookup 200 and 99 for rules
pointing to lookup 201) together with the CIDR and lookup table in the Should
Contain checks.
- Around line 99-113: The helper "Oc On Cluster" creates a temp file via Create
Random Temp File and never deletes it; after calling Process.Run Process and
reading the file into ${stdout}, call the OperatingSystem keyword Remove File
(Remove File    ${stdout_file}) before RETURN to delete the temp file, and also
add a best-effort cleanup immediately after the rc assertion (e.g., Run Keyword
And Ignore Error    Remove File    ${stdout_file}) so the temp file is removed
even if the test fails; references: Oc On Cluster, ${stdout_file}, Create Random
Temp File, Process.Run Process, Remove File, Run Keyword And Ignore Error.

---

Nitpick comments:
In `@pkg/config/c2cc.go`:
- Around line 52-59: The AllRemoteCIDRs method currently flattens
c.RemoteClusters (using rc.ClusterNetwork/ServiceNetwork) which can differ from
the normalized CIDRs the controller actually programs; update AllRemoteCIDRs to
iterate over c.Resolved (the normalized/resolved CIDR entries) and return those
strings instead so the annotation matches what the reconciler uses (refer to
C2CC.AllRemoteCIDRs and the c.Resolved field used by
pkg/controllers/c2cc/controller.go).
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: ad57e56b-d355-47be-968e-7a293752d024

📥 Commits

Reviewing files that changed from the base of the PR and between dbf1c5f and 1094edf.

⛔ Files ignored due to path filters (147)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cenkalti/backoff/v4/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/backoff.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/context.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/exponential.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/retry.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/ticker.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/timer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/backoff/v4/tries.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/hub/hub.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/codec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/debug.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/jsonrpc/jsonrpc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/cenkalti/rpc2/state.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/.gitattributes is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/.golangci.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/charset/charset.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/csv/parser.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/json/parser.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/archive.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/audio.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/binary.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/document.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/font.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ftyp.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/geo.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/image.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/magic.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ms_office.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/netpbm.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/ogg.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/text.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/text_csv.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/video.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/magic/zip.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/markup/markup.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/internal/scan/bytes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/mime.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/mimetype.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/supported_mimes.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/gabriel-vasile/mimetype/tree.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/currency/currency.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/locales/rules.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/.travis.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/errors.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/import_export.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/translator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/universal-translator/universal_translator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/MAINTAINERS.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/baked_in.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/cache.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/country_codes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/currency_codes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/errors.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/field_level.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/logo.png is excluded by !**/*.png, !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/postcode_regexes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/regexes.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/struct_level.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/translations.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/util.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/validator.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/go-playground/validator/v10/validator_instance.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/kind.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/machine.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/machine.go.rl is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/parsing_mode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/scim.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/scim/schema/type.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/urn.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/leodido/go-urn/urn8141.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/LICENSE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/NOTICE is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/cache.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/cache/uuidset.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/api.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/api_test_model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/condition.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/metrics.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/monitor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/options.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/client/validation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/database/references.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/mapper/info.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/mapper/mapper.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/model/model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/bindings.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/condition.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/error.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/map.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/monitor_select.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/mutation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/named_uuid.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/notation.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/row.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/rpc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/schema.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/database.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/gen.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/serverdb/model.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/ovn-kubernetes/libovsdb/ovsdb/set.go is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (29)
  • go.mod
  • pkg/cmd/run.go
  • pkg/config/c2cc.go
  • pkg/controllers/c2cc/annotation.go
  • pkg/controllers/c2cc/annotation_test.go
  • pkg/controllers/c2cc/controller.go
  • pkg/controllers/c2cc/helpers_test.go
  • pkg/controllers/c2cc/nbdb.go
  • pkg/controllers/c2cc/nbdb_test.go
  • pkg/controllers/c2cc/networkpolicy.go
  • pkg/controllers/c2cc/nftables.go
  • pkg/controllers/c2cc/nftables_test.go
  • pkg/controllers/c2cc/ovn.go
  • pkg/controllers/c2cc/ovn_test.go
  • pkg/controllers/c2cc/policy_routes.go
  • pkg/controllers/c2cc/policy_routes_test.go
  • pkg/controllers/c2cc/routes.go
  • pkg/controllers/c2cc/routes_test.go
  • pkg/controllers/c2cc/service_routes.go
  • pkg/controllers/c2cc/service_routes_test.go
  • test/assets/c2cc/curl-pod.yaml
  • test/assets/c2cc/hello-microshift.yaml
  • test/bin/scenario.sh
  • test/resources/c2cc.resource
  • test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh
  • test/suites/c2cc/connectivity.robot
  • test/suites/c2cc/infrastructure.robot
  • test/suites/c2cc/reconciliation.robot
  • test/suites/c2cc/sanity.robot
✅ Files skipped from review due to trivial changes (3)
  • test/assets/c2cc/curl-pod.yaml
  • test/assets/c2cc/hello-microshift.yaml
  • pkg/controllers/c2cc/helpers_test.go
🚧 Files skipped from review as they are similar to previous changes (12)
  • pkg/cmd/run.go
  • pkg/controllers/c2cc/annotation_test.go
  • pkg/controllers/c2cc/policy_routes_test.go
  • pkg/controllers/c2cc/networkpolicy.go
  • pkg/controllers/c2cc/routes_test.go
  • test/suites/c2cc/connectivity.robot
  • pkg/controllers/c2cc/service_routes_test.go
  • pkg/controllers/c2cc/nbdb_test.go
  • pkg/controllers/c2cc/policy_routes.go
  • test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh
  • pkg/controllers/c2cc/ovn.go
  • pkg/controllers/c2cc/nftables_test.go

Comment thread pkg/controllers/c2cc/controller.go
Comment thread pkg/controllers/c2cc/service_routes.go Outdated
Comment thread test/resources/c2cc.resource
Comment thread test/resources/c2cc.resource
CLUSTER_B_SVC_CIDR="10.46.0.0/16"
CLUSTER_B_DOMAIN="cluster-b.remote"

configure_c2cc_hosts() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

every line in this func is duplicated for both host.
can we run it twice with hostA and hostB params? or should this done in a particular order? because it waits for greenboot and restart microshift I guess not, but it feels weird having all lines duplicated twice

plus: are we planning testing with 3 VMs in the future?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

addressed the duplication
as for 3 VMs: potentially yes, maybe for GA? didn't have specific plans for it yet

pmtk and others added 3 commits April 29, 2026 16:49
The node watch was triggering a full reconcile on every node
modification (scheduling, status, labels). Now it extracts the
node object from the watch event and only signals when the SNAT
annotation actually differs from the desired value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The debounce goroutine relied on rawCh being closed (via
sock.Close -> Receive error -> reader return) to exit. Now it
selects on ctx.Done() directly, so shutdown is explicit and
doesn't depend on the error-handling cascade.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When multiple events queue in the buffered reconcileCh, each
one was triggering a separate full reconcile. Now the loop
drains all pending events before running one reconcile,
reducing redundant work under churn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh Outdated
Comment thread test/suites/c2cc/connectivity.robot Outdated
Comment thread test/suites/c2cc/infrastructure.robot
Comment thread test/suites/c2cc/reconciliation.robot Outdated
Comment thread test/suites/c2cc/sanity.robot Outdated
@agullon
Copy link
Copy Markdown
Contributor

agullon commented Apr 30, 2026

I reviewed test/ dir and it looks to me
looking forward for CI runs to check the RF logs

pmtk and others added 4 commits April 30, 2026 09:43
- Log warning when kube client init fails during cleanup
- Propagate service rule reconciliation failures (matching routes.go pattern)
- Replace inline Python with jsonpath in SNAT annotation test

Co-Authored-By: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The annotation manager now treats k8s.ovn.org/node-ingress-snat-exclude-subnets
as shared state. A tracking annotation (microshift.io/c2cc-snat-subnets) records
which CIDRs C2CC last wrote, so reconcile merges only our entries and cleanup
removes only our entries, preserving subnets added by other components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a cleanup.robot suite that disables C2CC by moving the config
drop-in aside, restarts MicroShift, and verifies all networking state
(routes, rules, nftables, OVN routes, annotations, NetworkPolicy) is
removed. Teardown restores the config so subsequent suites are unaffected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controllers/c2cc/controller.go`:
- Around line 100-103: The ready channel is closed before any reconciliation
runs, so move the readiness signal until after the first reconciliation
completes: call c.fullReconcile(ctx) first, wait for it to return
(handle/propagate or log any error), and only then call close(ready) and
klog.Infof("Ready..."); update the sequence around the ready variable and the
c.fullReconcile(ctx) invocation in controller.go so dependents see the service
as ready only after the initial routes/rules/nftables/NetworkPolicy have been
applied.

In `@pkg/controllers/c2cc/ovn.go`:
- Around line 186-189: The cleanup code currently only checks the
transport-level error from m.nbClient.Transact(ctx, ops...) and ignores
per-operation OVSDB errors; update the cleanup path (same place that handles
route removal around route.UUID) to inspect the returned transaction result for
per-op errors (like reconcile() does), log any operation-level failures with
klog.Errorf including route.UUID and the op error details, and append those
errors to errs so stale routes are not treated as successfully removed.

In `@test/scenarios-bootc/el9/presubmits/el98-src`@c2cc.sh:
- Around line 98-106: Replace the direct scp call with the existing
copy_file_from_vm helper so IPv6 wrapping is preserved: after
wait_for_microshift_to_be_ready(host2) keep the run_command_on_vm host2 that
creates and chmods /tmp/kubeconfig-b using ${host2_ip}, then call
copy_file_from_vm host2 "/tmp/kubeconfig-b" "${kubeconfig_b}" instead of scp -P
"${host2_ssh_port}" ...; remove the scp invocation and any manual use of
host2_ssh_port/host2_ip for fetching the file.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 731ce12b-f90a-4ba9-858e-ae6e502c9e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 1094edf and 41e3ab2.

📒 Files selected for processing (18)
  • pkg/controllers/c2cc/annotation.go
  • pkg/controllers/c2cc/annotation_test.go
  • pkg/controllers/c2cc/controller.go
  • pkg/controllers/c2cc/nbdb.go
  • pkg/controllers/c2cc/networkpolicy.go
  • pkg/controllers/c2cc/nftables.go
  • pkg/controllers/c2cc/ovn.go
  • pkg/controllers/c2cc/policy_routes.go
  • pkg/controllers/c2cc/routes.go
  • pkg/controllers/c2cc/service_routes.go
  • test/bin/scenario.sh
  • test/resources/c2cc.resource
  • test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh
  • test/suites/c2cc/cleanup.robot
  • test/suites/c2cc/connectivity.robot
  • test/suites/c2cc/infrastructure.robot
  • test/suites/c2cc/reconciliation.robot
  • test/suites/c2cc/sanity.robot
✅ Files skipped from review due to trivial changes (2)
  • test/suites/c2cc/connectivity.robot
  • pkg/controllers/c2cc/policy_routes.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • pkg/controllers/c2cc/networkpolicy.go
  • pkg/controllers/c2cc/nbdb.go
  • pkg/controllers/c2cc/service_routes.go
  • pkg/controllers/c2cc/routes.go
  • test/resources/c2cc.resource

Comment thread pkg/controllers/c2cc/controller.go
Comment thread pkg/controllers/c2cc/ovn.go Outdated
Comment thread test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh Outdated
pmtk and others added 2 commits April 30, 2026 19:39
The cleanup path only checked transport-level errors from Transact(),
silently ignoring per-operation OVSDB errors. Mirror the reconcile path
by inspecting each result for operation-level failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace raw scp with copy_file_from_vm helper which handles IPv6
address wrapping, preparing for future dual-stack test scenarios.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@pmtk pmtk marked this pull request as ready for review April 30, 2026 17:48
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 30, 2026
@openshift-ci openshift-ci Bot requested review from pacevedom and vanhalenar April 30, 2026 17:48
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/scenarios-bootc/el9/presubmits/el98-src`@c2cc.sh:
- Around line 58-63: The calls to wait_for_greenboot_on_hosts and
wait_for_microshift_to_be_ready currently rely on global errexit; change each
invocation (e.g. wait_for_greenboot_on_hosts "c2cc_pre_greenboot",
wait_for_greenboot_on_hosts "c2cc_greenboot", and
wait_for_microshift_to_be_ready) to perform an explicit return-code check: run
the function, test its exit status with if ! <call>; then emit a clear error
message (e.g. via echo or logger) and exit or return a non-zero status (exit 1)
to fail fast; keep configure_c2cc_host calls unchanged but ensure subsequent
waits follow this explicit-check pattern.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: c46ac14a-0f05-4c99-b70d-121c97d50990

📥 Commits

Reviewing files that changed from the base of the PR and between 41e3ab2 and 22dbfdd.

📒 Files selected for processing (2)
  • pkg/controllers/c2cc/ovn.go
  • test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh
✅ Files skipped from review due to trivial changes (1)
  • pkg/controllers/c2cc/ovn.go

Comment on lines +58 to +63
wait_for_greenboot_on_hosts "c2cc_pre_greenboot"

configure_c2cc_host host1 "${host2_ip}" "${CLUSTER_B_POD_CIDR}" "${CLUSTER_B_SVC_CIDR}" "${CLUSTER_B_DOMAIN}"
configure_c2cc_host host2 "${host1_ip}" "${CLUSTER_A_POD_CIDR}" "${CLUSTER_A_SVC_CIDR}" "${CLUSTER_A_DOMAIN}"

wait_for_greenboot_on_hosts "c2cc_greenboot"
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
# Verify whether this script currently depends on global errexit behavior.

echo "== Check scenario framework shell options =="
fd -i 'scenario.sh' test | while read -r f; do
  echo "--- ${f}"
  rg -n -C2 'set -e|set -o errexit|set -u|pipefail' "${f}"
done

echo
echo "== Check unguarded wait calls in this scenario =="
rg -n -C2 'wait_for_greenboot_on_hosts|wait_for_microshift_to_be_ready' \
  "test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh"

Repository: openshift/microshift

Length of output: 1140


🏁 Script executed:

#!/bin/bash
# Verify script sourcing and errexit dependencies

echo "=== Check script header and sourcing ==="
head -30 "test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh"

echo
echo "=== Check for errexit disabling in the script ==="
rg -n 'set \+e|set -o posix' "test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh"

echo
echo "=== Check wait_for_greenboot_on_hosts and wait_for_microshift_to_be_ready implementation ==="
rg -n -A15 'wait_for_greenboot_on_hosts\(\)' "test/scenarios-bootc/el9/presubmits/el98-src@c2cc.sh"

echo
rg -n -A10 'wait_for_microshift_to_be_ready\(\)' "test/bin/scenario.sh"

Repository: openshift/microshift

Length of output: 1943


🏁 Script executed:

rg -n -A30 'wait_for_microshift_to_be_ready\(\)' "test/bin/scenario.sh"

Repository: openshift/microshift

Length of output: 1139


Add explicit error handling for wait call failures.

The script sources scenario.sh which sets errexit, but relies on this global setting to catch failures from wait_for_greenboot_on_hosts() at lines 58 and 63. This creates fragile dependencies on upstream shell options. The wait_for_microshift_to_be_ready() call at line 102 has the same issue. Wrap these calls with explicit return checks:

Suggested fix
 configure_c2cc_hosts() {
     local -r host1_ip=$(get_vm_property host1 ip)
     local -r host2_ip=$(get_vm_property host2 ip)
 
-    wait_for_greenboot_on_hosts "c2cc_pre_greenboot"
+    if ! wait_for_greenboot_on_hosts "c2cc_pre_greenboot"; then
+        return 1
+    fi
 
     configure_c2cc_host host1 "${host2_ip}" "${CLUSTER_B_POD_CIDR}" "${CLUSTER_B_SVC_CIDR}" "${CLUSTER_B_DOMAIN}"
     configure_c2cc_host host2 "${host1_ip}" "${CLUSTER_A_POD_CIDR}" "${CLUSTER_A_SVC_CIDR}" "${CLUSTER_A_DOMAIN}"
 
-    wait_for_greenboot_on_hosts "c2cc_greenboot"
+    if ! wait_for_greenboot_on_hosts "c2cc_greenboot"; then
+        return 1
+    fi
 }
@@
-    wait_for_microshift_to_be_ready host2
+    if ! wait_for_microshift_to_be_ready host2; then
+        return 1
+    fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/scenarios-bootc/el9/presubmits/el98-src`@c2cc.sh around lines 58 - 63,
The calls to wait_for_greenboot_on_hosts and wait_for_microshift_to_be_ready
currently rely on global errexit; change each invocation (e.g.
wait_for_greenboot_on_hosts "c2cc_pre_greenboot", wait_for_greenboot_on_hosts
"c2cc_greenboot", and wait_for_microshift_to_be_ready) to perform an explicit
return-code check: run the function, test its exit status with if ! <call>; then
emit a clear error message (e.g. via echo or logger) and exit or return a
non-zero status (exit 1) to fail fast; keep configure_c2cc_host calls unchanged
but ensure subsequent waits follow this explicit-check pattern.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 30, 2026

@pmtk: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-tests-bootc-periodic-el10 22dbfdd link true /test e2e-aws-tests-bootc-periodic-el10
ci/prow/e2e-aws-tests-bootc-el9 22dbfdd link true /test e2e-aws-tests-bootc-el9
ci/prow/e2e-aws-tests-bootc-arm-el10 22dbfdd link true /test e2e-aws-tests-bootc-arm-el10
ci/prow/ocp-full-conformance-rhel-eus 22dbfdd link true /test ocp-full-conformance-rhel-eus
ci/prow/e2e-aws-tests-bootc-arm-el9 22dbfdd link true /test e2e-aws-tests-bootc-arm-el9
ci/prow/test-unit 22dbfdd link true /test test-unit
ci/prow/verify 22dbfdd link true /test verify
ci/prow/e2e-aws-tests-bootc-periodic-arm-el9 22dbfdd link true /test e2e-aws-tests-bootc-periodic-arm-el9
ci/prow/e2e-aws-tests-bootc-el10 22dbfdd link true /test e2e-aws-tests-bootc-el10
ci/prow/ocp-full-conformance-serial-rhel-eus 22dbfdd link true /test ocp-full-conformance-serial-rhel-eus

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants