1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package httpchaos
17
18 import (
19 "context"
20 "io"
21 "time"
22
23 . "github.com/onsi/ginkgo/v2"
24 corev1 "k8s.io/api/core/v1"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/types"
27 "k8s.io/apimachinery/pkg/util/wait"
28 "k8s.io/klog/v2"
29 "k8s.io/kubernetes/test/e2e/framework"
30 "sigs.k8s.io/controller-runtime/pkg/client"
31
32 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
33 "github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/util"
34 )
35
36 func TestcaseHttpReplaceThenRecover(
37 ns string,
38 cli client.Client,
39 c HTTPE2EClient,
40 port uint16,
41 ) {
42 ctx, cancel := context.WithCancel(context.Background())
43 defer cancel()
44
45 By("waiting on e2e helper ready")
46 err := util.WaitHTTPE2EHelperReady(*c.C, c.IP, port)
47 framework.ExpectNoError(err, "wait e2e helper ready error")
48
49 secret := "Bar"
50
51 By("waiting for assertion normal behaviour")
52 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
53 resp, err := getPodHttp(c, port, secret, "")
54 if err != nil {
55 return false, err
56 }
57 defer resp.Body.Close()
58
59 s := resp.Header.Get(SECRET)
60 b, err := io.ReadAll(resp.Body)
61 if err != nil {
62 return false, err
63 }
64
65 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
66
67 if s == secret {
68 return true, nil
69 }
70 return false, nil
71 })
72 framework.ExpectNoError(err, "helper server doesn't work as expected")
73 By("deploy helper server successfully")
74
75 By("create http replace chaos CRD objects")
76 replaceSecret := "Foo!"
77
78 httpChaos := &v1alpha1.HTTPChaos{
79 ObjectMeta: metav1.ObjectMeta{
80 Name: "http-chaos",
81 Namespace: ns,
82 },
83 Spec: v1alpha1.HTTPChaosSpec{
84 PodSelector: v1alpha1.PodSelector{
85 Selector: v1alpha1.PodSelectorSpec{
86 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
87 Namespaces: []string{ns},
88 LabelSelectors: map[string]string{"app": "http"},
89 },
90 },
91 Mode: v1alpha1.OneMode,
92 },
93 Port: 8080,
94 Target: "Request",
95 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
96 Replace: &v1alpha1.PodHttpChaosReplaceActions{
97 Headers: map[string]string{
98 SECRET: replaceSecret,
99 },
100 },
101 },
102 },
103 }
104 err = cli.Create(ctx, httpChaos)
105 framework.ExpectNoError(err, "create http chaos error")
106
107 By("waiting for assertion HTTP replace")
108 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
109 resp, err := getPodHttp(c, port, secret, "")
110 if err != nil {
111 return false, err
112 }
113 defer resp.Body.Close()
114
115 s := resp.Header.Get(SECRET)
116 b, err := io.ReadAll(resp.Body)
117 if err != nil {
118 return false, err
119 }
120
121 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
122
123 if s == replaceSecret {
124 return true, nil
125 }
126 return false, nil
127 })
128 framework.ExpectNoError(err, "http chaos doesn't work as expected")
129 By("apply http chaos successfully")
130
131 By("delete chaos CRD objects")
132
133 err = cli.Delete(ctx, httpChaos)
134 framework.ExpectNoError(err, "failed to delete http chaos")
135
136 By("waiting for assertion recovering")
137 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
138 resp, err := getPodHttp(c, port, secret, "")
139 if err != nil {
140 return false, err
141 }
142 defer resp.Body.Close()
143
144 s := resp.Header.Get(SECRET)
145 b, err := io.ReadAll(resp.Body)
146 if err != nil {
147 return false, err
148 }
149
150 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
151
152 if s == secret {
153 return true, nil
154 }
155 return false, nil
156 })
157 framework.ExpectNoError(err, "fail to recover http chaos")
158 }
159
160 func TestcaseHttpReplacePauseAndUnPause(
161 ns string,
162 cli client.Client,
163 c HTTPE2EClient,
164 port uint16,
165 ) {
166 ctx, cancel := context.WithCancel(context.Background())
167 defer cancel()
168
169 By("waiting on e2e helper ready")
170 err := util.WaitHTTPE2EHelperReady(*c.C, c.IP, port)
171 framework.ExpectNoError(err, "wait e2e helper ready error")
172
173 secret := "Bar"
174
175 By("waiting for assertion normal behaviour")
176 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
177 resp, err := getPodHttp(c, port, secret, "")
178 if err != nil {
179 return false, err
180 }
181 defer resp.Body.Close()
182
183 s := resp.Header.Get(SECRET)
184 b, err := io.ReadAll(resp.Body)
185 if err != nil {
186 return false, err
187 }
188
189 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
190
191 if s == secret {
192 return true, nil
193 }
194 return false, nil
195 })
196 framework.ExpectNoError(err, "helper server doesn't work as expected")
197 By("deploy helper server successfully")
198
199 By("create http replace chaos CRD objects")
200 replaceSecret := "Foo!"
201
202 httpChaos := &v1alpha1.HTTPChaos{
203 ObjectMeta: metav1.ObjectMeta{
204 Name: "http-chaos",
205 Namespace: ns,
206 },
207 Spec: v1alpha1.HTTPChaosSpec{
208 PodSelector: v1alpha1.PodSelector{
209 Selector: v1alpha1.PodSelectorSpec{
210 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
211 Namespaces: []string{ns},
212 LabelSelectors: map[string]string{"app": "http"},
213 },
214 },
215 Mode: v1alpha1.OneMode,
216 },
217 Port: 8080,
218 Target: "Request",
219 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
220 Replace: &v1alpha1.PodHttpChaosReplaceActions{
221 Headers: map[string]string{
222 SECRET: replaceSecret,
223 },
224 },
225 },
226 },
227 }
228 err = cli.Create(ctx, httpChaos)
229 framework.ExpectNoError(err, "create http chaos error")
230
231 chaosKey := types.NamespacedName{
232 Namespace: ns,
233 Name: "http-chaos",
234 }
235
236 By("waiting for assertion http chaos")
237 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
238 chaos := &v1alpha1.HTTPChaos{}
239 err = cli.Get(ctx, chaosKey, chaos)
240 framework.ExpectNoError(err, "get http chaos error")
241
242 for _, c := range chaos.GetStatus().Conditions {
243 if c.Type == v1alpha1.ConditionAllInjected {
244 if c.Status != corev1.ConditionTrue {
245 return false, nil
246 }
247 } else if c.Type == v1alpha1.ConditionSelected {
248 if c.Status != corev1.ConditionTrue {
249 return false, nil
250 }
251 }
252 }
253
254 resp, err := getPodHttp(c, port, secret, "")
255 if err != nil {
256 return false, err
257 }
258 defer resp.Body.Close()
259
260 s := resp.Header.Get(SECRET)
261 b, err := io.ReadAll(resp.Body)
262 if err != nil {
263 return false, err
264 }
265
266 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
267
268 if s == replaceSecret {
269 return true, nil
270 }
271 return false, nil
272 })
273 framework.ExpectNoError(err, "http chaos doesn't work as expected")
274
275 By("pause http replace chaos experiment")
276
277 err = util.PauseChaos(ctx, cli, httpChaos)
278 framework.ExpectNoError(err, "pause chaos error")
279
280 By("waiting for assertion about pause")
281 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
282 chaos := &v1alpha1.HTTPChaos{}
283 err = cli.Get(ctx, chaosKey, chaos)
284 framework.ExpectNoError(err, "get http chaos error")
285
286 for _, c := range chaos.GetStatus().Conditions {
287 if c.Type == v1alpha1.ConditionAllRecovered {
288 if c.Status != corev1.ConditionTrue {
289 return false, nil
290 }
291 } else if c.Type == v1alpha1.ConditionSelected {
292 if c.Status != corev1.ConditionTrue {
293 return false, nil
294 }
295 }
296 }
297
298 return true, err
299 })
300 framework.ExpectNoError(err, "check paused chaos failed")
301
302
303 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
304 resp, err := getPodHttp(c, port, secret, "")
305 if err != nil {
306 return false, err
307 }
308 defer resp.Body.Close()
309
310 s := resp.Header.Get(SECRET)
311 b, err := io.ReadAll(resp.Body)
312 if err != nil {
313 return false, err
314 }
315
316 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
317
318 if s == secret {
319 return true, nil
320 }
321 return false, nil
322 })
323 framework.ExpectNoError(err, "fail to recover http chaos")
324 By("resume http replace chaos experiment")
325
326 err = util.UnPauseChaos(ctx, cli, httpChaos)
327 framework.ExpectNoError(err, "resume chaos error")
328
329 By("assert that http replace is effective again")
330 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
331 chaos := &v1alpha1.HTTPChaos{}
332 err = cli.Get(ctx, chaosKey, chaos)
333 framework.ExpectNoError(err, "get http chaos error")
334
335 for _, c := range chaos.GetStatus().Conditions {
336 if c.Type == v1alpha1.ConditionAllInjected {
337 if c.Status != corev1.ConditionTrue {
338 return false, nil
339 }
340 } else if c.Type == v1alpha1.ConditionSelected {
341 if c.Status != corev1.ConditionTrue {
342 return false, nil
343 }
344 }
345 }
346
347 return true, err
348 })
349 framework.ExpectNoError(err, "check resumed chaos failed")
350
351 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
352 resp, err := getPodHttp(c, port, secret, "")
353 if err != nil {
354 return false, err
355 }
356 defer resp.Body.Close()
357
358 s := resp.Header.Get(SECRET)
359 b, err := io.ReadAll(resp.Body)
360 if err != nil {
361 return false, err
362 }
363
364 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
365
366 if s == replaceSecret {
367 return true, nil
368 }
369 return false, nil
370 })
371 framework.ExpectNoError(err, "HTTP chaos doesn't work as expected")
372
373 By("cleanup")
374
375 cli.Delete(ctx, httpChaos)
376 }
377
378 func TestcaseHttpReplaceBodyThenRecover(
379 ns string,
380 cli client.Client,
381 c HTTPE2EClient,
382 port uint16,
383 ) {
384 ctx, cancel := context.WithCancel(context.Background())
385 defer cancel()
386
387 By("waiting on e2e helper ready")
388 err := util.WaitHTTPE2EHelperReady(*c.C, c.IP, port)
389 framework.ExpectNoError(err, "wait e2e helper ready error")
390
391 body := "Hello World"
392 secret := "Bar"
393
394 By("waiting for assertion normal behaviour")
395 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
396 resp, err := getPodHttp(c, port, secret, body)
397 if err != nil {
398 return false, err
399 }
400 defer resp.Body.Close()
401
402 s := resp.Header.Get(SECRET)
403 b, err := io.ReadAll(resp.Body)
404 if err != nil {
405 return false, err
406 }
407
408 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
409
410 if s == secret && string(b) == body {
411 return true, nil
412 }
413 return false, nil
414 })
415 framework.ExpectNoError(err, "helper server doesn't work as expected")
416 By("deploy helper server successfully")
417
418 By("create http replace chaos CRD objects")
419 replacebody := "Hello Chaos Mesh"
420 replaceSecret := "Foo!"
421
422 httpChaos := &v1alpha1.HTTPChaos{
423 ObjectMeta: metav1.ObjectMeta{
424 Name: "http-chaos",
425 Namespace: ns,
426 },
427 Spec: v1alpha1.HTTPChaosSpec{
428 PodSelector: v1alpha1.PodSelector{
429 Selector: v1alpha1.PodSelectorSpec{
430 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
431 Namespaces: []string{ns},
432 LabelSelectors: map[string]string{"app": "http"},
433 },
434 },
435 Mode: v1alpha1.OneMode,
436 },
437 Port: 8080,
438 Target: "Request",
439 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
440 Replace: &v1alpha1.PodHttpChaosReplaceActions{
441 Headers: map[string]string{
442 SECRET: replaceSecret,
443 },
444 Body: []byte(replacebody),
445 },
446 },
447 },
448 }
449 err = cli.Create(ctx, httpChaos)
450 framework.ExpectNoError(err, "create http chaos error")
451
452 By("waiting for assertion HTTP replace")
453 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
454 resp, err := getPodHttp(c, port, secret, body)
455 if err != nil {
456 return false, err
457 }
458 defer resp.Body.Close()
459
460 s := resp.Header.Get(SECRET)
461 b, err := io.ReadAll(resp.Body)
462 if err != nil {
463 return false, err
464 }
465
466 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
467
468 if s == replaceSecret && string(b) == replacebody {
469 return true, nil
470 }
471 return false, nil
472 })
473 framework.ExpectNoError(err, "http chaos doesn't work as expected")
474 By("apply http chaos successfully")
475
476 By("delete chaos CRD objects")
477
478 err = cli.Delete(ctx, httpChaos)
479 framework.ExpectNoError(err, "failed to delete http chaos")
480
481 By("waiting for assertion recovering")
482 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
483 resp, err := getPodHttp(c, port, secret, body)
484 if err != nil {
485 return false, err
486 }
487 defer resp.Body.Close()
488
489 s := resp.Header.Get(SECRET)
490 b, err := io.ReadAll(resp.Body)
491 if err != nil {
492 return false, err
493 }
494
495 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
496
497 if s == secret && string(b) == body {
498 return true, nil
499 }
500 return false, nil
501 })
502 framework.ExpectNoError(err, "fail to recover http chaos")
503 }
504
505 func TestcaseHttpReplaceBodyPauseAndUnPause(
506 ns string,
507 cli client.Client,
508 c HTTPE2EClient,
509 port uint16,
510 ) {
511 ctx, cancel := context.WithCancel(context.Background())
512 defer cancel()
513
514 By("waiting on e2e helper ready")
515 err := util.WaitHTTPE2EHelperReady(*c.C, c.IP, port)
516 framework.ExpectNoError(err, "wait e2e helper ready error")
517
518 body := "Hello World"
519 secret := "Bar"
520
521 By("waiting for assertion normal behaviour")
522 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
523 resp, err := getPodHttp(c, port, secret, body)
524 if err != nil {
525 return false, err
526 }
527 defer resp.Body.Close()
528
529 s := resp.Header.Get(SECRET)
530 b, err := io.ReadAll(resp.Body)
531 if err != nil {
532 return false, err
533 }
534
535 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
536
537 if s == secret && string(b) == body {
538 return true, nil
539 }
540 return false, nil
541 })
542 framework.ExpectNoError(err, "helper server doesn't work as expected")
543 By("deploy helper server successfully")
544
545 By("create http replace chaos CRD objects")
546 replacebody := "Hello Chaos Mesh"
547 replaceSecret := "Foo!"
548
549 httpChaos := &v1alpha1.HTTPChaos{
550 ObjectMeta: metav1.ObjectMeta{
551 Name: "http-chaos",
552 Namespace: ns,
553 },
554 Spec: v1alpha1.HTTPChaosSpec{
555 PodSelector: v1alpha1.PodSelector{
556 Selector: v1alpha1.PodSelectorSpec{
557 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
558 Namespaces: []string{ns},
559 LabelSelectors: map[string]string{"app": "http"},
560 },
561 },
562 Mode: v1alpha1.OneMode,
563 },
564 Port: 8080,
565 Target: "Request",
566 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
567 Replace: &v1alpha1.PodHttpChaosReplaceActions{
568 Headers: map[string]string{
569 SECRET: replaceSecret,
570 },
571 Body: []byte(replacebody),
572 },
573 },
574 },
575 }
576 err = cli.Create(ctx, httpChaos)
577 framework.ExpectNoError(err, "create http chaos error")
578
579 chaosKey := types.NamespacedName{
580 Namespace: ns,
581 Name: "http-chaos",
582 }
583
584 By("waiting for assertion http chaos")
585 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
586 chaos := &v1alpha1.HTTPChaos{}
587 err = cli.Get(ctx, chaosKey, chaos)
588 framework.ExpectNoError(err, "get http chaos error")
589
590 for _, c := range chaos.GetStatus().Conditions {
591 if c.Type == v1alpha1.ConditionAllInjected {
592 if c.Status != corev1.ConditionTrue {
593 return false, nil
594 }
595 } else if c.Type == v1alpha1.ConditionSelected {
596 if c.Status != corev1.ConditionTrue {
597 return false, nil
598 }
599 }
600 }
601
602 resp, err := getPodHttp(c, port, secret, body)
603 if err != nil {
604 return false, err
605 }
606 defer resp.Body.Close()
607
608 s := resp.Header.Get(SECRET)
609 b, err := io.ReadAll(resp.Body)
610 if err != nil {
611 return false, err
612 }
613
614 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
615
616 if s == replaceSecret && string(b) == replacebody {
617 return true, nil
618 }
619 return false, nil
620 })
621 framework.ExpectNoError(err, "http chaos doesn't work as expected")
622
623 By("pause http replace chaos experiment")
624
625 err = util.PauseChaos(ctx, cli, httpChaos)
626 framework.ExpectNoError(err, "pause chaos error")
627
628 By("waiting for assertion about pause")
629 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
630 chaos := &v1alpha1.HTTPChaos{}
631 err = cli.Get(ctx, chaosKey, chaos)
632 framework.ExpectNoError(err, "get http chaos error")
633
634 for _, c := range chaos.GetStatus().Conditions {
635 if c.Type == v1alpha1.ConditionAllRecovered {
636 if c.Status != corev1.ConditionTrue {
637 return false, nil
638 }
639 } else if c.Type == v1alpha1.ConditionSelected {
640 if c.Status != corev1.ConditionTrue {
641 return false, nil
642 }
643 }
644 }
645
646 return true, err
647 })
648 framework.ExpectNoError(err, "check paused chaos failed")
649
650
651 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
652 resp, err := getPodHttp(c, port, secret, body)
653 if err != nil {
654 return false, err
655 }
656 defer resp.Body.Close()
657
658 s := resp.Header.Get(SECRET)
659 b, err := io.ReadAll(resp.Body)
660 if err != nil {
661 return false, err
662 }
663
664 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
665
666 if s == secret && string(b) == body {
667 return true, nil
668 }
669 return false, nil
670 })
671 framework.ExpectNoError(err, "fail to recover http chaos")
672 By("resume http replace chaos experiment")
673
674 err = util.UnPauseChaos(ctx, cli, httpChaos)
675 framework.ExpectNoError(err, "resume chaos error")
676
677 By("assert that http replace is effective again")
678 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
679 chaos := &v1alpha1.HTTPChaos{}
680 err = cli.Get(ctx, chaosKey, chaos)
681 framework.ExpectNoError(err, "get http chaos error")
682
683 for _, c := range chaos.GetStatus().Conditions {
684 if c.Type == v1alpha1.ConditionAllInjected {
685 if c.Status != corev1.ConditionTrue {
686 return false, nil
687 }
688 } else if c.Type == v1alpha1.ConditionSelected {
689 if c.Status != corev1.ConditionTrue {
690 return false, nil
691 }
692 }
693 }
694
695 return true, err
696 })
697 framework.ExpectNoError(err, "check resumed chaos failed")
698
699 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
700 resp, err := getPodHttp(c, port, secret, body)
701 if err != nil {
702 return false, err
703 }
704 defer resp.Body.Close()
705
706 s := resp.Header.Get(SECRET)
707 b, err := io.ReadAll(resp.Body)
708 if err != nil {
709 return false, err
710 }
711
712 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
713
714 if s == replaceSecret && string(b) == replacebody {
715 return true, nil
716 }
717 return false, nil
718 })
719 framework.ExpectNoError(err, "HTTP chaos doesn't work as expected")
720
721 By("cleanup")
722
723 cli.Delete(ctx, httpChaos)
724 }
725