Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ testbin/*

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.html

# Kubernetes Generated files - skip generated files, except for vendored files

Expand Down
5 changes: 2 additions & 3 deletions k8sutils/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St
logger.Error(err, "Unable to patch redis statefulset with comparison object")
return err
}
return updateStatefulSet(namespace, newStateful, recreateStateFulSet, cl)
return updateStatefulSet(cl, logger, namespace, newStateful, recreateStateFulSet)
}
logger.V(1).Info("Reconciliation Complete, no Changes required.")
return nil
Expand Down Expand Up @@ -698,8 +698,7 @@ func createStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace st
}

// updateStatefulSet is a method to update statefulset in Kubernetes
func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool, cl kubernetes.Interface) error {
logger := statefulSetLogger(namespace, stateful.Name)
func updateStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool) error {
_, err := cl.AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{})
if recreateStateFulSet {
sErr, ok := err.(*apierrors.StatusError)
Expand Down
125 changes: 125 additions & 0 deletions k8sutils/statefulset_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package k8sutils

import (
"context"
"path"
"testing"

Expand All @@ -10,7 +11,9 @@ import (
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
k8sClientFake "k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)
Expand Down Expand Up @@ -284,6 +287,128 @@ func Test_createStatefulSet(t *testing.T) {
}
}

func TestUpdateStatefulSet(t *testing.T) {
logger := logr.Discard()
tests := []struct {
name string
existingStsSpec appsv1.StatefulSetSpec
updatedStsSpec appsv1.StatefulSetSpec
recreateSts bool
stsPresent bool
expectErr error
}{
{
name: "Update StatefulSet without recreate in existing Statefulset",
existingStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(3)),
},
updatedStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(5)),
},
recreateSts: false,
stsPresent: true,
},
{
name: "Update StatefulSet with recreate in existing Statefulset",
existingStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(2)),
},
updatedStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(4)),
},
recreateSts: true,
stsPresent: true,
},
{
name: "Update StatefulSet without recreate StatefulSet is not present",
existingStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(2)),
},
updatedStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(4)),
},
recreateSts: false,
stsPresent: false,
expectErr: kerrors.NewNotFound(schema.GroupResource{Group: "apps", Resource: "statefulsets"}, "test-sts"),
},
{
name: "Update StatefulSet without recreate StatefulSet",
existingStsSpec: appsv1.StatefulSetSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"name": "redis",
},
},
},
},
updatedStsSpec: appsv1.StatefulSetSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"name": "redis-standalone",
},
},
},
},
recreateSts: false,
stsPresent: true,
},
{
name: "Update StatefulSet failed with Invalid Reason",
existingStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(2)),
},
updatedStsSpec: appsv1.StatefulSetSpec{
Replicas: ptr.To(int32(4)),
},
recreateSts: true,
stsPresent: false,
expectErr: kerrors.NewNotFound(schema.GroupResource{Group: "apps", Resource: "statefulsets"}, "test-sts"),
},
}

assert := assert.New(t)

for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
existingSts := appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-sts",
Namespace: "test-ns",
},
Spec: *test.existingStsSpec.DeepCopy(),
}
updatedSts := appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-sts",
Namespace: "test-ns",
},
Spec: *test.updatedStsSpec.DeepCopy(),
}
var client *k8sClientFake.Clientset
if test.stsPresent {
client = k8sClientFake.NewSimpleClientset(existingSts.DeepCopyObject())
} else {
client = k8sClientFake.NewSimpleClientset()
}
err := updateStatefulSet(client, logger, updatedSts.GetNamespace(), &updatedSts, test.recreateSts)
if test.expectErr != nil {
assert.Error(err, "Expected Error while updating Statefulset")
assert.Equal(test.expectErr, err)
} else {
assert.NoError(err, "Error while updating Statefulset")
}
if err == nil {
getUpdatedSts, err := client.AppsV1().StatefulSets(updatedSts.GetNamespace()).Get(context.TODO(), updatedSts.GetName(), metav1.GetOptions{})
assert.NoError(err, "Error getting Updted StatefulSet")
assert.NotEqual(getUpdatedSts.DeepCopy(), existingSts.DeepCopy(), "StatefulSet not updated")
}
})
}
}

func TestGenerateTLSEnvironmentVariables(t *testing.T) {
tlsConfig := &redisv1beta2.TLSConfig{
TLSConfig: common.TLSConfig{
Expand Down