1
16
17 package polymorphichelpers
18
19 import (
20 "reflect"
21 "testing"
22
23 appsv1 "k8s.io/api/apps/v1"
24 corev1 "k8s.io/api/core/v1"
25 apiequality "k8s.io/apimachinery/pkg/api/equality"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 "k8s.io/apimachinery/pkg/types"
30 "k8s.io/client-go/kubernetes/fake"
31 )
32
33 var rollbackTests = map[schema.GroupKind]reflect.Type{
34 {Group: "apps", Kind: "DaemonSet"}: reflect.TypeOf(&DaemonSetRollbacker{}),
35 {Group: "apps", Kind: "StatefulSet"}: reflect.TypeOf(&StatefulSetRollbacker{}),
36 {Group: "apps", Kind: "Deployment"}: reflect.TypeOf(&DeploymentRollbacker{}),
37 }
38
39 func TestRollbackerFor(t *testing.T) {
40 fakeClientset := &fake.Clientset{}
41
42 for kind, expectedType := range rollbackTests {
43 result, err := RollbackerFor(kind, fakeClientset)
44 if err != nil {
45 t.Fatalf("error getting Rollbacker for a %v: %v", kind.String(), err)
46 }
47
48 if reflect.TypeOf(result) != expectedType {
49 t.Fatalf("unexpected output type (%v was expected but got %v)", expectedType, reflect.TypeOf(result))
50 }
51 }
52 }
53
54 func TestGetDeploymentPatch(t *testing.T) {
55 patchType, patchBytes, err := getDeploymentPatch(&corev1.PodTemplateSpec{
56 Spec: corev1.PodSpec{
57 Containers: []corev1.Container{{Image: "foo"}}}}, map[string]string{"a": "true"})
58 if err != nil {
59 t.Error(err)
60 }
61 if patchType != types.JSONPatchType {
62 t.Errorf("expected strategic merge patch, got %v", patchType)
63 }
64 expectedPatch := `[` +
65 `{"op":"replace","path":"/spec/template","value":{"metadata":{"creationTimestamp":null},"spec":{"containers":[{"name":"","image":"foo","resources":{}}]}}},` +
66 `{"op":"replace","path":"/metadata/annotations","value":{"a":"true"}}` +
67 `]`
68 if string(patchBytes) != expectedPatch {
69 t.Errorf("expected:\n%s\ngot\n%s", expectedPatch, string(patchBytes))
70 }
71 }
72
73 func TestStatefulSetApplyRevision(t *testing.T) {
74 tests := []struct {
75 name string
76 source *appsv1.StatefulSet
77 expected *appsv1.StatefulSet
78 }{
79 {
80 "test_less",
81 &appsv1.StatefulSet{
82 Spec: appsv1.StatefulSetSpec{
83 Template: corev1.PodTemplateSpec{
84 ObjectMeta: metav1.ObjectMeta{
85 Annotations: map[string]string{"version": "v3"},
86 },
87 Spec: corev1.PodSpec{
88 InitContainers: []corev1.Container{{Name: "i0"}},
89 Containers: []corev1.Container{{Name: "c0"}},
90 Volumes: []corev1.Volume{{Name: "v0"}},
91 NodeSelector: map[string]string{"1dsa": "n0"},
92 },
93 },
94 },
95 },
96 &appsv1.StatefulSet{
97 Spec: appsv1.StatefulSetSpec{
98 Template: corev1.PodTemplateSpec{
99 Spec: corev1.PodSpec{
100 Containers: []corev1.Container{{Name: "c1"}},
101
102 InitContainers: []corev1.Container{},
103 },
104 },
105 },
106 },
107 },
108 {
109 "test_more",
110 &appsv1.StatefulSet{
111 Spec: appsv1.StatefulSetSpec{
112 Template: corev1.PodTemplateSpec{
113 Spec: corev1.PodSpec{
114 InitContainers: []corev1.Container{{Name: "i0"}},
115 },
116 },
117 },
118 },
119 &appsv1.StatefulSet{
120 Spec: appsv1.StatefulSetSpec{
121 Template: corev1.PodTemplateSpec{
122 ObjectMeta: metav1.ObjectMeta{
123 Annotations: map[string]string{"version": "v3"},
124 },
125 Spec: corev1.PodSpec{
126 InitContainers: []corev1.Container{{Name: "i1"}},
127 Containers: []corev1.Container{{Name: "c1"}},
128 Volumes: []corev1.Volume{{Name: "v1"}},
129 },
130 },
131 },
132 },
133 },
134 {
135 "test_equal",
136 &appsv1.StatefulSet{
137 Spec: appsv1.StatefulSetSpec{
138 Template: corev1.PodTemplateSpec{
139 ObjectMeta: metav1.ObjectMeta{
140 Annotations: map[string]string{"version": "v3"},
141 },
142 Spec: corev1.PodSpec{
143 Containers: []corev1.Container{{Name: "c1"}},
144 InitContainers: []corev1.Container{{Name: "i0"}},
145 Volumes: []corev1.Volume{{Name: "v0"}},
146 },
147 },
148 },
149 },
150 &appsv1.StatefulSet{
151 Spec: appsv1.StatefulSetSpec{
152 Template: corev1.PodTemplateSpec{
153 ObjectMeta: metav1.ObjectMeta{
154 Annotations: map[string]string{"version": "v2"},
155 },
156 Spec: corev1.PodSpec{
157 InitContainers: []corev1.Container{{Name: "i1"}},
158 Containers: []corev1.Container{{Name: "c1"}},
159 Volumes: []corev1.Volume{{Name: "v1"}},
160 },
161 },
162 },
163 },
164 },
165 }
166
167 for _, tt := range tests {
168 t.Run(tt.name, func(t *testing.T) {
169 patch, err := getStatefulSetPatch(tt.expected)
170 if err != nil {
171 t.Errorf("getStatefulSetPatch failed : %v", err)
172 }
173 cr := &appsv1.ControllerRevision{
174 Data: runtime.RawExtension{
175 Raw: patch,
176 },
177 }
178 tt.source, err = applyRevision(tt.source, cr)
179 if err != nil {
180 t.Errorf("apply revision failed : %v", err)
181 }
182
183 if !apiequality.Semantic.DeepEqual(tt.source.Spec, tt.expected.Spec) {
184 t.Errorf("expected out [%v] but get [%v]", tt.expected.Spec, tt.source.Spec)
185 }
186 })
187 }
188 }
189
View as plain text