Skip to content

feat(coordinator): support IPv6 address format and improve address pa…#1947

Merged
yottahmd merged 1 commit intodagucloud:mainfrom
artikell:feat_ipv6_address
Apr 2, 2026
Merged

feat(coordinator): support IPv6 address format and improve address pa…#1947
yottahmd merged 1 commit intodagucloud:mainfrom
artikell:feat_ipv6_address

Conversation

@artikell
Copy link
Copy Markdown
Contributor

@artikell artikell commented Apr 2, 2026

…rsing

  • Replace manual parsing with net.SplitHostPort and net.ParseIP
  • Add IPv6 test cases (with and without ports)

Summary by CodeRabbit

  • New Features

    • Added support for IPv6 address formats in coordinator configuration, including bracketed IPv6 notation with explicit ports and default port handling.
  • Bug Fixes

    • Improved address parsing robustness with enhanced validation for host-port combinations and better handling of edge cases.
  • Tests

    • Extended test coverage for IPv6 address parsing and registry member construction.

…rsing

- Replace manual parsing with net.SplitHostPort and net.ParseIP
- Add IPv6 test cases (with and without ports)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

The changes enhance address handling in the coordinator service by improving gRPC target construction and adding robust IPv6 support to address parsing. The client now uses net.JoinHostPort for address formatting, while the static registry's parser gains comprehensive IPv6 bracket notation support with port validation and fallback logic.

Changes

Cohort / File(s) Summary
Address Construction
internal/service/coordinator/client.go
Replaced fmt.Sprintf with net.JoinHostPort for gRPC target address formatting. Added net and strconv imports.
Address Parsing & Validation
internal/service/coordinator/static_registry.go
Enhanced parser to support IPv6 bracket notation ([ipv6]:port), host-only inputs with default port fallback (50055), numeric port validation (1–65535), and whitespace trimming. Added isIPv6Host helper function for IPv6 validation. Replaced simplistic strings.Split with net.SplitHostPort and expanded error handling.
Test Coverage
internal/service/coordinator/static_registry_test.go
Added new test cases validating IPv6 address parsing: bracketed IPv6 with explicit port, bracketed IPv6 with default port, and plain IPv6 with default port.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective of the changeset: adding IPv6 address format support and improving address parsing in the coordinator service.

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

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

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.

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.

🧹 Nitpick comments (3)
internal/service/coordinator/static_registry.go (1)

62-74: Shadowing host and err variables causes unexpected behavior.

The if statement at line 62 declares new host, portStr, and err variables that shadow the function's return parameters. This means when net.SplitHostPort succeeds, the returned host from line 73 is the inner-scoped variable, but the function's named return host remains empty if you later fall through to error paths.

While this code path returns early on line 73 so it works correctly now, shadowing named returns is fragile and can cause subtle bugs if the function is refactored. Consider avoiding shadowing:

♻️ Suggested refactor to avoid shadowing
-	if host, portStr, err := net.SplitHostPort(addr); err == nil {
-		p, err := strconv.Atoi(portStr)
+	if h, portStr, splitErr := net.SplitHostPort(addr); splitErr == nil {
+		p, err := strconv.Atoi(portStr)
 		if err != nil {
 			return "", 0, fmt.Errorf("invalid port: %w", err)
 		}
 		if p <= 0 || p > 65535 {
 			return "", 0, fmt.Errorf("port must be between 1 and 65535")
 		}
-		if host == "" {
+		if h == "" {
 			return "", 0, fmt.Errorf("host cannot be empty")
 		}
-		return host, p, nil
+		return h, p, nil
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/coordinator/static_registry.go` around lines 62 - 74, The
code shadows the function's named return variables by using := in the
net.SplitHostPort call; avoid shadowing by declaring locals first (e.g., h,
portStr, splitErr := net.SplitHostPort(addr) or use regular assignment to an
existing err variable) and then assign the local host to the named return (host
= h) before returning, ensuring you check and convert portStr with strconv.Atoi
into p and keep the existing validations in the same block; update the block
around net.SplitHostPort in static_registry.go (the if that currently declares
host, portStr, err) to use non-shadowing locals or explicit assignments.
internal/service/coordinator/static_registry_test.go (1)

211-228: Good IPv6 test coverage; consider adding edge case tests.

The new test cases cover the main IPv6 scenarios well. Consider adding tests for:

  • Malformed brackets: [ipv6 (missing closing bracket)
  • Empty brackets: []
  • IPv6 with zone ID: fe80::1%eth0 (the code handles this via zone stripping)
🧪 Optional additional test cases
{
    name:        "malformed bracket - missing close",
    addr:        "[fdbd:dc02:1a:e12::31",
    expectError: true,
    errorMsg:    "invalid address format",
},
{
    name:        "empty brackets",
    addr:        "[]",
    expectError: true,
    errorMsg:    "invalid address format",
},
{
    name:     "ipv6 with zone id",
    addr:     "fe80::1%eth0",
    wantHost: "fe80::1%eth0",
    wantPort: 50055,
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/coordinator/static_registry_test.go` around lines 211 - 228,
Add three edge-case table-driven tests alongside the existing IPv6 cases in
static_registry_test.go: a "malformed bracket - missing close" case with addr
"[fdbd:dc02:1a:e12::31", expectError: true and errorMsg like "invalid address
format"; an "empty brackets" case with addr "[]", expectError: true and errorMsg
"invalid address format"; and an "ipv6 with zone id" case with addr
"fe80::1%eth0", wantHost "fe80::1%eth0" and wantPort 50055. Place these entries
in the same test cases slice used by the existing IPv6 tests (the entries with
wantHost/wantPort), and ensure the test logic checks expectError/errorMsg when
provided and otherwise validates wantHost and wantPort.
internal/service/coordinator/client.go (1)

396-396: Good improvement for IPv6 support.

Using net.JoinHostPort correctly handles IPv6 addresses by automatically adding brackets when needed (e.g., [::1]:50055). This pairs well with parseAddress in static_registry.go which stores the IPv6 host without brackets.

The fmt.Sprintf("%s:%d", ...) patterns in internal/cmd/coord.go (line 215) and internal/runtime/builtin/redis/client.go (line 88) will also break with IPv6 addresses and should use net.JoinHostPort for consistency.

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

In `@internal/service/coordinator/client.go` at line 396, Replace manual "%s:%d"
formatting with net.JoinHostPort to correctly handle IPv6 in all address
constructions: update the address assembly in the coordinator command (the code
that currently uses fmt.Sprintf("%s:%d", member.Host, member.Port) in the coord
command builder) to use net.JoinHostPort(member.Host,
strconv.Itoa(member.Port)), and do the same in the Redis client initialization
(the place that formats host and port for the Redis client, e.g., NewRedisClient
or the function that constructs the Redis address) so IPv6 hosts are bracketed
consistently with parseAddress/static_registry usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/service/coordinator/client.go`:
- Line 396: Replace manual "%s:%d" formatting with net.JoinHostPort to correctly
handle IPv6 in all address constructions: update the address assembly in the
coordinator command (the code that currently uses fmt.Sprintf("%s:%d",
member.Host, member.Port) in the coord command builder) to use
net.JoinHostPort(member.Host, strconv.Itoa(member.Port)), and do the same in the
Redis client initialization (the place that formats host and port for the Redis
client, e.g., NewRedisClient or the function that constructs the Redis address)
so IPv6 hosts are bracketed consistently with parseAddress/static_registry
usage.

In `@internal/service/coordinator/static_registry_test.go`:
- Around line 211-228: Add three edge-case table-driven tests alongside the
existing IPv6 cases in static_registry_test.go: a "malformed bracket - missing
close" case with addr "[fdbd:dc02:1a:e12::31", expectError: true and errorMsg
like "invalid address format"; an "empty brackets" case with addr "[]",
expectError: true and errorMsg "invalid address format"; and an "ipv6 with zone
id" case with addr "fe80::1%eth0", wantHost "fe80::1%eth0" and wantPort 50055.
Place these entries in the same test cases slice used by the existing IPv6 tests
(the entries with wantHost/wantPort), and ensure the test logic checks
expectError/errorMsg when provided and otherwise validates wantHost and
wantPort.

In `@internal/service/coordinator/static_registry.go`:
- Around line 62-74: The code shadows the function's named return variables by
using := in the net.SplitHostPort call; avoid shadowing by declaring locals
first (e.g., h, portStr, splitErr := net.SplitHostPort(addr) or use regular
assignment to an existing err variable) and then assign the local host to the
named return (host = h) before returning, ensuring you check and convert portStr
with strconv.Atoi into p and keep the existing validations in the same block;
update the block around net.SplitHostPort in static_registry.go (the if that
currently declares host, portStr, err) to use non-shadowing locals or explicit
assignments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d4de3157-f42e-406e-ae1b-9a9a0df81e60

📥 Commits

Reviewing files that changed from the base of the PR and between 5f5f73a and fb44188.

📒 Files selected for processing (3)
  • internal/service/coordinator/client.go
  • internal/service/coordinator/static_registry.go
  • internal/service/coordinator/static_registry_test.go

Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd left a comment

Choose a reason for hiding this comment

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

Amazing! Thank you very much for adding support for IPv6!

@yottahmd yottahmd merged commit 7f6de95 into dagucloud:main Apr 2, 2026
5 checks passed
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 57.69231% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.64%. Comparing base (7e91b40) to head (fb44188).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/service/coordinator/static_registry.go 56.00% 5 Missing and 6 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1947      +/-   ##
==========================================
- Coverage   68.67%   68.64%   -0.04%     
==========================================
  Files         463      468       +5     
  Lines       58751    60007    +1256     
==========================================
+ Hits        40348    41190     +842     
- Misses      14673    14949     +276     
- Partials     3730     3868     +138     
Files with missing lines Coverage Δ
internal/service/coordinator/client.go 74.23% <100.00%> (+0.46%) ⬆️
internal/service/coordinator/static_registry.go 79.31% <56.00%> (-20.69%) ⬇️

... and 30 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7e91b40...fb44188. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

2 participants