-
Notifications
You must be signed in to change notification settings - Fork 11
feat(clusters): delete cluster if secret is deleted (#2060) #2142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
36235fa
e250673
1087cde
9613514
426ed5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,10 @@ func (r *BootstrapReconciler) SetupWithManager(name string, mgr ctrl.Manager) er | |
| func (r *BootstrapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
| var kubeConfigSecret = new(corev1.Secret) | ||
| if err := r.Get(ctx, req.NamespacedName, kubeConfigSecret); err != nil { | ||
| if client.IgnoreNotFound(err) == nil { | ||
| // missing secret - initiate cluster deletion if it already exists | ||
| return ctrl.Result{}, r.requestClusterDeletion(ctx, req.NamespacedName) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This wonβt work. If secret is missing we cannot clean up helm releases. During bootstrap process please add a finalizer to secret so you can initiate cluster deletion, which in turn will initiate plugins deletion.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ACK. |
||
| } | ||
|
Comment on lines
65
to
+69
|
||
| return ctrl.Result{}, client.IgnoreNotFound(err) | ||
| } | ||
| if kubeConfigSecret.Type == greenhouseapis.SecretTypeOIDCConfig { | ||
|
|
@@ -217,6 +221,15 @@ func (r *BootstrapReconciler) getCluster(ctx context.Context, kubeConfigSecret * | |
| return cluster, client.IgnoreNotFound(err) | ||
| } | ||
|
|
||
| func (r *BootstrapReconciler) requestClusterDeletion(ctx context.Context, namespacedName types.NamespacedName) error { | ||
| cluster := greenhousev1alpha1.Cluster{} | ||
| if err := r.Get(ctx, namespacedName, &cluster); err != nil { | ||
| return client.IgnoreNotFound(err) | ||
| } | ||
| log.FromContext(ctx).Info("Cluster secret not found, requesting Cluster deletion", "cluster", namespacedName.String()) | ||
| return client.IgnoreNotFound(r.Delete(ctx, &cluster)) | ||
| } | ||
|
|
||
| func enqueueSecretForCluster(_ context.Context, o client.Object) []ctrl.Request { | ||
| cluster, ok := o.(*greenhousev1alpha1.Cluster) | ||
| if !ok { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -294,8 +294,13 @@ func (r *RemoteClusterReconciler) EnsureDeleted(ctx context.Context, resource li | |
|
|
||
| kubeConfigSecret := &corev1.Secret{} | ||
| if err := r.Get(ctx, types.NamespacedName{Namespace: cluster.GetNamespace(), Name: cluster.GetSecretName()}, kubeConfigSecret); err != nil { | ||
| return ctrl.Result{}, lifecycle.Failed, err | ||
| log.FromContext(ctx).Info("cannot fetch secret", "cluster", cluster.Name, "error", err.Error()) | ||
| if client.IgnoreNotFound(err) != nil { | ||
| return ctrl.Result{}, lifecycle.Failed, err | ||
| } | ||
| return ctrl.Result{}, lifecycle.Success, nil | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm doesn't
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's skipping it, as there is no secret with configuration data needed to make the connection, which is needed to perform that cleanup.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anyway - instead of trying to unblock deletion there - i'll be going into "finalizer on a secret" path suggested by Abhi. |
||
| } | ||
|
|
||
| // early return if the cluster connectivity is via OIDC | ||
| if kubeConfigSecret.Type == greenhouseapis.SecretTypeOIDCConfig { | ||
| log.FromContext(ctx).Info("no resources to clean up", "secretType", kubeConfigSecret.Type, "cluster", cluster.Name) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -235,31 +235,4 @@ var _ = Describe("Cluster status", Ordered, func() { | |
| g.Expect(validCluster.Status.KubernetesVersion).ToNot(BeNil()) | ||
| }).Should(Succeed()) | ||
| }) | ||
|
|
||
| It("should reconcile the status of a cluster without a secret", func() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't we loosing coverage here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are loosing the coverage for the thing, which is removed by this PR. This whole task is to remove cluster which does not have already "access secret" - without which cluster can not be accessed, so if the cluster has to be removed, there is no way to reconcile its status. |
||
| By("checking cluster conditions") | ||
| Eventually(func(g Gomega) { | ||
| g.Expect(test.K8sClient.Get(test.Ctx, types.NamespacedName{Name: invalidCluster.Name, Namespace: setup.Namespace()}, invalidCluster)).ShouldNot(HaveOccurred(), "There should be no error getting the cluster resource") | ||
| g.Expect(invalidCluster.Status.StatusConditions).ToNot(BeNil()) | ||
| // Accessible condition validation. | ||
| accessibleCondition := invalidCluster.Status.GetConditionByType(greenhousev1alpha1.PermissionsVerified) | ||
| g.Expect(accessibleCondition).ToNot(BeNil(), "The Accessible condition should be present") | ||
| g.Expect(accessibleCondition.Status).To(Equal(metav1.ConditionUnknown), "The Accessible condition should be unknown") | ||
| g.Expect(accessibleCondition.Message).To(Equal("kubeconfig not valid - cannot validate cluster access")) | ||
| // ManagedResourcesDeployed condition validation. | ||
| managedResourcesDeployes := invalidCluster.Status.GetConditionByType(greenhousev1alpha1.ManagedResourcesDeployed) | ||
| g.Expect(managedResourcesDeployes).ToNot(BeNil(), "The ManagedResourcesDeployed condition should be present") | ||
| g.Expect(managedResourcesDeployes.Status).To(Equal(metav1.ConditionUnknown), "The ManagedResourcesDeployed condition should be unknown") | ||
| g.Expect(managedResourcesDeployes.Message).To(Equal("kubeconfig not valid - cannot validate managed resources")) | ||
| // KubeConfigValid condition validation. | ||
| kubeConfigValidCondition := invalidCluster.Status.GetConditionByType(greenhousev1alpha1.KubeConfigValid) | ||
| g.Expect(kubeConfigValidCondition).ToNot(BeNil(), "The KubeConfigValid condition should be present") | ||
| g.Expect(kubeConfigValidCondition.Status).To(Equal(metav1.ConditionFalse)) | ||
| g.Expect(kubeConfigValidCondition.Message).To(ContainSubstring("Secret \"" + invalidCluster.Name + "\" not found")) | ||
| // Ready condition validation. | ||
| readyCondition := invalidCluster.Status.GetConditionByType(greenhousemetav1alpha1.ReadyCondition) | ||
| g.Expect(readyCondition).ToNot(BeNil(), "The ClusterReady condition should be present") | ||
| g.Expect(readyCondition.Status).To(Equal(metav1.ConditionFalse)) | ||
| }).Should(Succeed()) | ||
| }) | ||
| }) | ||
Uh oh!
There was an error while loading. Please reload this page.