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/ioutil"
21 "net/http"
22 "time"
23
24 . "github.com/onsi/ginkgo"
25 corev1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/types"
28 "k8s.io/apimachinery/pkg/util/wait"
29 "k8s.io/klog/v2"
30 "k8s.io/kubernetes/test/e2e/framework"
31 "sigs.k8s.io/controller-runtime/pkg/client"
32
33 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
34 "github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/util"
35 )
36
37 func TestcaseHttpReplaceThenRecover(
38 ns string,
39 cli client.Client,
40 c http.Client,
41 port uint16,
42 ) {
43 ctx, cancel := context.WithCancel(context.Background())
44 defer cancel()
45
46 By("waiting on e2e helper ready")
47 err := util.WaitE2EHelperReady(c, port)
48 framework.ExpectNoError(err, "wait e2e helper ready error")
49
50 body := "Hello World"
51 secret := "Bar"
52
53 By("waiting for assertion normal behaviour")
54 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
55 resp, err := getPodHttp(c, port, secret, body)
56 if err != nil {
57 return false, err
58 }
59 defer resp.Body.Close()
60
61 s := resp.Header.Get(SECRET)
62 b, err := ioutil.ReadAll(resp.Body)
63 if err != nil {
64 return false, err
65 }
66
67 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
68
69 if s == secret && string(b) == body {
70 return true, nil
71 }
72 return false, nil
73 })
74 framework.ExpectNoError(err, "helper server doesn't work as expected")
75 By("deploy helper server successfully")
76
77 By("create http replace chaos CRD objects")
78 replacebody := "Hello Chaos Mesh"
79 replaceSecret := "Foo!"
80
81 httpChaos := &v1alpha1.HTTPChaos{
82 ObjectMeta: metav1.ObjectMeta{
83 Name: "http-chaos",
84 Namespace: ns,
85 },
86 Spec: v1alpha1.HTTPChaosSpec{
87 PodSelector: v1alpha1.PodSelector{
88 Selector: v1alpha1.PodSelectorSpec{
89 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
90 Namespaces: []string{ns},
91 LabelSelectors: map[string]string{"app": "http"},
92 },
93 },
94 Mode: v1alpha1.OneMode,
95 },
96 Port: 8080,
97 Target: "Request",
98 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
99 Replace: &v1alpha1.PodHttpChaosReplaceActions{
100 Headers: map[string]string{
101 SECRET: replaceSecret,
102 },
103 Body: []byte(replacebody),
104 },
105 },
106 },
107 }
108 err = cli.Create(ctx, httpChaos)
109 framework.ExpectNoError(err, "create http chaos error")
110
111 By("waiting for assertion HTTP replace")
112 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
113 resp, err := getPodHttp(c, port, secret, body)
114 if err != nil {
115 return false, err
116 }
117 defer resp.Body.Close()
118
119 s := resp.Header.Get(SECRET)
120 b, err := ioutil.ReadAll(resp.Body)
121 if err != nil {
122 return false, err
123 }
124
125 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
126
127 if s == replaceSecret && string(b) == replacebody {
128 return true, nil
129 }
130 return false, nil
131 })
132 framework.ExpectNoError(err, "http chaos doesn't work as expected")
133 By("apply http chaos successfully")
134
135 By("delete chaos CRD objects")
136
137 err = cli.Delete(ctx, httpChaos)
138 framework.ExpectNoError(err, "failed to delete http chaos")
139
140 By("waiting for assertion recovering")
141 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
142 resp, err := getPodHttp(c, port, secret, body)
143 if err != nil {
144 return false, err
145 }
146 defer resp.Body.Close()
147
148 s := resp.Header.Get(SECRET)
149 b, err := ioutil.ReadAll(resp.Body)
150 if err != nil {
151 return false, err
152 }
153
154 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
155
156 if s == secret && string(b) == body {
157 return true, nil
158 }
159 return false, nil
160 })
161 framework.ExpectNoError(err, "fail to recover http chaos")
162 }
163
164 func TestcaseHttpReplacePauseAndUnPause(
165 ns string,
166 cli client.Client,
167 c http.Client,
168 port uint16,
169 ) {
170 ctx, cancel := context.WithCancel(context.Background())
171 defer cancel()
172
173 By("waiting on e2e helper ready")
174 err := util.WaitE2EHelperReady(c, port)
175 framework.ExpectNoError(err, "wait e2e helper ready error")
176
177 body := "Hello World"
178 secret := "Bar"
179
180 By("waiting for assertion normal behaviour")
181 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
182 resp, err := getPodHttp(c, port, secret, body)
183 if err != nil {
184 return false, err
185 }
186 defer resp.Body.Close()
187
188 s := resp.Header.Get(SECRET)
189 b, err := ioutil.ReadAll(resp.Body)
190 if err != nil {
191 return false, err
192 }
193
194 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
195
196 if s == secret && string(b) == body {
197 return true, nil
198 }
199 return false, nil
200 })
201 framework.ExpectNoError(err, "helper server doesn't work as expected")
202 By("deploy helper server successfully")
203
204 By("create http replace chaos CRD objects")
205 replacebody := "Hello Chaos Mesh"
206 replaceSecret := "Foo!"
207
208 httpChaos := &v1alpha1.HTTPChaos{
209 ObjectMeta: metav1.ObjectMeta{
210 Name: "http-chaos",
211 Namespace: ns,
212 },
213 Spec: v1alpha1.HTTPChaosSpec{
214 PodSelector: v1alpha1.PodSelector{
215 Selector: v1alpha1.PodSelectorSpec{
216 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
217 Namespaces: []string{ns},
218 LabelSelectors: map[string]string{"app": "http"},
219 },
220 },
221 Mode: v1alpha1.OneMode,
222 },
223 Port: 8080,
224 Target: "Request",
225 PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
226 Replace: &v1alpha1.PodHttpChaosReplaceActions{
227 Headers: map[string]string{
228 SECRET: replaceSecret,
229 },
230 Body: []byte(replacebody),
231 },
232 },
233 },
234 }
235 err = cli.Create(ctx, httpChaos)
236 framework.ExpectNoError(err, "create http chaos error")
237
238 chaosKey := types.NamespacedName{
239 Namespace: ns,
240 Name: "http-chaos",
241 }
242
243 By("waiting for assertion http chaos")
244 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
245 chaos := &v1alpha1.HTTPChaos{}
246 err = cli.Get(ctx, chaosKey, chaos)
247 framework.ExpectNoError(err, "get http chaos error")
248
249 for _, c := range chaos.GetStatus().Conditions {
250 if c.Type == v1alpha1.ConditionAllInjected {
251 if c.Status != corev1.ConditionTrue {
252 return false, nil
253 }
254 } else if c.Type == v1alpha1.ConditionSelected {
255 if c.Status != corev1.ConditionTrue {
256 return false, nil
257 }
258 }
259 }
260
261 resp, err := getPodHttp(c, port, secret, body)
262 if err != nil {
263 return false, err
264 }
265 defer resp.Body.Close()
266
267 s := resp.Header.Get(SECRET)
268 b, err := ioutil.ReadAll(resp.Body)
269 if err != nil {
270 return false, err
271 }
272
273 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
274
275 if s == replaceSecret && string(b) == replacebody {
276 return true, nil
277 }
278 return false, nil
279 })
280 framework.ExpectNoError(err, "http chaos doesn't work as expected")
281
282 By("pause http replace chaos experiment")
283
284 err = util.PauseChaos(ctx, cli, httpChaos)
285 framework.ExpectNoError(err, "pause chaos error")
286
287 By("waiting for assertion about pause")
288 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
289 chaos := &v1alpha1.HTTPChaos{}
290 err = cli.Get(ctx, chaosKey, chaos)
291 framework.ExpectNoError(err, "get http chaos error")
292
293 for _, c := range chaos.GetStatus().Conditions {
294 if c.Type == v1alpha1.ConditionAllRecovered {
295 if c.Status != corev1.ConditionTrue {
296 return false, nil
297 }
298 } else if c.Type == v1alpha1.ConditionSelected {
299 if c.Status != corev1.ConditionTrue {
300 return false, nil
301 }
302 }
303 }
304
305 return true, err
306 })
307 framework.ExpectNoError(err, "check paused chaos failed")
308
309
310 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
311 resp, err := getPodHttp(c, port, secret, body)
312 if err != nil {
313 return false, err
314 }
315 defer resp.Body.Close()
316
317 s := resp.Header.Get(SECRET)
318 b, err := ioutil.ReadAll(resp.Body)
319 if err != nil {
320 return false, err
321 }
322
323 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
324
325 if s == secret && string(b) == body {
326 return true, nil
327 }
328 return false, nil
329 })
330 framework.ExpectNoError(err, "fail to recover http chaos")
331
332 By("resume http replace chaos experiment")
333
334 err = util.UnPauseChaos(ctx, cli, httpChaos)
335 framework.ExpectNoError(err, "resume chaos error")
336
337 By("assert that http replace is effective again")
338 err = wait.Poll(1*time.Second, 1*time.Minute, func() (done bool, err error) {
339 chaos := &v1alpha1.HTTPChaos{}
340 err = cli.Get(ctx, chaosKey, chaos)
341 framework.ExpectNoError(err, "get http chaos error")
342
343 for _, c := range chaos.GetStatus().Conditions {
344 if c.Type == v1alpha1.ConditionAllInjected {
345 if c.Status != corev1.ConditionTrue {
346 return false, nil
347 }
348 } else if c.Type == v1alpha1.ConditionSelected {
349 if c.Status != corev1.ConditionTrue {
350 return false, nil
351 }
352 }
353 }
354
355 return true, err
356 })
357 framework.ExpectNoError(err, "check resumed chaos failed")
358
359 err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
360 resp, err := getPodHttp(c, port, secret, body)
361 if err != nil {
362 return false, err
363 }
364 defer resp.Body.Close()
365
366 s := resp.Header.Get(SECRET)
367 b, err := ioutil.ReadAll(resp.Body)
368 if err != nil {
369 return false, err
370 }
371
372 klog.Infof("Status(%d), Secret(%s), Body(%s)", resp.StatusCode, s, string(b))
373
374 if s == replaceSecret && string(b) == replacebody {
375 return true, nil
376 }
377 return false, nil
378 })
379 framework.ExpectNoError(err, "HTTP chaos doesn't work as expected")
380
381 By("cleanup")
382
383 cli.Delete(ctx, httpChaos)
384 }
385