Skip to content

feat: label-only selector and port-filter default - #13

Merged
Andrei Kvapil (kvaps) merged 1 commit into
mainfrom
fix/default-port-filter
Apr 28, 2026
Merged

Andrei Kvapil (kvaps) merged 1 commit into
mainfrom
fix/default-port-filter

Conversation

@kvaps

@kvaps Andrei Kvapil (kvaps) commented Apr 28, 2026 •

Copy link
Copy Markdown
Member

Summary

Tightens the management contract before the next release:

  1. Label is the sole selector. Services without service.kubernetes.io/service-proxy-name: cozy-proxy are no longer managed, even if they carry networking.cozystack.io/wholeIP. The annotation alone has no selecting effect anymore.
  2. Port-filter is the default mode. wholeIPPassthrough is now an explicit opt-in via wholeIP: "true". Absent or any other value falls into per-port filtering, so a Service's declared spec.ports are the only ports cozy-proxy forwards by default.

Drops the now-unused hasWholeIPAnnotation helper. Tests cover the new selector and the new default. README rewritten — drops the dual-selector narrative, removes the "Which selector should I use?" section, marks port-filter as default, and updates the Usage example to include wholeIP: "true" so the bogus-port-65535 passthrough demonstration still makes sense.

Breaking changes

  • Services using the wholeIP annotation without the service-proxy-name label are no longer managed. Add the label.
  • Services that relied on the absent-annotation default (passthrough) now fall back to port-filter. Add networking.cozystack.io/wholeIP: "true" to keep the previous behavior.

Both behaviors are recent (#9, #11), unreleased, so the breakage scope is limited to in-tree consumers.

Test plan

  • Unit tests pass
  • Service with label only, no annotation, declared spec.ports: [22]: only port 22 reachable
  • Service with label + wholeIP: "true": all ports reachable
  • Service with wholeIP annotation only, no label: not managed (no rules created)
  • Service with label + wholeIP: "false" + allowICMP: "true": ports 22 + ICMP work

Summary by CodeRabbit

  • Documentation

    • Updated service selection and configuration guidance.
  • Changes

    • Service selection now relies on a single label instead of multiple selectors.
    • Default behavior changed to per-port filtering; whole-IP passthrough now requires explicit configuration.
    • Updated configuration examples to reflect new requirements.

Tighten the management contract for cozy-proxy:

- The service.kubernetes.io/service-proxy-name=cozy-proxy label is now
  the sole selector. Services without the label are no longer managed
  even if they carry the networking.cozystack.io/wholeIP annotation —
  the annotation alone has no selecting effect.
- Whole-IP passthrough becomes opt-in: wholeIPPassthrough returns true
  only for explicit wholeIP="true". Absent or any other value keeps the
  service in port-filter mode (consistent with wholeIP="false"), so
  declared Service.spec.ports are the only ports forwarded by default.

Drop the now-unused hasWholeIPAnnotation helper. Tests updated to cover
the new isCozyProxyService selector and the new wholeIPPassthrough
default. README rewritten: drop the dual-selector narrative and the
"Which selector should I use?" section, update the ingress-mode table
to mark port-filter as the default, and add wholeIP="true" to the
Usage example so the bogus port-65535 demonstration of whole-IP
behaviour keeps working.

BREAKING CHANGE: Services that previously relied on the wholeIP
annotation alone for selection must add the
service.kubernetes.io/service-proxy-name: cozy-proxy label. Services
that previously relied on the absent-annotation passthrough default
must add networking.cozystack.io/wholeIP: "true" to keep that
behaviour.

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
@kvaps
Andrei Kvapil (kvaps) merged commit 52fc7e7 into main Apr 28, 2026
1 check passed
@coderabbitai

coderabbitai Bot commented Apr 28, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 16699019-a29e-4308-a59c-ed276ea27ede

📥 Commits

Reviewing files that changed from the base of the PR and between 1b459f6 and 23ffd6d.

📒 Files selected for processing (3)
  • README.md
  • pkg/controllers/services_controller.go
  • pkg/controllers/services_controller_test.go

📝 Walkthrough

Walkthrough

The changes simplify service selection to depend solely on the service.kubernetes.io/service-proxy-name: cozy-proxy label, removing the wholeIP annotation as a selection criterion. The default behavior for wholeIPPassthrough shifts from true (passthrough mode) to false (port-filter mode), requiring explicit annotation to enable passthrough. Documentation and tests are updated accordingly.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updated to clarify that service.kubernetes.io/service-proxy-name: cozy-proxy is the sole selector for cozy-proxy management. Removed guidance on alternative selectors. Documented that per-port filtering is now the default, with whole-IP passthrough requiring explicit networking.cozystack.io/wholeIP: "true" annotation.
Service Controller Logic
pkg/controllers/services_controller.go
Modified service selection to use only the service.kubernetes.io/service-proxy-name label, removing wholeIP annotation-based selection. Changed wholeIPPassthrough default from true to false, now opting into passthrough only when explicitly set to "true".
Test Suite
pkg/controllers/services_controller_test.go
Replaced annotation-based selection test with TestIsCozyProxyService to verify label-based selection. Updated TestWholeIPPassthrough expectations to reflect new default behavior (false instead of true) and explicit value requirements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A label so clear, one selector to reign,
No more ambiguity causing the brain pain,
Port-filter by default, the sensible way,
Passthrough calls loudly—when you have it to say! 🎯

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/default-port-filter

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the service selection logic for cozy-proxy, making the 'service.kubernetes.io/service-proxy-name: cozy-proxy' label the sole requirement for service management. The 'networking.cozystack.io/wholeIP' annotation now only controls the ingress mode, with the default behavior changing from whole-IP passthrough to per-port filtering. Corresponding updates were made to the documentation and unit tests to align with these logic changes. I have no feedback to provide.

Andrei Kvapil (kvaps) added a commit to cozystack/cozystack that referenced this pull request Apr 28, 2026
Bumps the vendored cozy-proxy chart and image tag from v0.2.0 to v0.3.0
by running `make update` in `packages/system/cozy-proxy`.

cozy-proxy v0.3.0 release:
https://github.com/cozystack/cozy-proxy/releases/tag/v0.3.0

## Why

cozy-proxy v0.3.0 is the companion of #2501. The chart fix in #2501
finally honors the documented PortList semantics (only `externalPorts`
reachable, ICMP preserved by default), but only takes effect once
cozy-proxy v0.3.0 is in place — v0.2.0 has no port-aware logic, so the
chart fix silently no-ops on it. This PR ships that runtime side.

## Upgrade impact

For cozystack users this is a **bug fix, not a breaking change**.
cozy-proxy v0.3.0 introduces two contract changes upstream — (1)
label-only selector via `service.kubernetes.io/service-proxy-name:
cozy-proxy`, and (2) port-filter as the default ingress mode — both of
which are absorbed by the vm-instance chart (label landed in #2357,
`wholeIP` + `allowICMP` wired in #2501).

- **`externalMethod: WholeIP`** (default) — chart renders label +
`wholeIP: "true"` in both old and new versions. cozy-proxy keeps
passthrough. **No change.**
- **`externalMethod: PortList`** — previously the chart always rendered
`wholeIP: "true"` regardless of method, and cozy-proxy v0.2.0 had no
port-aware logic, so PortList was silently a no-op (all ports
reachable). After this bump + #2501, PortList behaves as documented:
only ports listed in `externalPorts` reach the VM. Users who configured
PortList but reached undeclared ports (relying on the silent no-op) will
see those ports become unreachable — that's the documented intent of
PortList finally taking effect. ICMP keeps working by default thanks to
`externalAllowICMP: true`.
- **DaemonSet rollover** — re-init of the nft table during cozy-proxy
pod restart is a brief blip on existing flows; same as any DaemonSet
upgrade.

Out-of-tree consumers using cozy-proxy directly (without the
`service-proxy-name` label, or relying on the absent-annotation
passthrough default) need to migrate per the upstream v0.3.0 release
notes — not a cozystack concern.

## Order of operations

This PR is functionally complete on its own (image bump), but the
user-facing PortList fix it enables only happens when #2501 also lands.
Recommended merge order:

1. #2501 first (chart adapts to the new contract)
2. This PR second (cozy-proxy DaemonSet picks up the new image)

The reverse order is also safe — cozy-proxy v0.3.0 with the unmodified
vm-instance chart still produces correct results for `externalMethod:
WholeIP` (most common case) and keeps PortList silently broken until
#2501 lands.

## Test plan

- [ ] `helm template packages/system/cozy-proxy` — image tag `v0.3.0`
rendered
- [ ] `make unit-tests` passes
- [ ] After #2501 lands, end-to-end: `externalMethod: PortList` with
`externalPorts: [22]` filters all other ports, ping works
- [ ] WholeIP-method VM Service unchanged after upgrade

## Companion PRs

- #2501 — vm-instance chart wires `wholeIP` / `allowICMP` per
`externalMethod`
- cozystack/cozy-proxy#13 (merged) — label-only selector + port-filter
default
- cozy-proxy v0.3.0 release notes —
https://github.com/cozystack/cozy-proxy/releases/tag/v0.3.0

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Released version 0.3.0 with updated Helm chart metadata and container
image configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant