@@ -33,7 +33,7 @@ import (
33
33
"sigs.k8s.io/e2e-framework/pkg/envconf"
34
34
"sigs.k8s.io/e2e-framework/pkg/features"
35
35
36
- ecv1alpha1 "go.etcd.io/etcd-operator/api/v1alpha1"
36
+ ec_v1alpha1 "go.etcd.io/etcd-operator/api/v1alpha1"
37
37
)
38
38
39
39
var etcdVersion = os .Getenv ("ETCD_VERSION" )
@@ -49,7 +49,7 @@ func TestInvalidClusterSize(t *testing.T) {
49
49
"with-negative-members" : - 1 ,
50
50
}
51
51
52
- etcdClusterSpec := & ecv1alpha1 .EtcdCluster {
52
+ etcdClusterSpec := & ec_v1alpha1 .EtcdCluster {
53
53
TypeMeta : metav1.TypeMeta {
54
54
APIVersion : "operator.etcd.io/v1alpha1" ,
55
55
Kind : "EtcdCluster" ,
@@ -58,7 +58,7 @@ func TestInvalidClusterSize(t *testing.T) {
58
58
Name : etcdClusterName ,
59
59
Namespace : namespace ,
60
60
},
61
- Spec : ecv1alpha1 .EtcdClusterSpec {
61
+ Spec : ec_v1alpha1 .EtcdClusterSpec {
62
62
Size : 0 ,
63
63
Version : etcdVersion ,
64
64
},
@@ -82,7 +82,7 @@ func TestInvalidClusterSize(t *testing.T) {
82
82
feature .Assess (fmt .Sprintf ("etcdCluster %s should not be created when etcdCluster.Spec.Size is %d" , name , size ),
83
83
func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
84
84
85
- var etcdCluster ecv1alpha1 .EtcdCluster
85
+ var etcdCluster ec_v1alpha1 .EtcdCluster
86
86
err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster )
87
87
if ! errors .IsNotFound (err ) {
88
88
t .Fatalf ("found unexpected etcdCluster %s with size %d. Got: %v" , name , size , err )
@@ -125,3 +125,173 @@ func TestClusterHealthy(t *testing.T) {
125
125
// 'testEnv' is the env.Environment you set up in TestMain
126
126
_ = testEnv .Test (t , feature .Feature ())
127
127
}
128
+
129
+ func TestScaleDownFrom3To1 (t * testing.T ) {
130
+ feature := features .New ("scale-down" )
131
+ etcdClusterName := "etcd-scale-down"
132
+
133
+ feature .Setup (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
134
+ createEtcdCluster (ctx , t , c , etcdClusterName , 3 )
135
+ waitForStsReady (ctx , t , c , etcdClusterName , 3 )
136
+ return ctx
137
+ })
138
+
139
+ feature .Assess ("scale down to 1" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
140
+ var etcdCluster ec_v1alpha1.EtcdCluster
141
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err != nil {
142
+ t .Fatalf ("Failed to get EtcdCluster: %v" , err )
143
+ }
144
+
145
+ etcdCluster .Spec .Size = 1
146
+ if err := c .Client ().Resources ().Update (ctx , & etcdCluster ); err != nil {
147
+ t .Fatalf ("Failed to update EtcdCluster: %v" , err )
148
+ }
149
+
150
+ waitForStsReady (ctx , t , c , etcdClusterName , 1 )
151
+ return ctx
152
+ })
153
+
154
+ feature .Assess ("verify member list" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
155
+ podName := fmt .Sprintf ("%s-0" , etcdClusterName )
156
+ stdout , stderr , err := execInPod (t , c , podName , namespace , []string {"etcdctl" , "member" , "list" })
157
+ if err != nil {
158
+ t .Fatalf ("Failed to exec in pod: %v, stderr: %s" , err , stderr )
159
+ }
160
+
161
+ if len (strings .Split (strings .TrimSpace (stdout ), "\n " )) != 1 {
162
+ t .Errorf ("Expected to find 1 member in member list, but got: %s" , stdout )
163
+ }
164
+ return ctx
165
+ })
166
+
167
+ feature .Teardown (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
168
+ var etcdCluster ec_v1alpha1.EtcdCluster
169
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err == nil {
170
+ if err := c .Client ().Resources ().Delete (ctx , & etcdCluster ); err != nil {
171
+ t .Logf ("Failed to delete EtcdCluster: %v" , err )
172
+ }
173
+ }
174
+ return ctx
175
+ })
176
+
177
+ _ = testEnv .Test (t , feature .Feature ())
178
+ }
179
+
180
+ func TestScaleUpFrom1To3 (t * testing.T ) {
181
+ feature := features .New ("scale-up" )
182
+ etcdClusterName := "etcd-scale-up"
183
+
184
+ feature .Setup (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
185
+ createEtcdCluster (ctx , t , c , etcdClusterName , 1 )
186
+ waitForStsReady (ctx , t , c , etcdClusterName , 1 )
187
+ return ctx
188
+ })
189
+
190
+ feature .Assess ("scale up to 3" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
191
+ var etcdCluster ec_v1alpha1.EtcdCluster
192
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err != nil {
193
+ t .Fatalf ("Failed to get EtcdCluster: %v" , err )
194
+ }
195
+
196
+ etcdCluster .Spec .Size = 3
197
+ if err := c .Client ().Resources ().Update (ctx , & etcdCluster ); err != nil {
198
+ t .Fatalf ("Failed to update EtcdCluster: %v" , err )
199
+ }
200
+
201
+ waitForStsReady (ctx , t , c , etcdClusterName , 3 )
202
+ return ctx
203
+ })
204
+
205
+ feature .Assess ("verify member list" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
206
+ podName := fmt .Sprintf ("%s-0" , etcdClusterName )
207
+ stdout , stderr , err := execInPod (t , c , podName , namespace , []string {"etcdctl" , "member" , "list" })
208
+ if err != nil {
209
+ t .Fatalf ("Failed to exec in pod: %v, stderr: %s" , err , stderr )
210
+ }
211
+
212
+ if len (strings .Split (strings .TrimSpace (stdout ), "\n " )) != 3 {
213
+ t .Errorf ("Expected to find 3 members in member list, but got: %s" , stdout )
214
+ }
215
+ return ctx
216
+ })
217
+
218
+ feature .Teardown (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
219
+ var etcdCluster ec_v1alpha1.EtcdCluster
220
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err == nil {
221
+ if err := c .Client ().Resources ().Delete (ctx , & etcdCluster ); err != nil {
222
+ t .Logf ("Failed to delete EtcdCluster: %v" , err )
223
+ }
224
+ }
225
+ return ctx
226
+ })
227
+
228
+ _ = testEnv .Test (t , feature .Feature ())
229
+ }
230
+
231
+ func TestPromoteReadyLearner (t * testing.T ) {
232
+ feature := features .New ("promote-learner" )
233
+ etcdClusterName := "etcd-promote-learner"
234
+
235
+ feature .Setup (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
236
+ createEtcdCluster (ctx , t , c , etcdClusterName , 2 )
237
+ waitForStsReady (ctx , t , c , etcdClusterName , 2 )
238
+ // Manually add a third member as a learner
239
+ podName := fmt .Sprintf ("%s-0" , etcdClusterName )
240
+ _ , stderr , err := execInPod (t , c , podName , namespace , []string {"etcdctl" , "member" , "add" , "etcd-promote-learner-2" , "--peer-urls=http://etcd-promote-learner-2.etcd-promote-learner.etcd-operator-system.svc.cluster.local:2380" , "--learner" })
241
+ if err != nil {
242
+ t .Fatalf ("Failed to add learner: %v, stderr: %s" , err , stderr )
243
+ }
244
+ return ctx
245
+ })
246
+
247
+ feature .Assess ("promote learner" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
248
+ var etcdCluster ec_v1alpha1.EtcdCluster
249
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err != nil {
250
+ t .Fatalf ("Failed to get EtcdCluster: %v" , err )
251
+ }
252
+
253
+ etcdCluster .Spec .Size = 3
254
+ if err := c .Client ().Resources ().Update (ctx , & etcdCluster ); err != nil {
255
+ t .Fatalf ("Failed to update EtcdCluster: %v" , err )
256
+ }
257
+
258
+ // Wait for the learner to be promoted.
259
+ wait .For (func (ctx context.Context ) (done bool , err error ) {
260
+ podName := fmt .Sprintf ("%s-0" , etcdClusterName )
261
+ command := []string {"etcdctl" , "member" , "list" , "-w" , "table" }
262
+ stdout , _ , err := execInPod (t , c , podName , namespace , command )
263
+ if err != nil {
264
+ return false , nil
265
+ }
266
+ return ! strings .Contains (stdout , "true" ), nil
267
+ }, wait .WithTimeout (2 * time .Minute ), wait .WithInterval (5 * time .Second ))
268
+
269
+ return ctx
270
+ })
271
+
272
+ feature .Assess ("verify member list" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
273
+ podName := fmt .Sprintf ("%s-0" , etcdClusterName )
274
+ command := []string {"etcdctl" , "member" , "list" , "-w" , "table" }
275
+ stdout , stderr , err := execInPod (t , c , podName , namespace , command )
276
+ if err != nil {
277
+ t .Fatalf ("Failed to exec in pod: %v, stderr: %s" , err , stderr )
278
+ }
279
+
280
+ if strings .Contains (stdout , "true" ) {
281
+ t .Errorf ("Expected all members not to be learners, but found a learner. Member list:\n %s" , stdout )
282
+ }
283
+ return ctx
284
+ })
285
+
286
+ feature .Teardown (func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
287
+ var etcdCluster ec_v1alpha1.EtcdCluster
288
+ if err := c .Client ().Resources ().Get (ctx , etcdClusterName , namespace , & etcdCluster ); err == nil {
289
+ if err := c .Client ().Resources ().Delete (ctx , & etcdCluster ); err != nil {
290
+ t .Logf ("Failed to delete EtcdCluster: %v" , err )
291
+ }
292
+ }
293
+ return ctx
294
+ })
295
+
296
+ _ = testEnv .Test (t , feature .Feature ())
297
+ }
0 commit comments