Skip to content

feat: support batch TCP/UDP port ranges in stream config#264

Open
nic-6443 wants to merge 2 commits intomainfrom
feat/stream-port-range
Open

feat: support batch TCP/UDP port ranges in stream config#264
nic-6443 wants to merge 2 commits intomainfrom
feat/stream-port-range

Conversation

@nic-6443
Copy link
Contributor

@nic-6443 nic-6443 commented Mar 19, 2026

What

Support port range notation in gateway.stream.tcp and gateway.stream.udp configuration for Kubernetes deployments.

Why

Users with many TCP proxy ports (30+) need to modify configs and restart for each new port. Port range support reduces config changes. This is the Helm chart companion to api7/api7-ee-3-gateway#1272.

How

  • ConfigMap: Passes range strings through to config.yaml where the gateway's native nginx listen directive handles them (strings are properly quoted).
  • Container ports & Service ports: New helper templates expand port ranges into individual port entries since Kubernetes requires concrete port numbers.
  • Reversed ranges: Automatically swaps bounds (e.g., "2100-2000""2000-2100") instead of silently producing no ports.

New helper templates in _helpers.tpl

  • gateway.expandPorts: Expands a port string (may contain ranges like "2000-2100") into a list of individual port numbers
  • gateway.normalizedTcpPorts: Normalizes TCP array entries into expanded port objects with port/nodePort/tls
  • gateway.normalizedUdpPorts: Normalizes UDP array entries into expanded port objects

Supported formats in values.yaml

gateway:
  stream:
    enabled: true
    tcp:
      - 9100                          # existing: single port (integer)
      - addr: 192.168.31.10:5432      # existing: address with port
      - "2000-2100"                   # NEW: port range string
      - addr: "5000-5010"             # NEW: object form with range
        tls: true
      - addr: "127.0.0.1:4000-4100"   # NEW: address with port range
    udp:
      - 9200                           # existing: single port
      - "9300-9310"                    # NEW: port range string

Backward compatibility

All existing formats (integer, string, map with addr/tls/nodePort) continue to work unchanged. Verified with helm template and helm lint.

Related PR

Gateway: api7/api7-ee-3-gateway#1272

Add support for port range notation and comma-separated port lists
in gateway.stream.tcp and gateway.stream.udp configuration.

ConfigMap passes range strings through to config.yaml where the
gateway's native parsing handles them. For K8s container ports and
service ports, new helper templates (gateway.expandPorts,
gateway.normalizedTcpPorts, gateway.normalizedUdpPorts) expand
port ranges into individual port entries since Kubernetes requires
concrete port numbers.

Supported formats in values.yaml:
- Port range: '2000-2100'
- Address with range: '127.0.0.1:2000-2100'
- Comma-separated: '1881,1888,3000'
- Mixed: '1881,1888,2000-2100,3000'
- Object form with range: {addr: '5000-5010', tls: true}

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

Added Helm helpers to parse and expand TCP/UDP port specs (scalars, maps, ranges, comma lists) and refactored gateway templates to use normalized JSON outputs for port entries; also adjusted ConfigMap quoting and added commented examples in values.yaml.

Changes

Cohort / File(s) Summary
Port helper functions
charts/gateway/templates/_helpers.tpl
Added gateway.expandPorts, gateway.normalizedTcpPorts, and gateway.normalizedUdpPorts to parse/expand port strings, accept scalar or map items, and emit JSON { "entries":[...] } with {port, nodePort} entries.
Pod template
charts/gateway/templates/_pod.tpl
Replaced direct iteration of .Values.gateway.stream.tcp/.udp with include "gateway.normalizedTcpPorts" / gateway.normalizedUdpPorts + fromJson; iterate normalized.entries and render containerPort from entry.port. Removed prior kindIs "map" and addr-splitting logic.
Service ports
charts/gateway/templates/service-gateway.yaml
Now uses normalized port helpers + fromJson and iterates .$normalized.entries; port/targetPort sourced from $entry.port (int); NodePort assignment simplified to auto-assign or use non-empty $entry.nodePort. Removed addr-based parsing branches.
ConfigMap entries
charts/gateway/templates/configmap.yaml
Quoted .addr for map entries and emit string entries as quoted scalars; non-string, non-map values remain unquoted.
Values examples
charts/gateway/values.yaml
Added commented examples demonstrating port ranges, address+range formats, comma-separated lists and a TLS-on-range example under gateway.stream.tcp / gateway.stream.udp.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I’m a rabbit parsing ports with cheer,
Ranges unfurl and entries appear,
Commas, hyphens, addr: all made clear,
Templates now tidy, port lists near—
Hop, hop, deploy! 🐇🎛️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding support for TCP/UDP port ranges in the stream configuration, which is the primary feature introduced across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ 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 feat/stream-port-range
📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link

@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 (2)
charts/gateway/templates/_helpers.tpl (2)

144-168: Consider consolidating TCP/UDP normalization helpers.

gateway.normalizedTcpPorts and gateway.normalizedUdpPorts share identical logic. While Helm templating makes parameterized helpers awkward, you could potentially unify them into a single gateway.normalizedPorts helper if the protocol distinction isn't needed within the normalization logic itself.

This is a minor DRY improvement and can be deferred.

Also applies to: 175-199

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

In `@charts/gateway/templates/_helpers.tpl` around lines 144 - 168, The two
helpers gateway.normalizedTcpPorts and gateway.normalizedUdpPorts duplicate
identical normalization logic; consolidate them by creating a single helper
named gateway.normalizedPorts that contains the shared code (reusing
gateway.expandPorts for expansions) and update call sites to pass protocol if
needed or ignore it if unnecessary; ensure the new helper returns the same dict
"entries" JSON shape as before so consumers of
normalizedTcpPorts/normalizedUdpPorts keep the same contract, then remove the
duplicated helper definitions.

158-165: nodePort is silently ignored when expanding port ranges.

When a user specifies a map entry with both a range and nodePort:

tcp:
  - addr: "5000-5010"
    nodePort: 31000

The nodePort value is silently discarded (line 161 sets nodePort: ""). This is logically correct since you cannot assign a single nodePort to multiple ports, but users may not expect this silent behavior.

Consider documenting this limitation in values.yaml near the port range examples.

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

In `@charts/gateway/templates/_helpers.tpl` around lines 158 - 165, The template
silently drops nodePort when expanding ranges (see nodePort, addrStr and
gateway.expandPorts usage where expanded.ports are appended with nodePort ""),
so update the chart documentation: add a clear note in values.yaml next to the
port/range examples that nodePort is ignored for comma- or dash-based ranges
(e.g. "addr: '5000-5010'") and explain alternatives (provide individual port
entries or omit nodePort and rely on ClusterIP/LoadBalancer), and optionally
mention why (one nodePort cannot map to multiple ports) and how to map nodePorts
manually if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@charts/gateway/templates/_helpers.tpl`:
- Around line 122-129: The template currently computes $start and $end from a
dashed port range and uses $count := add1 (sub $end $start), which produces a
negative count and an empty range if the user supplies a reversed range (e.g.,
"2100-2000"); update the logic in the block that handles dashed ranges (the code
using contains, splitList, $start, $end, $count, sub, until) to detect when gt
$start $end and either swap the bounds (assign $tmp := $start; set $start =
$end; set $end = $tmp) so the range is normalized, or call the Helm fail
function with a clear error message indicating the reversed range, ensuring you
take the chosen approach consistently and preserve the subsequent use of $count
and the until loop to produce ports.

In `@charts/gateway/templates/service-gateway.yaml`:
- Around line 99-104: Add validation to reject or adjust invalid NodePort
assignments when $global.Values.gateway.stream.autoAssignNodePort is true:
ensure the value used for nodePort (currently $entry.port when
autoAssignNodePort is enabled, or $entry.nodePort otherwise) falls within the
Kubernetes NodePort range 30000–32767. Implement this by adding a Helm values
schema rule (values.schema.json) that requires nodePort or port to be an integer
within 30000–32767 whenever $global.Values.gateway.stream.autoAssignNodePort is
true, or add a pre-install/helm hook check that validates $entry.port before
rendering the service template and fails fast with a clear error referencing the
stream entry name and offending port.

---

Nitpick comments:
In `@charts/gateway/templates/_helpers.tpl`:
- Around line 144-168: The two helpers gateway.normalizedTcpPorts and
gateway.normalizedUdpPorts duplicate identical normalization logic; consolidate
them by creating a single helper named gateway.normalizedPorts that contains the
shared code (reusing gateway.expandPorts for expansions) and update call sites
to pass protocol if needed or ignore it if unnecessary; ensure the new helper
returns the same dict "entries" JSON shape as before so consumers of
normalizedTcpPorts/normalizedUdpPorts keep the same contract, then remove the
duplicated helper definitions.
- Around line 158-165: The template silently drops nodePort when expanding
ranges (see nodePort, addrStr and gateway.expandPorts usage where expanded.ports
are appended with nodePort ""), so update the chart documentation: add a clear
note in values.yaml next to the port/range examples that nodePort is ignored for
comma- or dash-based ranges (e.g. "addr: '5000-5010'") and explain alternatives
(provide individual port entries or omit nodePort and rely on
ClusterIP/LoadBalancer), and optionally mention why (one nodePort cannot map to
multiple ports) and how to map nodePorts manually if needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b6a2bbb-85f1-472e-a151-9df37dfd9af0

📥 Commits

Reviewing files that changed from the base of the PR and between 60bed18 and d0fb44a.

📒 Files selected for processing (5)
  • charts/gateway/templates/_helpers.tpl
  • charts/gateway/templates/_pod.tpl
  • charts/gateway/templates/configmap.yaml
  • charts/gateway/templates/service-gateway.yaml
  • charts/gateway/values.yaml

- Remove comma-separated support from expandPorts helper
- Handle reversed port ranges (e.g., '2100-2000') by swapping bounds
- Update values.yaml examples to match gateway changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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