Skip to content

Commit

Permalink
push
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Gupta <[email protected]>
  • Loading branch information
shubham-cmyk committed Nov 9, 2023
1 parent 6ab929c commit 6211a83
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 18 deletions.
8 changes: 5 additions & 3 deletions controllers/redis_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ import (
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// RedisReconciler reconciles a Redis object
type RedisReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
K8sClient kubernetes.Interface
Log logr.Logger
Scheme *runtime.Scheme
}

// Reconcile is part of the main kubernetes reconciliation loop which aims
Expand All @@ -53,7 +55,7 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
reqLogger.Info("Found annotations redis.opstreelabs.in/skip-reconcile, so skipping reconcile")
return ctrl.Result{RequeueAfter: time.Second * 10}, nil
}
if err = k8sutils.HandleRedisFinalizer(instance, r.Client); err != nil {
if err = k8sutils.HandleRedisFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil {
return ctrl.Result{}, err
}

Expand Down
26 changes: 11 additions & 15 deletions k8sutils/finalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package k8sutils

import (
"context"
"fmt"
"strconv"

redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
"github.com/OT-CONTAINER-KIT/redis-operator/mocks"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
Expand All @@ -26,16 +29,15 @@ func finalizerLogger(namespace string, name string) logr.Logger {
}

// HandleRedisFinalizer finalize resource if instance is marked to be deleted
func HandleRedisFinalizer(cr *redisv1beta2.Redis, cl client.Client) error {
logger := finalizerLogger(cr.Namespace, RedisFinalizer)
func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error {
if cr.GetDeletionTimestamp() != nil {
if controllerutil.ContainsFinalizer(cr, RedisFinalizer) {
if err := finalizeRedisPVC(cr); err != nil {
if err := finalizeRedisPVC(k8sClient, logger, cr); err != nil {
return err
}
controllerutil.RemoveFinalizer(cr, RedisFinalizer)
if err := cl.Update(context.TODO(), cr); err != nil {
logger.Error(err, "Could not remove finalizer "+RedisFinalizer)
if err := ctrlclient.Update(context.TODO(), cr); err != nil {
logger.Error(err, "Could not remove finalizer", "finalizer", RedisFinalizer)
return err
}
}
Expand Down Expand Up @@ -134,17 +136,11 @@ func AddRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client)
}

// finalizeRedisPVC delete PVC
func finalizeRedisPVC(cr *redisv1beta2.Redis) error {
logger := finalizerLogger(cr.Namespace, RedisFinalizer)
PVCName := cr.Name + "-" + cr.Name + "-0"
client, err := generateK8sClient(generateK8sConfig)
if err != nil {
logger.Error(err, "Could not generate kubernetes client")
return err
}
err = client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{})
func finalizeRedisPVC(client kubernetes.Interface, logger mocks.LoggerInterface, cr *redisv1beta2.Redis) error {
PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name)
err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName)
logger.Error(err, "Could not delete Persistent Volume Claim", "PVCName", PVCName)
return err
}
return nil
Expand Down
122 changes: 122 additions & 0 deletions k8sutils/finalizers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package k8sutils

import (
"context"
"fmt"
"testing"

"github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2"
"github.com/go-logr/logr/testr"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClientFake "k8s.io/client-go/kubernetes/fake"
)

// func TestHandleRedisFinalizer(t *testing.T) {
// cr := &v1beta2.Redis{
// TypeMeta: metav1.TypeMeta{
// Kind: "Redis",
// APIVersion: "redis.opstreelabs.in/v1beta2",
// },
// ObjectMeta: metav1.ObjectMeta{
// Name: "test-redis",
// Namespace: "default",
// DeletionTimestamp: &metav1.Time{Time: time.Now()},
// Finalizers: []string{RedisFinalizer},
// },
// }

// // Create a fake controller-runtime client
// scheme := runtime.NewScheme()
// mockAddToScheme := v1beta2.SchemeBuilder.Register(&v1beta2.Redis{}, &v1beta2.RedisList{}).AddToScheme(scheme)
// utilruntime.Must(mockAddToScheme)

// ctrlFakeclient := ctrlClientFake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(cr.DeepCopyObject()).Build()
// k8sFakeClient := k8sClientFake.NewSimpleClientset(cr.DeepCopyObject())

// logger := testr.New(t)
// // Run the HandleRedisFinalizer function
// err := HandleRedisFinalizer(ctrlFakeclient, k8sFakeClient, logger, cr)
// assert.NoError(t, err)

// // Check if the PVC was deleted
// PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name)
// _, err = k8sFakeClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), PVCName, metav1.GetOptions{})
// assert.True(t, k8serrors.IsNotFound(err))

// // Check if the finalizer was removed
// updatedCR := &v1beta2.Redis{}
// err = ctrlFakeclient.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "test-redis"}, updatedCR)
// assert.NoError(t, err)
// assert.NotContains(t, updatedCR.GetFinalizers(), RedisFinalizer)

// // Ensure the logger's Error method was not called
// //logger.AssertNotCalled(t, "Error", mock.Anything, mock.Anything, mock.Anything)
// }

func TestFinalizeRedisPVC(t *testing.T) {
tests := []struct {
name string
existingPVC *corev1.PersistentVolumeClaim
expectError bool
errorExpected error
}{
{
name: "PVC exists and is deleted successfully",
existingPVC: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "test-redis-test-redis-0",
Namespace: "default",
},
},
expectError: false,
errorExpected: nil,
},
{
name: "PVC does not exist and no error should be returned",
existingPVC: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "nonexistent",
Namespace: "default",
},
},
expectError: false,
errorExpected: nil,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
logger := testr.New(t)
cr := &v1beta2.Redis{
ObjectMeta: metav1.ObjectMeta{
Name: "test-redis",
Namespace: "default",
},
}
var k8sClient *k8sClientFake.Clientset
if tc.existingPVC != nil {
k8sClient = k8sClientFake.NewSimpleClientset(tc.existingPVC.DeepCopyObject())
} else {
k8sClient = k8sClientFake.NewSimpleClientset()
}

err := finalizeRedisPVC(k8sClient, logger, cr)
if tc.expectError {
assert.Error(t, err)
assert.Equal(t, tc.errorExpected, err)
} else {
assert.NoError(t, err)
}

// Verify that the PVC is not found in case of success or non-existent PVC
if !tc.expectError {
pvcName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name)
_, err = k8sClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{})
assert.True(t, k8serrors.IsNotFound(err))
}
})
}
}
5 changes: 5 additions & 0 deletions mocks/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package mocks

type LoggerInterface interface {
Error(error, string, ...interface{})
}

0 comments on commit 6211a83

Please sign in to comment.