Skip to content

Commit de9cd02

Browse files
authored
feat: Improve clusteraccess (#167)
* add clusteraccess Manager implementation that works for unit tests * prevent StableRequestName function from returning names that exceed the k8s name length limit
1 parent f912f33 commit de9cd02

File tree

8 files changed

+152
-14
lines changed

8 files changed

+152
-14
lines changed

api/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/openmcp-project/openmcp-operator/api
33
go 1.25.1
44

55
require (
6-
github.com/openmcp-project/controller-utils v0.21.0
6+
github.com/openmcp-project/controller-utils v0.22.0
77
k8s.io/api v0.34.1
88
k8s.io/apiextensions-apiserver v0.34.1
99
k8s.io/apimachinery v0.34.1

api/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw
7373
github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE=
7474
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
7575
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
76-
github.com/openmcp-project/controller-utils v0.21.0 h1:X5yN/BnJuNX9CXWgIU/cCynWFFv1KLR4zW9nnJl5Izg=
77-
github.com/openmcp-project/controller-utils v0.21.0/go.mod h1:b8VcTK6iXFgkW6pXtIEDbaiQtzqYycVMFmElc7SFBQQ=
76+
github.com/openmcp-project/controller-utils v0.22.0 h1:kdWGds+LOyOaOuKqWZGsJUv17e78HCr5y3bJOMSkdqE=
77+
github.com/openmcp-project/controller-utils v0.22.0/go.mod h1:aIF4lk7agc+yCNRN5Oqg4BLlzRKsGixqwsGmxPoO5ak=
7878
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
7979
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8080
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
dario.cat/mergo v1.0.2
1414
github.com/onsi/ginkgo/v2 v2.25.3
1515
github.com/onsi/gomega v1.38.2
16-
github.com/openmcp-project/controller-utils v0.21.0
16+
github.com/openmcp-project/controller-utils v0.22.0
1717
github.com/openmcp-project/openmcp-operator/api v0.14.0
1818
github.com/openmcp-project/openmcp-operator/lib v0.14.0
1919
github.com/spf13/cobra v1.10.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw
9797
github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE=
9898
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
9999
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
100-
github.com/openmcp-project/controller-utils v0.21.0 h1:X5yN/BnJuNX9CXWgIU/cCynWFFv1KLR4zW9nnJl5Izg=
101-
github.com/openmcp-project/controller-utils v0.21.0/go.mod h1:b8VcTK6iXFgkW6pXtIEDbaiQtzqYycVMFmElc7SFBQQ=
100+
github.com/openmcp-project/controller-utils v0.22.0 h1:kdWGds+LOyOaOuKqWZGsJUv17e78HCr5y3bJOMSkdqE=
101+
github.com/openmcp-project/controller-utils v0.22.0/go.mod h1:aIF4lk7agc+yCNRN5Oqg4BLlzRKsGixqwsGmxPoO5ak=
102102
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
103103
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
104104
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

lib/clusteraccess/clusteraccess.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ import (
1111
"k8s.io/apimachinery/pkg/util/wait"
1212
"k8s.io/client-go/tools/clientcmd"
1313

14-
"github.com/openmcp-project/controller-utils/pkg/clusters"
15-
"github.com/openmcp-project/controller-utils/pkg/resources"
1614
corev1 "k8s.io/api/core/v1"
1715
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1816
"k8s.io/apimachinery/pkg/runtime"
1917
"sigs.k8s.io/controller-runtime/pkg/client"
2018
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2119

20+
"github.com/openmcp-project/controller-utils/pkg/clusters"
21+
ctrlutils "github.com/openmcp-project/controller-utils/pkg/controller"
22+
"github.com/openmcp-project/controller-utils/pkg/resources"
23+
2224
clustersv1alpha1 "github.com/openmcp-project/openmcp-operator/api/clusters/v1alpha1"
25+
commonapi "github.com/openmcp-project/openmcp-operator/api/common"
2326
constv1alpha1 "github.com/openmcp-project/openmcp-operator/api/constants"
2427
libutils "github.com/openmcp-project/openmcp-operator/lib/utils"
25-
26-
commonapi "github.com/openmcp-project/openmcp-operator/api/common"
2728
)
2829

2930
const (
@@ -839,11 +840,13 @@ func (m *accessRequestMutator) Mutate(accessRequest *clustersv1alpha1.AccessRequ
839840

840841
// StableRequestName generates a stable name for a Cluster- or AccessRequest related to an MCP.
841842
// This basically results in '<lowercase_controller_name>--<request_name>'.
843+
// If the resulting string exceeds the Kubernetes name length limit of 63 characters, it will be truncated with the last characters replaced by a hash of what was removed.
842844
func StableRequestName(controllerName string, request reconcile.Request) string {
843845
return StableRequestNameFromLocalName(controllerName, request.Name)
844846
}
845847

848+
// StableRequestNameFromLocalName works like StableRequestName but takes a local name directly instead of a reconcile.Request.
846849
func StableRequestNameFromLocalName(controllerName, localName string) string {
847850
controllerName = strings.ToLower(controllerName)
848-
return fmt.Sprintf("%s--%s", controllerName, localName)
851+
return ctrlutils.ShortenToXCharactersUnsafe(fmt.Sprintf("%s--%s", controllerName, localName), ctrlutils.K8sMaxNameLength)
849852
}

lib/clusteraccess/testing.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package clusteraccess
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
corev1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/runtime"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
13+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
14+
15+
"github.com/openmcp-project/controller-utils/pkg/clusters"
16+
"github.com/openmcp-project/controller-utils/pkg/resources"
17+
18+
clustersv1alpha1 "github.com/openmcp-project/openmcp-operator/api/clusters/v1alpha1"
19+
commonapi "github.com/openmcp-project/openmcp-operator/api/common"
20+
openmcpconst "github.com/openmcp-project/openmcp-operator/api/constants"
21+
)
22+
23+
func NewTestClusterAccessManager(platformClusterClient client.Client, controllerName, controllerNamespace string, fakeClientMapping map[string]client.Client) Manager {
24+
return &testManagerImpl{
25+
managerImpl: managerImpl{
26+
platformClusterClient: platformClusterClient,
27+
controllerName: controllerName,
28+
controllerNamespace: controllerNamespace,
29+
timeout: 5 * time.Minute,
30+
interval: 10 * time.Second,
31+
log: nil, // Default to no logging
32+
},
33+
fakeClientMapping: fakeClientMapping,
34+
}
35+
}
36+
37+
type testManagerImpl struct {
38+
managerImpl
39+
fakeClientMapping map[string]client.Client
40+
}
41+
42+
var _ Manager = &testManagerImpl{}
43+
44+
// CreateAndWaitForCluster implements Manager.
45+
func (m *testManagerImpl) CreateAndWaitForCluster(ctx context.Context, localName, purpose string, scheme *runtime.Scheme, permissions []clustersv1alpha1.PermissionsRequest) (*clusters.Cluster, error) {
46+
cr := &clustersv1alpha1.ClusterRequest{
47+
ObjectMeta: metav1.ObjectMeta{
48+
Name: StableRequestNameFromLocalName(m.controllerName, localName),
49+
Namespace: m.controllerNamespace,
50+
},
51+
}
52+
53+
clusterRequestMutator := newClusterRequestMutator(cr.Name, cr.Namespace, purpose)
54+
clusterRequestMutator.WithMetadata(resources.NewMetadataMutator().WithLabels(map[string]string{
55+
openmcpconst.ManagedByLabel: m.controllerName,
56+
}))
57+
58+
if err := resources.CreateOrUpdateResource(ctx, m.platformClusterClient, clusterRequestMutator); err != nil {
59+
return nil, fmt.Errorf("failed to create/update ClusterRequest: %w", err)
60+
}
61+
62+
// TESTING MODIFICATIONS
63+
// fake ClusterRequest readiness
64+
old := cr.DeepCopy()
65+
cr.Status.Phase = clustersv1alpha1.REQUEST_GRANTED
66+
if err := m.platformClusterClient.Status().Patch(ctx, cr, client.MergeFrom(old)); err != nil {
67+
return nil, fmt.Errorf("failed to update ClusterRequest status: %w", err)
68+
}
69+
70+
cl, _, err := m.WaitForClusterAccess(ctx, localName, scheme, &commonapi.ObjectReference{
71+
Name: cr.Name,
72+
Namespace: cr.Namespace,
73+
}, ReferenceToClusterRequest, permissions)
74+
return cl, err
75+
}
76+
77+
// WaitForClusterAccess implements Manager.
78+
func (m *testManagerImpl) WaitForClusterAccess(ctx context.Context, localName string, scheme *runtime.Scheme, ref *commonapi.ObjectReference, refType ClusterReferenceType, permissions []clustersv1alpha1.PermissionsRequest) (*clusters.Cluster, *clustersv1alpha1.AccessRequest, error) {
79+
ar := &clustersv1alpha1.AccessRequest{
80+
ObjectMeta: metav1.ObjectMeta{
81+
Name: StableRequestNameFromLocalName(m.controllerName, localName),
82+
Namespace: m.controllerNamespace,
83+
},
84+
}
85+
86+
accessRequestMutator := newAccessRequestMutator(ar.Name, ar.Namespace)
87+
switch refType {
88+
case ReferenceToCluster:
89+
accessRequestMutator.WithClusterRef(ref)
90+
case ReferenceToClusterRequest:
91+
accessRequestMutator.WithRequestRef(ref)
92+
default:
93+
return nil, nil, fmt.Errorf("invalid ClusterReferenceType: %s", refType)
94+
}
95+
accessRequestMutator.WithTokenPermissions(permissions)
96+
accessRequestMutator.WithMetadata(resources.NewMetadataMutator().WithLabels(map[string]string{
97+
openmcpconst.ManagedByLabel: m.controllerName,
98+
}))
99+
100+
if err := resources.CreateOrUpdateResource(ctx, m.platformClusterClient, accessRequestMutator); err != nil {
101+
return nil, nil, fmt.Errorf("failed to create/update AccessRequest: %w", err)
102+
}
103+
104+
// TESTING MODIFICATIONS
105+
// fake AccessRequest readiness and return cluster from fake client mapping
106+
fakeClient, ok := m.fakeClientMapping[localName]
107+
if !ok {
108+
return nil, nil, fmt.Errorf("no fake client found for local cluster name %q", localName) // simulate AccessRequest not being granted
109+
}
110+
old := ar.DeepCopy()
111+
ar.Status.Phase = clustersv1alpha1.REQUEST_GRANTED
112+
ar.Status.SecretRef = &commonapi.ObjectReference{
113+
Name: ar.Name,
114+
Namespace: ar.Namespace,
115+
}
116+
if err := m.platformClusterClient.Status().Patch(ctx, ar, client.MergeFrom(old)); err != nil {
117+
return nil, nil, fmt.Errorf("failed to update AccessRequest status: %w", err)
118+
}
119+
sec := &corev1.Secret{}
120+
sec.Name = ar.Status.SecretRef.Name
121+
sec.Namespace = ar.Status.SecretRef.Namespace
122+
if _, err := controllerutil.CreateOrUpdate(ctx, m.platformClusterClient, sec, func() error {
123+
sec.Data = map[string][]byte{
124+
clustersv1alpha1.SecretKeyKubeconfig: []byte("fake:" + localName),
125+
}
126+
return nil
127+
}); err != nil {
128+
return nil, nil, fmt.Errorf("failed to create/update fake kubeconfig secret for AccessRequest: %w", err)
129+
}
130+
if fakeClient == nil {
131+
// create new default fake client if none was provided
132+
fakeClient = fake.NewClientBuilder().WithScheme(scheme).Build()
133+
}
134+
return clusters.NewTestClusterFromClient(localName, fakeClient), ar, nil
135+
}

lib/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ replace github.com/openmcp-project/openmcp-operator/api => ../api
77
require (
88
github.com/onsi/ginkgo/v2 v2.25.3
99
github.com/onsi/gomega v1.38.2
10-
github.com/openmcp-project/controller-utils v0.21.0
10+
github.com/openmcp-project/controller-utils v0.22.0
1111
github.com/openmcp-project/openmcp-operator/api v0.14.0
1212
k8s.io/api v0.34.1
1313
k8s.io/apimachinery v0.34.1

lib/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw
7373
github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE=
7474
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
7575
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
76-
github.com/openmcp-project/controller-utils v0.21.0 h1:X5yN/BnJuNX9CXWgIU/cCynWFFv1KLR4zW9nnJl5Izg=
77-
github.com/openmcp-project/controller-utils v0.21.0/go.mod h1:b8VcTK6iXFgkW6pXtIEDbaiQtzqYycVMFmElc7SFBQQ=
76+
github.com/openmcp-project/controller-utils v0.22.0 h1:kdWGds+LOyOaOuKqWZGsJUv17e78HCr5y3bJOMSkdqE=
77+
github.com/openmcp-project/controller-utils v0.22.0/go.mod h1:aIF4lk7agc+yCNRN5Oqg4BLlzRKsGixqwsGmxPoO5ak=
7878
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
7979
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8080
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

0 commit comments

Comments
 (0)