Skip to content

Commit ee1ea71

Browse files
committed
use K8sNameUUID instead of K8sNameHash and let each mcp have its own namespace
1 parent 720cfa3 commit ee1ea71

File tree

7 files changed

+102
-27
lines changed

7 files changed

+102
-27
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ require (
1010
dario.cat/mergo v1.0.2
1111
github.com/onsi/ginkgo/v2 v2.25.1
1212
github.com/onsi/gomega v1.38.1
13-
github.com/openmcp-project/controller-utils v0.17.0
13+
github.com/openmcp-project/controller-utils v0.17.1-0.20250815092130-15c510e7eb87
1414
github.com/openmcp-project/openmcp-operator/api v0.11.0
15+
github.com/openmcp-project/openmcp-operator/lib v0.11.0
1516
github.com/spf13/cobra v1.9.1
1617
k8s.io/api v0.33.4
1718
k8s.io/apimachinery v0.33.4

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY
9797
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
9898
github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk=
9999
github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g=
100-
github.com/openmcp-project/controller-utils v0.17.0 h1:dZsMX2ur/b1759+aKJmcJRdkOVJ131czE6AtIGKX1dE=
101-
github.com/openmcp-project/controller-utils v0.17.0/go.mod h1:RgatwIEftAvHbhd3FIyXb2Sm0N6/AK8A2aF8zBxK930=
100+
github.com/openmcp-project/controller-utils v0.17.1-0.20250815092130-15c510e7eb87 h1:PB/IG0h2fQNRdD5RfQprRkG2195XZA8fNVlLwDaj078=
101+
github.com/openmcp-project/controller-utils v0.17.1-0.20250815092130-15c510e7eb87/go.mod h1:PCxwUUek1PJA1/NHxFW9xFe5h+9erCyAgt+SkDrL4xk=
102+
github.com/openmcp-project/openmcp-operator/lib v0.11.0 h1:ga+n/lKwovULi/KYw3HttWVMKplON4S4dzIAIBg5CV4=
103+
github.com/openmcp-project/openmcp-operator/lib v0.11.0/go.mod h1:/FjNH8TJfbRomUYNvhtt4Peb1nrhe1IovCfun9DUMhY=
102104
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
103105
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
104106
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

lib/clusteraccess/clusteraccess.go

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package clusteraccess
33
import (
44
"context"
55
"fmt"
6+
"strings"
67
"time"
78

89
"github.com/openmcp-project/controller-utils/pkg/logging"
@@ -26,7 +27,9 @@ import (
2627
)
2728

2829
const (
29-
controllerName = "ClusterAccess"
30+
controllerName = "ClusterAccess"
31+
requestSuffixMCP = "--mcp"
32+
requestSuffixWorkload = "--wl"
3033
)
3134

3235
// Reconciler is an interface for reconciling access to openMCP clusters.
@@ -123,10 +126,14 @@ func (r *reconcilerImpl) WithWorkloadScheme(scheme *runtime.Scheme) Reconciler {
123126
}
124127

125128
func (r *reconcilerImpl) MCPCluster(ctx context.Context, request reconcile.Request) (*clusters.Cluster, error) {
129+
platformNamespace, err := libutils.StableMCPNamespace(request.Name, request.Namespace)
130+
if err != nil {
131+
return nil, err
132+
}
126133
mcpAccessRequest := &clustersv1alpha1.AccessRequest{
127134
ObjectMeta: metav1.ObjectMeta{
128-
Name: libutils.StableRequestNameMCP(request.Name, r.controllerName),
129-
Namespace: libutils.StableRequestNamespace(request.Namespace),
135+
Name: StableRequestName(r.controllerName, request) + requestSuffixMCP,
136+
Namespace: platformNamespace,
130137
},
131138
}
132139

@@ -143,10 +150,14 @@ func (r *reconcilerImpl) MCPCluster(ctx context.Context, request reconcile.Reque
143150
}
144151

145152
func (r *reconcilerImpl) WorkloadCluster(ctx context.Context, request reconcile.Request) (*clusters.Cluster, error) {
153+
platformNamespace, err := libutils.StableMCPNamespace(request.Name, request.Namespace)
154+
if err != nil {
155+
return nil, err
156+
}
146157
workloadAccessRequest := &clustersv1alpha1.AccessRequest{
147158
ObjectMeta: metav1.ObjectMeta{
148-
Name: libutils.StableRequestNameWorkload(request.Name, r.controllerName),
149-
Namespace: libutils.StableRequestNamespace(request.Namespace),
159+
Name: StableRequestName(r.controllerName, request) + requestSuffixWorkload,
160+
Namespace: platformNamespace,
150161
},
151162
}
152163

@@ -165,9 +176,13 @@ func (r *reconcilerImpl) WorkloadCluster(ctx context.Context, request reconcile.
165176
func (r *reconcilerImpl) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
166177
log := logging.FromContextOrPanic(ctx).WithName(controllerName)
167178

168-
requestNamespace := libutils.StableRequestNamespace(request.Namespace)
169-
requestNameMCP := libutils.StableRequestNameMCP(request.Name, r.controllerName)
170-
requestNameWorkload := libutils.StableRequestNameWorkload(request.Name, r.controllerName)
179+
platformNamespace, err := libutils.StableMCPNamespace(request.Name, request.Namespace)
180+
if err != nil {
181+
return reconcile.Result{}, err
182+
}
183+
requestNamespace := platformNamespace
184+
requestNameMCP := StableRequestName(r.controllerName, request) + requestSuffixMCP
185+
requestNameWorkload := StableRequestName(r.controllerName, request) + requestSuffixWorkload
171186

172187
metadata := requestMetadata(r.controllerName, request)
173188

@@ -258,9 +273,13 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, request reconcile.Reques
258273
}
259274

260275
func (r *reconcilerImpl) ReconcileDelete(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
261-
requestNamespace := libutils.StableRequestNamespace(request.Namespace)
262-
requestNameMCP := libutils.StableRequestNameMCP(request.Name, r.controllerName)
263-
requestNameWorkload := libutils.StableRequestNameWorkload(request.Name, r.controllerName)
276+
platformNamespace, err := libutils.StableMCPNamespace(request.Name, request.Namespace)
277+
if err != nil {
278+
return reconcile.Result{}, err
279+
}
280+
requestNamespace := platformNamespace
281+
requestNameMCP := StableRequestName(r.controllerName, request) + requestSuffixMCP
282+
requestNameWorkload := StableRequestName(r.controllerName, request) + requestSuffixWorkload
264283

265284
// Delete the Workload AccessRequest if it exists
266285
workloadAccessDeleted, err := deleteAccessRequest(ctx, r.platformClusterClient, requestNameWorkload, requestNamespace)
@@ -719,3 +738,10 @@ func (m *accessRequestMutator) Mutate(accessRequest *clustersv1alpha1.AccessRequ
719738
return nil
720739
}
721740
}
741+
742+
// StableRequestName generates a stable name for a Cluster- or AccessRequest related to an MCP.
743+
// This basically results in '<lowercase_controller_name>--<request_name>'.
744+
func StableRequestName(controllerName string, request reconcile.Request) string {
745+
controllerName = strings.ToLower(controllerName)
746+
return fmt.Sprintf("%s--%s", controllerName, request.Name)
747+
}

lib/clusteraccess/clusteraccess_test.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919

2020
clustersv1alpha1 "github.com/openmcp-project/openmcp-operator/api/clusters/v1alpha1"
2121
"github.com/openmcp-project/openmcp-operator/lib/clusteraccess"
22-
"github.com/openmcp-project/openmcp-operator/lib/utils"
2322

2423
"sigs.k8s.io/controller-runtime/pkg/client"
2524

@@ -118,7 +117,7 @@ var _ = Describe("ClusterAccessReconciler", func() {
118117
It("should create MCP-/Workload ClusterRequests/AccessRequests", func() {
119118
var reconcileResult reconcile.Result
120119

121-
expectedRequestNamespace := "ob-test"
120+
expectedRequestNamespace := "mcp--80158a25-6874-80a6-a75d-94f57da600c0"
122121

123122
request := reconcile.Request{
124123
NamespacedName: client.ObjectKey{
@@ -129,21 +128,21 @@ var _ = Describe("ClusterAccessReconciler", func() {
129128

130129
accessRequestMCP := &clustersv1alpha1.AccessRequest{
131130
ObjectMeta: metav1.ObjectMeta{
132-
Name: utils.StableRequestNameMCP(request.Name, controllerName),
131+
Name: clusteraccess.StableRequestName(controllerName, request) + "--mcp",
133132
Namespace: expectedRequestNamespace,
134133
},
135134
}
136135

137136
clusterRequestWorkload := &clustersv1alpha1.ClusterRequest{
138137
ObjectMeta: metav1.ObjectMeta{
139-
Name: utils.StableRequestNameWorkload(request.Name, controllerName),
138+
Name: clusteraccess.StableRequestName(controllerName, request) + "--wl",
140139
Namespace: expectedRequestNamespace,
141140
},
142141
}
143142

144143
accessRequestWorkload := &clustersv1alpha1.AccessRequest{
145144
ObjectMeta: metav1.ObjectMeta{
146-
Name: utils.StableRequestNameWorkload(request.Name, controllerName),
145+
Name: clusteraccess.StableRequestName(controllerName, request) + "--wl",
147146
Namespace: expectedRequestNamespace,
148147
},
149148
}
@@ -239,7 +238,7 @@ var _ = Describe("ClusterAccessReconciler", func() {
239238
It("should delete MCP-/Workload ClusterRequests/AccessRequests", func() {
240239
var reconcileResult reconcile.Result
241240

242-
expectedRequestNamespace := "ob-test"
241+
expectedRequestNamespace := "mcp--80158a25-6874-80a6-a75d-94f57da600c0"
243242

244243
request := reconcile.Request{
245244
NamespacedName: client.ObjectKey{
@@ -250,21 +249,21 @@ var _ = Describe("ClusterAccessReconciler", func() {
250249

251250
accessRequestMCP := &clustersv1alpha1.AccessRequest{
252251
ObjectMeta: metav1.ObjectMeta{
253-
Name: utils.StableRequestNameMCP(request.Name, controllerName),
252+
Name: clusteraccess.StableRequestName(controllerName, request) + "--mcp",
254253
Namespace: expectedRequestNamespace,
255254
},
256255
}
257256

258257
clusterRequestWorkload := &clustersv1alpha1.ClusterRequest{
259258
ObjectMeta: metav1.ObjectMeta{
260-
Name: utils.StableRequestNameWorkload(request.Name, controllerName),
259+
Name: clusteraccess.StableRequestName(controllerName, request) + "--wl",
261260
Namespace: expectedRequestNamespace,
262261
},
263262
}
264263

265264
accessRequestWorkload := &clustersv1alpha1.AccessRequest{
266265
ObjectMeta: metav1.ObjectMeta{
267-
Name: utils.StableRequestNameWorkload(request.Name, controllerName),
266+
Name: clusteraccess.StableRequestName(controllerName, request) + "--wl",
268267
Namespace: expectedRequestNamespace,
269268
},
270269
}

lib/clusteraccess/testdata/test-01/access-secrets.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v1
22
kind: Secret
33
metadata:
44
name: mcp-access
5-
namespace: ob-test
5+
namespace: mcp--80158a25-6874-80a6-a75d-94f57da600c0
66
data:
77
kubeconfig: YXBpVmVyc2lvbjogdjEKa2luZDogQ29uZmlnCnByZWZlcmVuY2VzOiB7fQpjbHVzdGVyczoKLSBjbHVzdGVyOgogICAgc2VydmVyOiBodHRwczovL2FwaS5jbHVzdGVyLWIuZXhhbXBsZS5jb206NjQ0MwogIG5hbWU6IGNsdXN0ZXIKY29udGV4dHM6Ci0gY29udGV4dDoKICAgIGNsdXN0ZXI6IGNsdXN0ZXIKICAgIHVzZXI6IHVzZXIKICBuYW1lOiBjb250ZXh0CmN1cnJlbnQtY29udGV4dDogY29udGV4dAp1c2VyczoKLSBuYW1lOiB1c2VyCiAgdXNlcjoKICAgIHRva2VuOiBhYmM=
88

@@ -11,6 +11,6 @@ apiVersion: v1
1111
kind: Secret
1212
metadata:
1313
name: workload-access
14-
namespace: ob-test
14+
namespace: mcp--80158a25-6874-80a6-a75d-94f57da600c0
1515
data:
1616
kubeconfig: YXBpVmVyc2lvbjogdjEKa2luZDogQ29uZmlnCnByZWZlcmVuY2VzOiB7fQpjbHVzdGVyczoKLSBjbHVzdGVyOgogICAgc2VydmVyOiBodHRwczovL2FwaS5jbHVzdGVyLWIuZXhhbXBsZS5jb206NjQ0MwogIG5hbWU6IGNsdXN0ZXIKY29udGV4dHM6Ci0gY29udGV4dDoKICAgIGNsdXN0ZXI6IGNsdXN0ZXIKICAgIHVzZXI6IHVzZXIKICBuYW1lOiBjb250ZXh0CmN1cnJlbnQtY29udGV4dDogY29udGV4dAp1c2VyczoKLSBuYW1lOiB1c2VyCiAgdXNlcjoKICAgIHRva2VuOiBhYmM=

lib/utils/utils.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,65 @@ import (
88

99
const (
1010
prefixOnboarding = "ob-"
11-
prefixMCP = "mcp-"
11+
oldPrefixMCP = "mcp-"
1212
prefixWorkload = "wl-"
13+
prefixMCP = "mcp--"
1314
)
1415

1516
// StableRequestNamespace returns a stable namespace for ClusterRequests and AccessRequests,
1617
// that can be created/used on the platform cluster.
1718
// onboardingNamespace is the namespace of the reconciled resource on the onboarding cluster.
19+
//
20+
// Deprecated: Use StableMCPNamespace instead.
1821
func StableRequestNamespace(onboardingNamespace string) string {
1922
return fmt.Sprint(prefixOnboarding, onboardingNamespace)
2023
}
2124

2225
// StableRequestNameMCP returns a stable name for MCP requests that can be used in a request namespace on the platform cluster.
2326
// onboardingName is the name of the reconciled resource on the onboarding cluster.
2427
// controllerName is the name of the controller that is reconciling the resource.
28+
//
29+
// Deprecated: Since every MCP now has its own namespace on the platform cluster, producing unique names this way is not required anymore for namespace-scoped resources. Use StableMCPIdentifier for cluster-scoped resources.
2530
func StableRequestNameMCP(onboardingName, controllerName string) string {
26-
return fmt.Sprint(prefixMCP, controller.K8sNameHash(onboardingName, controllerName))
31+
return fmt.Sprint(oldPrefixMCP, controller.K8sNameHash(onboardingName, controllerName))
2732
}
2833

2934
// StableRequestNameWorkload returns a stable name for Workload requests that can be used in a request namespace on the platform cluster.
3035
// onboardingName is the name of the reconciled resource on the onboarding cluster.
3136
// controllerName is the name of the controller that is reconciling the resource.
37+
//
38+
// Deprecated: Since each MCP now has its own namespace, the controller can choose the request name relatively freely (just avoid conflicts with other controllers).
3239
func StableRequestNameWorkload(onboardingName, controllerName string) string {
3340
return fmt.Sprint(prefixWorkload, controller.K8sNameHash(onboardingName, controllerName))
3441
}
3542

3643
// StableRequestNameOnboarding returns a stable name for Onboarding requests that can be used in a request namespace on the platform cluster.
3744
// onboardingName is the name of the reconciled resource on the onboarding cluster.
3845
// controllerName is the name of the controller that is reconciling the resource.
46+
//
47+
// Deprecated: Since each MCP now has its own namespace, the controller can choose the request name relatively freely (just avoid conflicts with other controllers).
3948
func StableRequestNameOnboarding(onboardingName, controllerName string) string {
4049
return fmt.Sprint(prefixOnboarding, controller.K8sNameHash(onboardingName, controllerName))
4150
}
51+
52+
// StableMCPNamespace computes the namespace on the onboarding cluster that belongs to the given MCP.
53+
// onboardingName and onboardingNamespace are name and namespace of the MCP resource on the onboarding cluster.
54+
func StableMCPNamespace(onboardingName, onboardingNamespace string) (string, error) {
55+
res, err := controller.K8sNameUUID(onboardingNamespace, onboardingName)
56+
if err != nil {
57+
return res, fmt.Errorf("error computing MCP namespace on platform cluster: %w", err)
58+
}
59+
return prefixMCP + res, nil
60+
}
61+
62+
// StableMCPIdentifier computes a string that is stable for the given MCP name and namespace and at the same time unique across all MCPs.
63+
// This can be used to name cluster-scoped resources on the platform cluster. It is recommended to add a prefix or suffix to it.
64+
// For namespaced resources, use the MCP-specific namespace (get the name via StableMCPNamespace).
65+
// onboardingName and onboardingNamespace are name and namespace of the MCP resource on the onboarding cluster.
66+
func StableMCPIdentifier(onboardingName, onboardingNamespace string) (string, error) {
67+
res, err := controller.K8sNameUUID(onboardingNamespace, onboardingName)
68+
if err != nil {
69+
return res, fmt.Errorf("error computing MCP identifier for platform cluster: %w", err)
70+
}
71+
return res, nil
72+
}

lib/utils/utils_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,20 @@ var _ = Describe("Utils", func() {
5353
Expect(utils.StableRequestNameWorkload(onboardingName, controllerName)).To(Equal(expectedName))
5454
})
5555
})
56+
57+
Context("StableMCPNamespace", func() {
58+
It("should compute the MCP namespace on the platform cluster", func() {
59+
expectedNamespace, err := utils.StableMCPNamespace(onboardingName, onboardingNamespace)
60+
Expect(err).NotTo(HaveOccurred())
61+
Expect(expectedNamespace).To(Equal("mcp--ed00e8ed-8a09-8c62-a9b8-e6fc20255174"))
62+
})
63+
})
64+
65+
Context("StableMCPIdentifier", func() {
66+
It("should compute a stable MCP identifier", func() {
67+
expectedIdentifier, err := utils.StableMCPIdentifier(onboardingName, onboardingNamespace)
68+
Expect(err).NotTo(HaveOccurred())
69+
Expect(expectedIdentifier).To(Equal("ed00e8ed-8a09-8c62-a9b8-e6fc20255174"))
70+
})
71+
})
5672
})

0 commit comments

Comments
 (0)