Skip to content

feat: namespace-scoped ControlPlane, ControlPlaneEndpoint, ControlPlaneRegistration#12

Merged
zachsmith1 merged 1 commit intomainfrom
feat/namespace-scoped-controlplanes
Mar 22, 2026
Merged

feat: namespace-scoped ControlPlane, ControlPlaneEndpoint, ControlPlaneRegistration#12
zachsmith1 merged 1 commit intomainfrom
feat/namespace-scoped-controlplanes

Conversation

@zachsmith1
Copy link
Copy Markdown
Contributor

@zachsmith1 zachsmith1 commented Mar 22, 2026

Summary

  • Make ControlPlane, ControlPlaneEndpoint, and ControlPlaneRegistration namespace-scoped
  • Enables multi-tenant isolation via namespace-based RBAC
  • ControlPlaneClass stays cluster-scoped (policy resource)
  • Management namespace naming includes CP namespace to avoid collisions
  • Gateway resources created in CP namespace

Breaking change

CRD scope is immutable — old CRDs must be deleted and recreated.

CLI compatibility

No CLI code changes needed — CPs are created in the configured namespace.


Note

High Risk
High risk because it changes CRD scope (an immutable, breaking API change) and updates controller reconciliation/resource lookup semantics to be namespace-aware, which can affect routing/endpoint resolution and multi-tenant behavior if any namespace handling is missed.

Overview
Scope change: Updates the CRDs and kubebuilder markers so ControlPlane, ControlPlaneEndpoint, and ControlPlaneRegistration are Namespaced instead of cluster-scoped.

Controller behavior updates: Adjusts reconciliation to fetch referenced ControlPlaneEndpoint/ControlPlane objects using the caller’s namespace, creates auto-managed gateway resources (ControlPlaneEndpoint, HTTPRoute) in the ControlPlane namespace, and updates management-namespace naming to include the ControlPlane namespace to avoid cross-namespace name collisions.

Tests: Updates controller tests to consistently create/get/delete these resources using explicit namespaces.

Written by Cursor Bugbot for commit f7471da. This will update automatically on new commits. Configure here.

…ration namespace-scoped

Enables multi-tenant isolation via namespace-based RBAC. CPs live in
org/project namespaces, and standard k8s RBAC on the namespace governs
who can create/view them.

Changes:
- ControlPlane: scope=Cluster → scope=Namespaced
- ControlPlaneEndpoint: scope=Cluster → scope=Namespaced
- ControlPlaneRegistration: scope=Cluster → scope=Namespaced
- All endpoint/CP lookups now include namespace from the parent resource
- Management namespace naming includes CP namespace to avoid collisions
- Gateway resources (HTTPRoute, ControlPlaneEndpoint) created in CP namespace
- Tests updated for namespace-scoped resources

ControlPlaneClass remains cluster-scoped (it's policy, not tenant data).

CLI compatibility: kplane CLI creates CPs in its configured namespace
(typically kplane-system or default). No CLI code changes needed.

BREAKING: CRD scope change is immutable — old CRDs must be deleted
and recreated. Existing ControlPlane resources must be migrated.
@zachsmith1 zachsmith1 merged commit b3db2ba into main Mar 22, 2026
5 of 7 checks passed
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

return name
}
hash := sha256.Sum256([]byte(controlPlane.Name))
hash := sha256.Sum256([]byte(cpID))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Truncation uses Name instead of cpID losing namespace

Medium Severity

In managementNamespace, the new cpID variable (which includes the namespace prefix for non-default namespaces) is correctly used for both the initial name construction and the hash computation. However, trunc on line 379 still uses controlPlane.Name instead of cpID. When truncation kicks in (name exceeding 63 chars), the namespace portion is entirely dropped from the human-readable part of the management namespace name. While the hash suffix prevents actual collisions, this inconsistency defeats the purpose of including the namespace in cpID and makes the truncated names misleading.

Fix in Cursor Fix in Web


// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:resource:scope=Namespaced
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Default clusterPath uses non-unique Name causing data collision

High Severity

The scope change from Cluster to Namespaced means controlPlane.Name is no longer globally unique. However, clusterPathForControlPlane still defaults clusterPath to controlPlane.Name, which is the key used to partition virtual cluster data in etcd (via /clusters/<clusterPath>/). Two CPs with the same name in different namespaces would share the same virtual cluster data path. Worse, destroyClusterData uses this path to delete etcd keys — deleting one CP with DeletionPolicyDestroy would destroy another same-named CP's data. The managementNamespace function was updated with cpID to handle namespace collisions, but clusterPathForControlPlane was not.

Additional Locations (1)
Fix in Cursor Fix in Web

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