Skip to content

fix(controller): add container ports so workloads can be targeted by name - #4382

Merged
chathuranga95 merged 2 commits into
openchoreo:mainfrom
kavix:fix-4329-container-ports-clean
Sep 29, 2026
Merged

chathuranga95 merged 2 commits into
openchoreo:mainfrom
kavix:fix-4329-container-ports-clean

Conversation

@kavix

@kavix kavix commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Purpose

Workload endpoints currently render into a Service with a named port and a numeric targetPort, but the generated container spec does not include a ports: block.

This means the pod does not explicitly declare the port, causing features that resolve ports by name against the pod spec to fail silently. For example:

  • Linkerd Server resources cannot bind to the port.
  • Named NetworkPolicy / CiliumNetworkPolicy port rules resolve to zero ports and may be denied under a default-deny baseline.
  • Port-constraining admission policies cannot validate the intended port.
  • Prometheus pod-role scraping requires relabeling workarounds to synthesize target ports.

This PR adds container port definitions derived from workload endpoints and ensures Service targetPort references resolve correctly.

Fixes #4329

Approach

  • Added buildContainerPorts() in internal/pipeline/component/context/derived.go.

    • Creates a derived view that generates one named container port per workload endpoint.
    • Reuses the existing sanitization and deduplication logic from buildServicePorts() to ensure generated Kubernetes port names are valid and unique.
  • Added a new workload.toContainerPorts() CEL macro in cel_extensions.go.

    • Mirrors the existing toServicePorts() macro.
  • Updated ServicePortEntry.TargetPort.

    • Changed it from a raw numeric port value to the name of the matching container port.
    • Ensures rendered Services target ports explicitly declared by the pod.
  • Added ports: ${workload.toContainerPorts()} to container specifications in built-in ClusterComponentType templates under samples/:

    • service
    • webapp
    • grpc-service
    • tls-service
    • http-openapi-service
    • component-with-configs
    • component-with-embedded-traits
  • containerPort is informational only and does not affect application bindings or traffic routing.

    • Existing workloads only require a rolling restart during upgrade.
    • No runtime behavior changes are introduced.

Related Issues

Fixes #4329

Checklist

  • Tests added or updated (unit, integration, etc.)
  • Samples updated (if applicable)
  • Added backport/<release-branch> label if this should be backported (e.g., backport/release-v1.0)
  • This PR includes AI-generated code or content

Remarks

Container ports are named after endpoint keys so that workloads with multiple endpoints on the same port number but different visibility settings receive separate container port entries.

Kubernetes allows multiple named container ports with the same port number, so container ports are not deduplicated by port + protocol like Service ports.

Each endpoint requires its own unique name because the Service targetPort must resolve to the corresponding container port name.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openchoreo/openchoreo/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 2828eab0-e235-4cf8-8e45-0c454c5998ec

📥 Commits

Reviewing files that changed from the base of the PR and between e2440c9 and 85967f4.

📒 Files selected for processing (5)
  • internal/pipeline/component/context/cel_extensions_test.go
  • internal/pipeline/component/context/cel_integration_test.go
  • samples/getting-started/all.yaml
  • samples/getting-started/component-types/service.yaml
  • samples/getting-started/component-types/webapp.yaml

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Summary

Summary

  • Added a named container port for each workload endpoint.
  • Sanitized endpoint keys and generated unique port names when sanitized keys collide.
  • Changed Service targetPort values to reference the matching container port name.
  • Added workload.toContainerPorts() and used it in built-in component templates.
  • Container ports do not change application bindings or traffic routing. The pod template changes trigger a rolling restart. Services may temporarily have no ready endpoints as updated pods start.

Changed files

Top-level folder Files
internal/ 5
samples/ 8
api/ 0
config/ 0
pkg/ 0
install/ 0
docs/ 0
openapi/ 0
agents/ 0
make/ 0
cmd/ 0
Total 13

API and CRD surface

  • Changed exported ServicePortEntry.TargetPort from int64 to string.
  • Added exported ContainerPortEntry, with Name, ContainerPort, and Protocol fields.
  • Added ContainerPorts to DerivedContext.
  • Added the workload.toContainerPorts() CEL macro.
  • No Kubernetes API or CRD schema files changed.
  • Compatibility risk: Medium. Consumers of the exported Go types or derived context may need updates. Pod template changes trigger a rollout, and Services now require matching named ports on ready pods.

Tests

Updated or added tests for:

  • Service port target names across HTTP, gRPC, and UDP endpoints.
  • Target-port defaults, differing service and target ports, sanitized names, and name collisions.
  • The workload.toContainerPorts() macro and its receiver guard.
  • CEL integration output for named Service targets and container ports.
  • Non-nil ContainerPorts in an empty derived context.

The supplied changes do not show tests for rendered Deployment or Pod output, rollout behavior, or integration with Linkerd, NetworkPolicy, CiliumNetworkPolicy, admission policies, or Prometheus pod-role scraping. No test execution results were provided.

Risk hotspots

  • Reconciliation and rollout: The pod template change causes existing Deployments to roll out.
  • Traffic routing: Service target names must match the container port names on ready pods. A Service update before replacement pods are ready can cause a temporary endpoint gap.
  • Authn/authz and policy integration: The new named ports enable integrations such as Linkerd Server bindings and named network-policy rules. No direct authentication or authorization policy changes are shown.
  • RBAC: No RBAC changes are shown.
  • Secrets: No secret handling changes are shown.
  • Install and upgrade paths: No installer or upgrade files changed. Existing workloads still need the rollout that adds their declared container ports.

Walkthrough

The pipeline derives named container ports from workload endpoints and uses their names as service targetPort values. A CEL macro exposes the derived ports. Sample Deployment templates render those ports in container specifications.

Changes

Named container port rendering

Layer / File(s) Summary
Derive container ports and map service targets
internal/pipeline/component/context/cel_return_types.go, internal/pipeline/component/context/derived.go
Adds ContainerPortEntry and changes ServicePortEntry.TargetPort to a string. Derives deterministic container port entries and maps endpoint names to service target ports.
Expose and test port macros
internal/pipeline/component/context/cel_extensions.go, internal/pipeline/component/context/cel_extensions_test.go, internal/pipeline/component/context/cel_integration_test.go
Registers workload.toContainerPorts() and uses a shared workload identifier for receiver matching. Tests cover named service targets, generated container ports, receiver checks, and empty inputs.
Render container ports in sample templates
samples/component-types/*, samples/getting-started/component-types/*, samples/getting-started/all.yaml
Adds container ports fields populated by workload.toContainerPorts().

Priority: ⚪ Not assessed

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant DeploymentTemplate
  participant toContainerPortsMacro
  participant DerivedContext
  participant ServiceTemplate
  participant toServicePortsMacro
  DeploymentTemplate->>toContainerPortsMacro: evaluate workload.toContainerPorts()
  toContainerPortsMacro->>DerivedContext: select containerPorts
  DerivedContext-->>DeploymentTemplate: container port entries
  ServiceTemplate->>toServicePortsMacro: evaluate workload.toServicePorts()
  toServicePortsMacro->>DerivedContext: select servicePorts
  DerivedContext-->>ServiceTemplate: service ports with named targetPort
Loading

Merge Risk: ⚪ Minimal · up to 85967

The change adds named container ports to sample Deployments and points Service target ports at those names. No concrete merge-blocking issue was found. As the PR notes, existing workloads need a rolling restart when they pick up the new pod template.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 85967

The updated examples render matching ports, but existing workloads may temporarily or permanently lack the declarations required by the new Service targets. That could interrupt traffic during upgrades or when older templates remain in use. No security bypass was established.

Retained concerns

  • Medium · architecture · inferred: Existing templates or pods without the new named container ports can be incompatible with Services rendered using named target ports. The supplied evidence does not establish a migration or rollout gate that prevents this mismatch.
Security review details

Security Blast Radius

  • inferred — The demonstrated effect is on Service-to-pod port resolution for workloads using the changed template contract. The supplied evidence does not establish an attacker-controlled route or cross-tenant exposure.

Trust Boundaries and Controls

  • observed — The tested CEL receiver restriction rejects toContainerPorts() on an unrelated receiver; no changed test range establishes a new authentication or privilege boundary.

Resilience and Maintainability Implications

  • inferred — Uncoordinated adoption of named Service targets and named pod ports could disrupt availability during a mixed-version rollout; actual reconciliation ordering and recovery behavior are not established.

Hardening Proposals

  • proposed — Before changing a Service to named targets, verify that its selected pod templates declare matching names, and define upgrade and rollback handling for existing templates and pods.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title uses the required Conventional Commits format and clearly describes the main change: adding container ports so workloads can be targeted by name.
Description check ✅ Passed The description includes all required sections. It explains the problem, solution, related issue, testing and sample updates, AI-generated content, and additional context.
Linked Issues check ✅ Passed The PR meets the coding requirements in [#4329]. buildContainerPorts creates one named ContainerPortEntry for each workload endpoint, uses sanitized and collision-safe endpoint names, and sets the…
Out of Scope Changes check ✅ Passed The changed context code, CEL registration, tests, and component templates directly support [#4329]. The tests and shared derivation logic are supporting implementation. The available PR summary shows…
Full details: Docstring Coverage

Explanation

Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

@kavix kavix changed the title fix(renderer): add container ports so workloads can be targeted by name fix(controller): add container ports so workloads can be targeted by name Jul 31, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
internal/pipeline/component/context/cel_extensions_test.go (1)

600-694: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add container-port edge-case coverage.

The new coverage checks only the default case where TargetPort equals Port. Add cases where TargetPort differs from Port, where the protocol is UDP, and where sanitized endpoint names collide. These cases verify that each Service targetPort names a declared container port.

As per path instructions, "Add tests for critical logic or regressions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/pipeline/component/context/cel_extensions_test.go` around lines 600
- 694, Add edge-case table entries to TestWorkloadEndpointsToServicePortsMacro
for endpoints whose TargetPort differs from Port, a UDP endpoint with a distinct
target port, and multiple endpoint names that sanitize to the same value. Assert
each generated Service targetPort references the declared container-port name
and verify the expected collision-handling behavior.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/pipeline/component/context/cel_return_types.go`:
- Line 95: Run gofmt on the file containing the TargetPort field to remove
trailing whitespace and apply standard Go formatting, including any required
import grouping.

---

Outside diff comments:
In `@internal/pipeline/component/context/cel_extensions_test.go`:
- Around line 600-694: Add edge-case table entries to
TestWorkloadEndpointsToServicePortsMacro for endpoints whose TargetPort differs
from Port, a UDP endpoint with a distinct target port, and multiple endpoint
names that sanitize to the same value. Assert each generated Service targetPort
references the declared container-port name and verify the expected
collision-handling behavior.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ff845436-fa8c-4818-9ff5-917e8cb74652

📥 Commits

Reviewing files that changed from the base of the PR and between d23d0ff and bdb5ae2.

📒 Files selected for processing (12)
  • internal/pipeline/component/context/cel_extensions.go
  • internal/pipeline/component/context/cel_extensions_test.go
  • internal/pipeline/component/context/cel_integration_test.go
  • internal/pipeline/component/context/cel_return_types.go
  • internal/pipeline/component/context/derived.go
  • samples/component-types/component-grpc-service/grpc-service-component.yaml
  • samples/component-types/component-http-openapi-service/http-openapi-service-component.yaml
  • samples/component-types/component-tls-service/tls-service-component.yaml
  • samples/component-types/component-with-configs/component-with-configs.yaml
  • samples/component-types/component-with-embedded-traits/component-with-embedded-traits.yaml
  • samples/getting-started/component-types/service.yaml
  • samples/getting-started/component-types/webapp.yaml

Comment thread internal/pipeline/component/context/cel_return_types.go Outdated
@codecov

codecov Bot commented Jul 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kavix
kavix force-pushed the fix-4329-container-ports-clean branch from bdb5ae2 to 6510567 Compare July 31, 2026 13:10
kavix added a commit to kavix/openchoreo that referenced this pull request Aug 1, 2026
@kavix
kavix force-pushed the fix-4329-container-ports-clean branch from e2440c9 to 13feae2 Compare August 1, 2026 08:38
kavix added a commit to kavix/openchoreo that referenced this pull request Aug 1, 2026
kavix added a commit to kavix/openchoreo that referenced this pull request Aug 1, 2026
@kavix
kavix force-pushed the fix-4329-container-ports-clean branch from 2c47426 to 3fd644f Compare August 1, 2026 08:53
@chathuranga95
chathuranga95 force-pushed the fix-4329-container-ports-clean branch from 3fd644f to 85967f4 Compare September 29, 2026 11:15
@chathuranga95

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chathuranga95
chathuranga95 merged commit 943ca4d into openchoreo:main Sep 29, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Workload endpoints should be translated into named container ports

3 participants