...

Source file src/github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/chaos/httpchaos/http_replace.go

Documentation: github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/chaos/httpchaos

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    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  	// delete chaos CRD
   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  	// pause experiment
   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  	// wait 1 min to check whether io replace still exists
   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  	// resume experiment
   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  	// cleanup
   383  	cli.Delete(ctx, httpChaos)
   384  }
   385