Skip to content

Commit

Permalink
Increase unit test coverage (#785)
Browse files Browse the repository at this point in the history
  • Loading branch information
donatwork authored Nov 19, 2024
1 parent 5bc17bd commit a51fbb3
Show file tree
Hide file tree
Showing 19 changed files with 4,936 additions and 113 deletions.
9 changes: 6 additions & 3 deletions controllers/csm_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,12 @@ func (r *ContainerStorageModuleReconciler) Reconcile(_ context.Context, req ctrl
err = utils.UpdateStatus(ctx, csm, r, newStatus)
if err != nil && !unitTestRun {
log.Error(err, "Failed to update CR status")
return utils.LogBannerAndReturn(reconcile.Result{Requeue: true}, err)
utils.LogEndReconcile()
return reconcile.Result{Requeue: true}, err
}
r.EventRecorder.Eventf(csm, corev1.EventTypeNormal, csmv1.EventCompleted, "install/update storage component: %s completed OK", csm.Name)
return utils.LogBannerAndReturn(reconcile.Result{}, nil)
utils.LogEndReconcile()
return reconcile.Result{}, nil
}

// syncErr can be nil, even if CSM state = failed
Expand All @@ -366,7 +368,8 @@ func (r *ContainerStorageModuleReconciler) Reconcile(_ context.Context, req ctrl
// Failed deployment
r.EventRecorder.Eventf(csm, corev1.EventTypeWarning, csmv1.EventUpdated, "Failed install: %s", syncErr.Error())

return utils.LogBannerAndReturn(reconcile.Result{Requeue: true}, syncErr)
utils.LogEndReconcile()
return reconcile.Result{Requeue: true}, syncErr
}

func (r *ContainerStorageModuleReconciler) ignoreUpdatePredicate() predicate.Predicate {
Expand Down
2 changes: 1 addition & 1 deletion pkg/drivers/commonconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func GetNode(ctx context.Context, cr csmv1.ContainerStorageModule, operatorConfi

for i := range initcontainers {
utils.ReplaceAllContainerImageApply(operatorConfig.K8sVersion, &initcontainers[i])
utils.UpdateinitContainerApply(cr.Spec.Driver.InitContainers, &initcontainers[i])
utils.UpdateInitContainerApply(cr.Spec.Driver.InitContainers, &initcontainers[i])
}

nodeYaml.DaemonSetApplyConfig.Spec.Template.Spec.InitContainers = initcontainers
Expand Down
2 changes: 2 additions & 0 deletions pkg/modules/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,8 @@ func getCerts(ctx context.Context, op utils.OperatorConfig, cr csmv1.ContainerSt
authHostname = component.Hostname
authCertificate = component.Certificate
authPrivateKey = component.PrivateKey

log.Infof("Authorization hostname: %s", authHostname)
}
}

Expand Down
126 changes: 126 additions & 0 deletions pkg/resources/configmap/configmap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configmap

import (
"context"
"errors"
"testing"

common "github.com/dell/csm-operator/pkg/utils"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestSyncConfigMap(t *testing.T) {
ctx := context.TODO()
configMap := corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "test-configmap",
Namespace: "test-namespace",
},
Data: map[string]string{
"key": "value",
},
}

t.Run("Create new ConfigMap", func(t *testing.T) {
// fake client
client := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build()

err := SyncConfigMap(ctx, configMap, client)
assert.NoError(t, err)

// check that the configmap was created
foundConfigMap := &corev1.ConfigMap{}
err = client.Get(ctx, types.NamespacedName{Name: configMap.Name, Namespace: configMap.Namespace}, foundConfigMap)
assert.NoError(t, err)
assert.Equal(t, configMap.Data, foundConfigMap.Data)

// Check that the ConfigMap has the correct data
if foundConfigMap.Data["key"] != configMap.Data["key"] {
t.Errorf("ConfigMap has incorrect data: expected %s, got %s", configMap.Data["key"], foundConfigMap.Data["key"])
}
})

t.Run("Update existing ConfigMap", func(t *testing.T) {
// fake client
client := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(&configMap).Build()

updatedConfigMap := configMap.DeepCopy()
updatedConfigMap.Data["key"] = "new-value"

err := SyncConfigMap(ctx, *updatedConfigMap, client)
assert.NoError(t, err)

// check that the configmap was updated
foundConfigMap := &corev1.ConfigMap{}
err = client.Get(ctx, types.NamespacedName{Name: configMap.Name, Namespace: configMap.Namespace}, foundConfigMap)
assert.NoError(t, err)
assert.Equal(t, updatedConfigMap.Data, foundConfigMap.Data)

// Check that the ConfigMap has the correct data
if foundConfigMap.Data["key"] != updatedConfigMap.Data["key"] {
t.Errorf("ConfigMap has incorrect data: expected %s, got %s", updatedConfigMap.Data["key"], foundConfigMap.Data["key"])
}
})

t.Run("Handle error on getting ConfigMap", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, _ client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return errors.New("get error")
},
}

err := SyncConfigMap(ctx, configMap, client)
assert.Error(t, err)
assert.Equal(t, "get error", err.Error())
})

t.Run("Handle error on creating ConfigMap", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, key client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return apierrors.NewNotFound(corev1.Resource("configmap"), key.Name)
},
CreateFunc: func(_ context.Context, _ client.Object, _ ...client.CreateOption) error {
return errors.New("create error")
},
}

err := SyncConfigMap(ctx, configMap, client)
assert.Error(t, err)
assert.Equal(t, "creating configmap: create error", err.Error())
})

t.Run("Handle error on updating ConfigMap", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, _ client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return nil
},

UpdateFunc: func(_ context.Context, _ client.Object, _ ...client.UpdateOption) error {
return errors.New("update error")
},
}

err := SyncConfigMap(ctx, configMap, client)
assert.Error(t, err)
assert.Equal(t, "updating configmap: update error", err.Error())
})
}
111 changes: 111 additions & 0 deletions pkg/resources/csidriver/csidriver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package csidriver

import (
"context"
"errors"
"testing"

common "github.com/dell/csm-operator/pkg/utils"
"github.com/stretchr/testify/assert"
storagev1 "k8s.io/api/storage/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestSyncCSIDriver(t *testing.T) {
ctx := context.TODO()
csiDriver := storagev1.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "test-csidriver",
},
}

t.Run("Create new CSIDriver", func(t *testing.T) {
// fake client
client := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build()

err := SyncCSIDriver(ctx, csiDriver, client)
assert.NoError(t, err)

// check that the csidriver was created
foundCSIDriver := &storagev1.CSIDriver{}
err = client.Get(ctx, types.NamespacedName{Name: csiDriver.Name}, foundCSIDriver)
assert.NoError(t, err)
assert.Equal(t, csiDriver.Name, foundCSIDriver.Name)
})

t.Run("Update existing CSIDriver", func(t *testing.T) {
// fake client
client := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build()

updatedCSIDriver := csiDriver.DeepCopy()
updatedCSIDriver.Annotations = map[string]string{"key": "test-annotation"}

err := SyncCSIDriver(ctx, *updatedCSIDriver, client)
assert.NoError(t, err)

// check that the csidriver was updated
foundCSIDriver := &storagev1.CSIDriver{}
err = client.Get(ctx, types.NamespacedName{Name: csiDriver.Name}, foundCSIDriver)
assert.NoError(t, err)
assert.Equal(t, updatedCSIDriver.Annotations, foundCSIDriver.Annotations)
})

t.Run("Handle error on getting CSIDriver", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, _ client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return errors.New("get error")
},
}

err := SyncCSIDriver(ctx, csiDriver, client)
assert.Error(t, err)
assert.Equal(t, "get error", err.Error())
})

t.Run("Handle error on creating CSIDriver", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, key client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return apierrors.NewNotFound(storagev1.Resource("csidriver"), key.Name)
},
CreateFunc: func(_ context.Context, _ client.Object, _ ...client.CreateOption) error {
return errors.New("create error")
},
}

err := SyncCSIDriver(ctx, csiDriver, client)
assert.Error(t, err)
assert.Equal(t, "creating csidriver object: create error", err.Error())
})

t.Run("Handle error on updating CSIDriver", func(t *testing.T) {
client := &common.MockClient{
GetFunc: func(_ context.Context, _ client.ObjectKey, _ client.Object, _ ...client.GetOption) error {
return nil
},
UpdateFunc: func(_ context.Context, _ client.Object, _ ...client.UpdateOption) error {
return errors.New("update error")
},
}

err := SyncCSIDriver(ctx, csiDriver, client)
assert.Error(t, err)
assert.Equal(t, "updating csidriver object: update error", err.Error())
})
}
20 changes: 13 additions & 7 deletions pkg/resources/daemonset/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"context"

"github.com/dell/csm-operator/pkg/logger"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
appsv1 "k8s.io/client-go/applyconfigurations/apps/v1"
"k8s.io/client-go/kubernetes"
Expand All @@ -31,18 +32,23 @@ func SyncDaemonset(ctx context.Context, daemonset appsv1.DaemonSetApplyConfigura
daemonsets := k8sClient.AppsV1().DaemonSets(*daemonset.ObjectMetaApplyConfiguration.Namespace)

found, err := daemonsets.Get(ctx, *daemonset.ObjectMetaApplyConfiguration.Name, metav1.GetOptions{})
if err != nil {
log.Errorw("get SyncDaemonset error", "Error", err.Error())
}

opts := metav1.ApplyOptions{FieldManager: "application/apply-patch"}
if found == nil || found.Name == "" {
if err != nil && errors.IsNotFound(err) {
log.Infow("No existing DaemonSet", "Name:", daemonset.Name)
} else if err != nil {
log.Errorw("Get SyncDaemonSet error", "Error", err.Error())
return err
} else {
log.Infow("found daemonset", "image", found.Spec.Template.Spec.Containers[0].Image)
log.Infow("Found DaemonSet", "image", found.Spec.Template.Spec.Containers[0].Image)
}

opts := metav1.ApplyOptions{FieldManager: "application/apply-patch"}

// ensure Spec and Template are initialized
if daemonset.Spec.Template.Labels == nil {
daemonset.Spec.Template.Labels = make(map[string]string)
}
daemonset.Spec.Template.Labels["csm"] = csmName

_, err = daemonsets.Apply(ctx, &daemonset, opts)
if err != nil {
log.Errorw("Apply DaemonSet error", "set", err.Error())
Expand Down
Loading

0 comments on commit a51fbb3

Please sign in to comment.