Skip to content
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

Added detach functionality for the Cassandra user #501

Merged
merged 1 commit into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apis/clusterresources/v1beta1/cassandrauser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ func (r *CassandraUser) ToInstAPI(username, password string) *models.InstaUser {
InitialPermission: "standard",
}
}

func (r *CassandraUser) GetDeletionFinalizer() string {
return models.DeletionFinalizer + "_" + r.Namespace + "_" + r.Name
}
2 changes: 1 addition & 1 deletion apis/clusters/v1beta1/cassandra_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type CassandraSpec struct {
PasswordAndUserAuth bool `json:"passwordAndUserAuth,omitempty"`
Spark []*Spark `json:"spark,omitempty"`
BundledUseOnly bool `json:"bundledUseOnly,omitempty"`
UserRef []*UserReference `json:"userRef,omitempty"`
UserRefs []*UserReference `json:"userRefs,omitempty"`
}

// CassandraStatus defines the observed state of Cassandra
Expand Down
4 changes: 2 additions & 2 deletions apis/clusters/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

123 changes: 68 additions & 55 deletions controllers/clusterresources/cassandrauser_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package clusterresources
import (
"context"

"github.com/go-logr/logr"
k8sCore "k8s.io/api/core/v1"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -89,7 +88,27 @@ func (r *CassandraUserReconciler) Reconcile(ctx context.Context, req ctrl.Reques
return models.ReconcileRequeue, nil
}

if controllerutil.AddFinalizer(s, u.GetDeletionFinalizer()) {
err = r.Update(ctx, s)
if err != nil {
l.Error(err, "Cannot update Cassandra user's secret with deletion finalizer",
"secret name", s.Name, "secret namespace", s.Namespace)
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Update secret with deletion finalizer has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}
}

patch := u.NewPatch()
if controllerutil.AddFinalizer(u, u.GetDeletionFinalizer()) {
err = r.Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot patch Cassandra user with deletion finalizer")
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Patching Cassandra user with deletion finalizer has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}
}

username, password, err := getUserCreds(s)
if err != nil {
Expand Down Expand Up @@ -132,21 +151,7 @@ func (r *CassandraUserReconciler) Reconcile(ctx context.Context, req ctrl.Reques
"User has been created for a cluster. Cluster ID: %s, username: %s",
clusterID, username)

finalizerNeeded := controllerutil.AddFinalizer(s, models.DeletionFinalizer)
if finalizerNeeded {
err = r.Update(ctx, s)
if err != nil {
l.Error(err, "Cannot update Cassandra user secret",
"secret name", s.Name,
"secret namespace", s.Namespace)
r.EventRecorder.Eventf(u, models.Warning, models.UpdatedEvent,
"Cannot assign Cassandra user to a k8s secret. Reason: %v", err)

return models.ReconcileRequeue, nil
}
}

controllerutil.AddFinalizer(u, models.DeletionUserFinalizer+clusterID)
controllerutil.AddFinalizer(u, getDeletionUserFinalizer(clusterID))
err = r.Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot patch Cassandra user resource",
Expand Down Expand Up @@ -188,7 +193,7 @@ func (r *CassandraUserReconciler) Reconcile(ctx context.Context, req ctrl.Reques
return models.ReconcileRequeue, nil
}

controllerutil.RemoveFinalizer(u, models.DeletionUserFinalizer+clusterID)
controllerutil.RemoveFinalizer(u, getDeletionUserFinalizer(clusterID))
err = r.Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot patch Cassandra user resource",
Expand All @@ -202,58 +207,66 @@ func (r *CassandraUserReconciler) Reconcile(ctx context.Context, req ctrl.Reques

continue
}
}

if u.DeletionTimestamp != nil {
err = r.handleDeleteUser(ctx, l, s, u)
if err != nil {
return models.ReconcileRequeue, nil
}
}

return models.ExitReconcile, nil
}
if event == models.ClusterDeletingEvent {
delete(u.Status.ClustersEvents, clusterID)
err = r.Status().Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot detach clusterID from the Cassandra user resource",
"cluster ID", clusterID)
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Detaching clusterID from the OpenSearch user resource has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}

func (r *CassandraUserReconciler) handleDeleteUser(
ctx context.Context,
l logr.Logger,
s *k8sCore.Secret,
u *v1beta1.CassandraUser,
) error {
username, _, err := getUserCreds(s)
if err != nil {
l.Error(err, "Cannot get user credentials")
r.EventRecorder.Eventf(u, models.Warning, models.CreatingEvent,
"Cannot get user credentials. Reason: %v", err)
controllerutil.RemoveFinalizer(u, getDeletionUserFinalizer(clusterID))
err = r.Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot delete finalizer from the Cassandra user resource",
"cluster ID", clusterID)
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Deleting finalizer from the Cassandra user resource has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}

return err
l.Info("Cassandra user has been detached from the cluster", "cluster ID", clusterID)
r.EventRecorder.Eventf(u, models.Normal, models.Deleted,
"User has been detached from the cluster. ClusterID: %v", clusterID)
}
}

for clusterID, event := range u.Status.ClustersEvents {
if event == models.Created || event == models.CreatingEvent {
l.Error(models.ErrUserStillExist, "please remove the user from the cluster specification",
"username", username, "cluster ID", clusterID)
if u.DeletionTimestamp != nil {
if u.Status.ClustersEvents != nil {
l.Error(models.ErrUserStillExist, "Please remove the user from the cluster specification")
r.EventRecorder.Event(u, models.Warning, models.DeletingEvent,
"The user is still attached to cluster, please remove the user from the cluster specification.")

return models.ErrUserStillExist
return models.ExitReconcile, nil
}
}

l.Info("Cassandra user has been deleted", "username", username)

controllerutil.RemoveFinalizer(s, models.DeletionFinalizer)
err = r.Update(ctx, s)
if err != nil {
l.Error(err, "Cannot remove finalizer from secret", "secret name", s.Name)
controllerutil.RemoveFinalizer(s, u.GetDeletionFinalizer())
err = r.Update(ctx, s)
if err != nil {
l.Error(err, "Cannot delete finalizer from the user's secret")
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Deleting finalizer from the user's secret has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}

r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Resource patch is failed. Reason: %v", err)
controllerutil.RemoveFinalizer(u, u.GetDeletionFinalizer())
err = r.Patch(ctx, u, patch)
if err != nil {
l.Error(err, "Cannot delete finalizer from the Cassandra user resource")
r.EventRecorder.Eventf(u, models.Warning, models.PatchFailed,
"Deleting finalizer from the OpenSearch user resource has been failed. Reason: %v", err)
return models.ReconcileRequeue, nil
}

return err
l.Info("The user resource has been deleted")
return models.ExitReconcile, nil
}

return nil
return models.ExitReconcile, nil
}

// SetupWithManager sets up the controller with the Manager.
Expand Down
Loading