Skip to content

[management, proxy] Add require_subdomain capability for proxy clusters#5628

Merged
lixmal merged 4 commits intomainfrom
feature/require-subdomain-validation
Mar 20, 2026
Merged

[management, proxy] Add require_subdomain capability for proxy clusters#5628
lixmal merged 4 commits intomainfrom
feature/require-subdomain-validation

Conversation

@lixmal
Copy link
Copy Markdown
Collaborator

@lixmal lixmal commented Mar 19, 2026

Describe your changes

  • Add require_subdomain field to ProxyCapabilities proto and ReverseProxyDomain API response
  • Proxy clusters can now report whether bare cluster domain usage is allowed
  • When require_subdomain=true, service creation/update rejects domain == cluster_domain
  • Allow custom domains to be used bare (without subdomain) via extractClusterFromCustomDomains
  • Add server-side validation in both create and update paths
  • Add --require-subdomain / NB_PROXY_REQUIRE_SUBDOMAIN flag to proxy binary (default false)

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Configuration is via proxy flag/env var, no user-facing docs needed.

Summary by CodeRabbit

  • New Features

    • Clusters can advertise a "require subdomain" capability so services must use subdomain labels instead of bare cluster domains.
    • API now exposes a require_subdomain flag and a CLI/server option to configure/query this behavior.
  • Bug Fixes & Validation

    • Management now validates and rejects bare-domain service creation/updates when the cluster requires a subdomain.
  • Other

    • Improved custom-domain matching to select the most specific domain match.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a90a99dc-956b-46ec-8709-e10737fbc37b

📥 Commits

Reviewing files that changed from the base of the PR and between 81f2e63 and f759ea0.

📒 Files selected for processing (3)
  • management/internals/modules/reverseproxy/domain/manager/domain_test.go
  • management/internals/modules/reverseproxy/domain/manager/manager.go
  • management/internals/modules/reverseproxy/service/manager/manager.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • management/internals/modules/reverseproxy/domain/manager/domain_test.go

📝 Walkthrough

Walkthrough

Adds a RequireSubdomain capability propagated from proxy config through gRPC and controller layers into domain API and service manager; service create/update now validate and reject bare cluster domains when a cluster requires a subdomain.

Changes

Cohort / File(s) Summary
Domain & API Models
management/internals/modules/reverseproxy/domain/domain.go, shared/management/http/api/types.gen.go, shared/management/proto/proxy_service.proto, shared/management/http/api/openapi.yml
Added RequireSubdomain *bool to Domain and API/protobuf/OpenAPI representations.
Domain Manager & API Mapping
management/internals/modules/reverseproxy/domain/manager/api.go, management/internals/modules/reverseproxy/domain/manager/manager.go, management/internals/modules/reverseproxy/domain/manager/domain_test.go
Mapped RequireSubdomain into API output; manager populates it for cluster-derived (free) domains; improved custom-domain matching and added cluster-extraction tests.
Controller Surface & Mocks
management/internals/modules/reverseproxy/proxy/manager.go, management/internals/modules/reverseproxy/proxy/manager/controller.go, management/internals/modules/reverseproxy/proxy/manager_mock.go
Added ClusterRequireSubdomain(clusterAddr string) *bool to Controller interface; GRPC controller forwards call; updated mock with expectation recorder.
gRPC Aggregation
management/internals/shared/grpc/proxy.go, management/internals/shared/grpc/proxy_test.go
Implemented ProxyServiceServer.ClusterRequireSubdomain aggregating connected proxies' RequireSubdomain capability; added test stub returning nil.
Service Manager & Validation
management/internals/modules/reverseproxy/service/manager/manager.go, management/internals/modules/reverseproxy/service/manager/manager_test.go, management/internals/modules/reverseproxy/service/manager/l4_port_test.go
Added validateSubdomainRequirement and invoked it during service create/update (transactional); extracted update helper; tests cover true/false/nil behaviors and updated gomock expectations.
Proxy Server & CLI
proxy/server.go, proxy/cmd/proxy/cmd/root.go
Added Server.RequireSubdomain field and --require-subdomain / NB_PROXY_REQUIRE_SUBDOMAIN flag; advertised capability on mapping stream.
Integration & Test Mocks
proxy/management_integration_test.go
Extended test proxy controller mock with ClusterRequireSubdomain returning nil.

Sequence Diagram

sequenceDiagram
    participant User as User/API
    participant SMgr as Service Manager
    participant Ctrl as Proxy Controller
    participant GRPC as ProxyServiceServer (gRPC)
    participant Conn as Connected Proxy(s)
    participant DMgr as Domain Manager

    User->>SMgr: Create/Update Service(domain, ...)
    SMgr->>SMgr: derive ProxyCluster from domain
    SMgr->>Ctrl: ClusterRequireSubdomain(cluster)
    Ctrl->>GRPC: ClusterRequireSubdomain(cluster)
    GRPC->>Conn: read conn.capabilities.RequireSubdomain
    alt any conn true
        GRPC-->>Ctrl: true
    else any conn reported (but none true)
        GRPC-->>Ctrl: false
    else none reported
        GRPC-->>Ctrl: nil
    end
    Ctrl-->>SMgr: *bool (true/false/nil)
    alt capability == true AND domain == cluster
        SMgr-->>User: Error "requires a subdomain label"
    else
        SMgr->>DMgr: GetDomains()
        DMgr->>Ctrl: ClusterRequireSubdomain(cluster)
        Ctrl-->>DMgr: *bool
        DMgr-->>User: Domain list (RequireSubdomain set)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • pascal-fischer

Poem

🐇 I nibble on the code tonight,
A dot of flag, a tiny light,
"Require subdomain," the proxies hum,
Managers check before changes come,
Hops of logic — neat and bright.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.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
Title check ✅ Passed The title accurately summarizes the main change: adding a require_subdomain capability for proxy clusters, which is the central feature implemented across management and proxy modules.
Description check ✅ Passed The description covers all key changes, includes completed checklist items (feature enhancement, created tests), addresses documentation needs, and acknowledges the CLA. All required template sections are present with substantive content.

✏️ 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 feature/require-subdomain-validation
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@lixmal lixmal changed the title [management] Add require_subdomain capability for proxy clusters [management][proxy] Add require_subdomain capability for proxy clusters Mar 19, 2026
@lixmal lixmal changed the title [management][proxy] Add require_subdomain capability for proxy clusters [management, proxy] Add require_subdomain capability for proxy clusters Mar 19, 2026
Copy link
Copy Markdown
Contributor

@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

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

Inline comments:
In `@management/internals/modules/reverseproxy/domain/manager/manager.go`:
- Around line 309-312: The function extractClusterFromCustomDomains currently
returns the first matching custom domain which can pick a less-specific suffix
match; instead, iterate all customDomains in extractClusterFromCustomDomains,
track the best (longest) matching cd.Domain where serviceDomain == cd.Domain or
strings.HasSuffix(serviceDomain, "."+cd.Domain), and after the loop return the
TargetCluster for the longest match (or false if none). Update the function to
prefer exact/more-specific domain matches by length and add a regression test
that covers overlapping domains (e.g., entries for "example.com" and
"app.example.com") to ensure app.example.com resolves to the more specific
target cluster.

In `@management/internals/modules/reverseproxy/service/manager/manager.go`:
- Around line 568-570: The current validateSubdomainRequirement check only runs
in handleDomainChange and is skipped on updates that don't change
service.Domain; move or add a call to
validateSubdomainRequirement(service.Domain, service.ProxyCluster) at the end of
persistServiceUpdate (after the domain-change branch completes) so the final
ProxyCluster is validated on every update; specifically, ensure
persistServiceUpdate invokes validateSubdomainRequirement with the
service.Domain and the resolved/new Cluster (the same values used when creating
newCluster in handleDomainChange) and returns the error to block saves when a
cluster now requires subdomains.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f25788f2-7803-49bb-9b57-49a07e8e7c19

📥 Commits

Reviewing files that changed from the base of the PR and between a1858a9 and 2910e7e.

⛔ Files ignored due to path filters (1)
  • shared/management/proto/proxy_service.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (17)
  • management/internals/modules/reverseproxy/domain/domain.go
  • management/internals/modules/reverseproxy/domain/manager/api.go
  • management/internals/modules/reverseproxy/domain/manager/domain_test.go
  • management/internals/modules/reverseproxy/domain/manager/manager.go
  • management/internals/modules/reverseproxy/proxy/manager.go
  • management/internals/modules/reverseproxy/proxy/manager/controller.go
  • management/internals/modules/reverseproxy/proxy/manager_mock.go
  • management/internals/modules/reverseproxy/service/manager/l4_port_test.go
  • management/internals/modules/reverseproxy/service/manager/manager.go
  • management/internals/modules/reverseproxy/service/manager/manager_test.go
  • management/internals/shared/grpc/proxy.go
  • management/internals/shared/grpc/proxy_test.go
  • proxy/cmd/proxy/cmd/root.go
  • proxy/server.go
  • shared/management/http/api/openapi.yml
  • shared/management/http/api/types.gen.go
  • shared/management/proto/proxy_service.proto

Comment thread management/internals/modules/reverseproxy/domain/manager/manager.go Outdated
Comment thread management/internals/modules/reverseproxy/service/manager/manager.go Outdated
@sonarqubecloud
Copy link
Copy Markdown

@lixmal lixmal merged commit b550a2f into main Mar 20, 2026
45 checks passed
@lixmal lixmal deleted the feature/require-subdomain-validation branch March 20, 2026 10:29
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