Skip to content

Commit 4490088

Browse files
authored
fix: update the controlplane resource even when in deletion (#216)
1 parent 1f0afc9 commit 4490088

File tree

11 files changed

+212
-32
lines changed

11 files changed

+212
-32
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.42.0-dev
1+
v0.42.1

charts/mcp-operator/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ apiVersion: v2
22
name: mcp-operator
33
description: A Helm chart for the mcp-operator
44
type: application
5-
version: v0.42.0
6-
appVersion: v0.42.0
5+
version: v0.42.1
6+
appVersion: v0.42.1
77
home: https://github.com/openmcp-project/mcp-operator
88
sources:
99
- https://github.com/openmcp-project/mcp-operator

charts/mcp-operator/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ deployment:
1414

1515
image:
1616
repository: ghcr.io/openmcp-project/images/mcp-operator
17-
tag: v0.42.0
17+
tag: v0.42.1
1818
pullPolicy: IfNotPresent
1919

2020
imagePullSecrets: []

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/openmcp-project/cluster-provider-gardener/api v0.9.0
1717
github.com/openmcp-project/control-plane-operator v0.1.17
1818
github.com/openmcp-project/controller-utils v0.23.1
19-
github.com/openmcp-project/mcp-operator/api v0.42.0
19+
github.com/openmcp-project/mcp-operator/api v0.42.1
2020
github.com/openmcp-project/openmcp-operator/api v0.15.2
2121
github.com/openmcp-project/openmcp-operator/lib v0.15.2
2222
github.com/openmcp-project/service-provider-landscaper v0.7.0

internal/controller/core/cloudorchestrator/controller.go

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,43 @@ func (r *CloudOrchestratorReconciler) reconcile(ctx context.Context, req ctrl.Re
163163
return components.ReconcileResult[*openmcpv1alpha1.CloudOrchestrator]{Component: co, ReconcileError: openmcperrors.WithReason(fmt.Errorf("APIServer dependency is ready, but no kubeconfig could be found in its status"), cconst.ReasonDependencyStatusInvalid)}, coreControlPlane, "", ""
164164
}
165165

166+
// only create the ControlPlane resource if it doesn't exist yet and the CO resource is not being deleted
167+
if co.DeletionTimestamp.IsZero() && coreControlPlane == nil {
168+
// ControlPlane from Core Cluster
169+
coreControlPlane = &corev1beta1.ControlPlane{
170+
ObjectMeta: metav1.ObjectMeta{
171+
Name: utils.PrefixWithNamespace(co.Namespace, co.Name),
172+
},
173+
}
174+
}
175+
176+
// create or update the ControlPlane resource in the Core Cluster
177+
// this will handle both creation and update scenarios
178+
// it is not being called when in deletion and the control plane doesn't exist anymore
179+
if coreControlPlane != nil {
180+
// create or update the CO ControlPlane with the configuration from the openmcpv1alpha1.CloudOrchestrator CR
181+
_, err = controllerutil.CreateOrUpdate(ctx, r.CoreClient, coreControlPlane, func() error {
182+
spec, err := convertToControlPlaneSpec(&co.Spec, &as.Status)
183+
if err != nil {
184+
return err
185+
}
186+
coreControlPlane.Spec = *spec
187+
188+
// update labels
189+
labels, err := r.copyLabels(ctx, co)
190+
if err != nil {
191+
return err
192+
}
193+
coreControlPlane.Labels = labels
194+
return nil
195+
})
196+
errs := openmcperrors.NewReasonableErrorList()
197+
if err != nil {
198+
errs = errs.Append(openmcperrors.Join(errModifyingControlPlane, err))
199+
return components.ReconcileResult[*openmcpv1alpha1.CloudOrchestrator]{Component: co, ReconcileError: errs.Aggregate()}, coreControlPlane, "", ""
200+
}
201+
}
202+
166203
if !co.DeletionTimestamp.IsZero() {
167204
// handle deletion
168205
log.Info("Deleting CloudOrchestrator")
@@ -230,33 +267,8 @@ func (r *CloudOrchestratorReconciler) reconcile(ctx context.Context, req ctrl.Re
230267
return components.ReconcileResult[*openmcpv1alpha1.CloudOrchestrator]{Component: co, ReconcileError: openmcperrors.WithReason(fmt.Errorf("error setting dependency finalizer on Authorization component resource: %w", err), cconst.ReasonCrateClusterInteractionProblem)}, coreControlPlane, "", ""
231268
}
232269

233-
// ControlPlane from Core Cluster
234-
coreControlPlane = &corev1beta1.ControlPlane{
235-
ObjectMeta: metav1.ObjectMeta{
236-
Name: utils.PrefixWithNamespace(co.Namespace, co.Name),
237-
},
238-
}
239-
240-
// create or update the CO ControlPlane with the configuration from the openmcpv1alpha1.CloudOrchestrator CR
241-
_, err = controllerutil.CreateOrUpdate(ctx, r.CoreClient, coreControlPlane, func() error {
242-
spec, err := convertToControlPlaneSpec(&co.Spec, &as.Status)
243-
if err != nil {
244-
return err
245-
}
246-
coreControlPlane.Spec = *spec
247-
248-
// update labels
249-
labels, err := r.copyLabels(ctx, co)
250-
if err != nil {
251-
return err
252-
}
253-
coreControlPlane.Labels = labels
254-
return nil
255-
})
256-
errs := openmcperrors.NewReasonableErrorList()
257-
if err != nil {
258-
errs = errs.Append(openmcperrors.Join(errModifyingControlPlane, err))
259-
return components.ReconcileResult[*openmcpv1alpha1.CloudOrchestrator]{Component: co, ReconcileError: errs.Aggregate()}, coreControlPlane, "", ""
270+
if coreControlPlane == nil {
271+
return components.ReconcileResult[*openmcpv1alpha1.CloudOrchestrator]{Component: co, ReconcileError: openmcperrors.WithReason(fmt.Errorf("CloudOrchestrator ControlPlane resource not found"), cconst.ReasonCOCoreClusterInteractionProblem)}, nil, "", ""
260272
}
261273

262274
// find out if the CO ControlPlane resource is Ready

internal/controller/core/cloudorchestrator/controller_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,75 @@ var _ = Describe("CO-1153 CloudOrchestrator Controller", func() {
428428
Expect(cp.Spec.Target.Kubeconfig).NotTo(BeNil())
429429
Expect(cp.Spec.Crossplane).To(BeNil())
430430
})
431+
432+
It("should update the ControlPlane resource even when in deletion", func() {
433+
var err error
434+
435+
env := testEnvSetup(path.Join("testdata", "test-09"), "")
436+
437+
co := &openmcpv1alpha1.CloudOrchestrator{}
438+
err = env.Client(testutils.CrateCluster).Get(env.Ctx, types.NamespacedName{Name: "test", Namespace: "test"}, co)
439+
Expect(err).NotTo(HaveOccurred())
440+
441+
req := testing.RequestFromObject(co)
442+
_ = env.ShouldReconcile(coReconciler, req)
443+
444+
err = env.Client(testutils.CrateCluster).Get(env.Ctx, client.ObjectKeyFromObject(co), co)
445+
Expect(err).NotTo(HaveOccurred())
446+
447+
Expect(co.Status.Conditions).To(ConsistOf(
448+
MatchComponentCondition(openmcpv1alpha1.ComponentCondition{
449+
Type: openmcpv1alpha1.CloudOrchestratorComponent.HealthyCondition(),
450+
Status: openmcpv1alpha1.ComponentConditionStatusFalse,
451+
Reason: cconst.ReasonWaitingForCloudOrchestrator,
452+
}),
453+
MatchComponentCondition(openmcpv1alpha1.ComponentCondition{
454+
Type: openmcpv1alpha1.CloudOrchestratorComponent.ReconciliationCondition(),
455+
Status: openmcpv1alpha1.ComponentConditionStatusTrue,
456+
}),
457+
))
458+
459+
cp := &corev1beta1.ControlPlane{}
460+
err = env.Client(testutils.COCoreCluster).Get(env.Ctx, types.NamespacedName{
461+
Namespace: "",
462+
Name: "test--test",
463+
}, cp)
464+
Expect(err).NotTo(HaveOccurred())
465+
Expect(cp.Spec.Target.Kubeconfig).NotTo(BeNil())
466+
// set a finalizer to simulate deletion
467+
controllerutil.AddFinalizer(cp, "core.orchestrate.cloud.sap")
468+
err = env.Client(testutils.COCoreCluster).Update(env.Ctx, cp)
469+
Expect(err).NotTo(HaveOccurred())
470+
471+
// Delete CO resource
472+
err = env.Client(testutils.CrateCluster).Delete(env.Ctx, co)
473+
Expect(err).ToNot(HaveOccurred())
474+
_ = env.ShouldReconcile(coReconciler, req)
475+
476+
// check that the ControlPlane resource has a deletion timestamp
477+
err = env.Client(testutils.COCoreCluster).Get(env.Ctx, types.NamespacedName{
478+
Namespace: "",
479+
Name: "test--test",
480+
}, cp)
481+
Expect(err).NotTo(HaveOccurred())
482+
Expect(cp.DeletionTimestamp).ToNot(BeNil())
483+
484+
// Update CO resource to trigger an update on the ControlPlane resource
485+
err = env.Client(testutils.CrateCluster).Get(env.Ctx, types.NamespacedName{Name: "test", Namespace: "test"}, co)
486+
Expect(err).NotTo(HaveOccurred())
487+
co.Spec.Kyverno = &openmcpv1alpha1.KyvernoConfig{
488+
Version: "8.8.8",
489+
}
490+
err = env.Client(testutils.CrateCluster).Update(env.Ctx, co)
491+
Expect(err).NotTo(HaveOccurred())
492+
_ = env.ShouldReconcile(coReconciler, req)
493+
494+
err = env.Client(testutils.COCoreCluster).Get(env.Ctx, types.NamespacedName{
495+
Namespace: "",
496+
Name: "test--test",
497+
}, cp)
498+
Expect(err).NotTo(HaveOccurred())
499+
Expect(cp.Spec.Kyverno).ToNot(BeNil())
500+
Expect(cp.Spec.Kyverno.Version).To(Equal("8.8.8"))
501+
})
431502
})
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
apiVersion: core.openmcp.cloud/v1alpha1
2+
kind: APIServer
3+
metadata:
4+
name: test
5+
namespace: test
6+
labels:
7+
"openmcp.cloud/mcp-generation": "1"
8+
spec:
9+
desiredRegion:
10+
direction: central
11+
name: europe
12+
type: GardenerDedicated
13+
status:
14+
conditions:
15+
- lastTransitionTime: "2024-05-22T08:23:47Z"
16+
status: "True"
17+
type: apiServerHealthy
18+
observedGenerations:
19+
internalConfiguration: -1
20+
managedControlPlane: 1
21+
resource: 0
22+
adminAccess:
23+
creationTimestamp: "2024-05-22T08:23:47Z"
24+
expirationTimestamp: "2024-11-18T08:23:47Z"
25+
kubeconfig: |
26+
apiVersion: v1
27+
clusters:
28+
- name: apiserver
29+
cluster:
30+
server: https://apiserver.dummy
31+
certificate-authority-data: ZHVtbXkK
32+
contexts:
33+
- name: apiserver
34+
context:
35+
cluster: apiserver
36+
user: apiserver
37+
current-context: apiserver
38+
users:
39+
- name: apiserver
40+
user:
41+
client-certificate-data: ZHVtbXkK
42+
client-key-data: ZHVtbXkK
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: core.openmcp.cloud/v1alpha1
2+
kind: Authentication
3+
metadata:
4+
generation: 1
5+
labels:
6+
openmcp.cloud/mcp-generation: "1"
7+
name: test
8+
namespace: test
9+
spec:
10+
enableSystemIdentityProvider: true
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: core.openmcp.cloud/v1alpha1
2+
kind: Authorization
3+
metadata:
4+
generation: 1
5+
labels:
6+
openmcp.cloud/mcp-generation: "1"
7+
name: test
8+
namespace: test
9+
spec:
10+
roleBindings:
11+
- role: admin
12+
subjects:
13+
- apiGroup: rbac.authorization.k8s.io
14+
kind: User
15+
name: john.doe@example.com
16+
- role: view
17+
subjects: []
18+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: core.openmcp.cloud/v1alpha1
2+
kind: CloudOrchestrator
3+
metadata:
4+
name: test
5+
namespace: test
6+
labels:
7+
"openmcp.cloud/mcp-generation": "1"
8+
finalizers:
9+
- cloudorchestrator.openmcp.cloud
10+
spec:
11+
crossplane:
12+
version: 1.17.0
13+
providers:
14+
- name: provider-kubernetes
15+
version: 0.14.1
16+
btpServiceOperator:
17+
version: 0.6.0
18+
externalSecretsOperator:
19+
version: 0.10.0
20+
kyverno:
21+
version: 3.2.7
22+
flux:
23+
version: 3.2.0

0 commit comments

Comments
 (0)