...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/workflow/controllers/serial_node_reconciler_test.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/workflow/controllers

     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 controllers
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"strings"
    22  	"time"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  
    31  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    32  )
    33  
    34  // integration tests
    35  var _ = Describe("Workflow", func() {
    36  	var ns string
    37  	BeforeEach(func() {
    38  		ctx := context.TODO()
    39  		newNs := corev1.Namespace{
    40  			ObjectMeta: metav1.ObjectMeta{
    41  				GenerateName: "chaos-mesh-",
    42  			},
    43  			Spec: corev1.NamespaceSpec{},
    44  		}
    45  		Expect(kubeClient.Create(ctx, &newNs)).To(Succeed())
    46  		ns = newNs.Name
    47  		By(fmt.Sprintf("create new namespace %s", ns))
    48  	})
    49  
    50  	AfterEach(func() {
    51  		ctx := context.TODO()
    52  		nsToDelete := corev1.Namespace{}
    53  		Expect(kubeClient.Get(ctx, types.NamespacedName{Name: ns}, &nsToDelete)).To(Succeed())
    54  		Expect(kubeClient.Delete(ctx, &nsToDelete)).To(Succeed())
    55  		By(fmt.Sprintf("cleanup namespace %s", ns))
    56  	})
    57  
    58  	Context("with one serial node", func() {
    59  		Context("with one simple serial node", func() {
    60  
    61  			It("should spawn all the children one by one", func() {
    62  				By("create simple workflow")
    63  				ctx := context.TODO()
    64  
    65  				networkChaosDuration := 5 * time.Second
    66  				networkChaosDurationString := networkChaosDuration.String()
    67  				podChaosDuration := 7 * time.Second
    68  				podChaosDurationString := podChaosDuration.String()
    69  				stressChaosDuration := 9 * time.Second
    70  				stressChaosDurationString := stressChaosDuration.String()
    71  
    72  				toleratedJitter := 10 * time.Second
    73  
    74  				simpleSerialWorkflow := v1alpha1.Workflow{
    75  					ObjectMeta: metav1.ObjectMeta{
    76  						Name:      "simple-serial",
    77  						Namespace: ns,
    78  					},
    79  					Spec: v1alpha1.WorkflowSpec{
    80  						Entry: "serial",
    81  						Templates: []v1alpha1.Template{
    82  							{
    83  								Name: "serial",
    84  								Type: v1alpha1.TypeSerial,
    85  								Children: []string{
    86  									"network-chaos",
    87  									"pod-chaos",
    88  									"stress-chaos",
    89  								},
    90  							}, {
    91  								Name:     "network-chaos",
    92  								Type:     v1alpha1.TypeNetworkChaos,
    93  								Deadline: &networkChaosDurationString,
    94  								EmbedChaos: &v1alpha1.EmbedChaos{
    95  									NetworkChaos: &v1alpha1.NetworkChaosSpec{
    96  										PodSelector: v1alpha1.PodSelector{
    97  											Selector: v1alpha1.PodSelectorSpec{
    98  												GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
    99  													Namespaces: []string{ns},
   100  													LabelSelectors: map[string]string{
   101  														"app": "not-exist",
   102  													},
   103  												},
   104  											},
   105  											Mode: v1alpha1.AllMode,
   106  										},
   107  										Action: v1alpha1.PartitionAction,
   108  									},
   109  								},
   110  							}, {
   111  								Name:     "pod-chaos",
   112  								Type:     v1alpha1.TypePodChaos,
   113  								Deadline: &podChaosDurationString,
   114  								EmbedChaos: &v1alpha1.EmbedChaos{
   115  									PodChaos: &v1alpha1.PodChaosSpec{
   116  										ContainerSelector: v1alpha1.ContainerSelector{
   117  											PodSelector: v1alpha1.PodSelector{
   118  												Selector: v1alpha1.PodSelectorSpec{
   119  													GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   120  														Namespaces: []string{ns},
   121  														LabelSelectors: map[string]string{
   122  															"app": "not-exist",
   123  														},
   124  													},
   125  												},
   126  												Mode: v1alpha1.AllMode,
   127  											},
   128  										},
   129  										Action: v1alpha1.PodKillAction,
   130  									},
   131  								},
   132  							},
   133  							{
   134  								Name:     "stress-chaos",
   135  								Type:     v1alpha1.TypeStressChaos,
   136  								Deadline: &stressChaosDurationString,
   137  								EmbedChaos: &v1alpha1.EmbedChaos{
   138  									StressChaos: &v1alpha1.StressChaosSpec{
   139  										ContainerSelector: v1alpha1.ContainerSelector{
   140  											PodSelector: v1alpha1.PodSelector{
   141  												Selector: v1alpha1.PodSelectorSpec{
   142  													GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   143  														Namespaces: []string{ns},
   144  														LabelSelectors: map[string]string{
   145  															"app": "not-exist",
   146  														},
   147  													},
   148  												},
   149  												Mode: v1alpha1.AllMode,
   150  											},
   151  										},
   152  										Stressors: &v1alpha1.Stressors{
   153  											CPUStressor: &v1alpha1.CPUStressor{
   154  												Stressor: v1alpha1.Stressor{
   155  													Workers: 2,
   156  												},
   157  											}},
   158  									},
   159  								},
   160  							},
   161  						},
   162  					}}
   163  				Expect(kubeClient.Create(ctx, &simpleSerialWorkflow)).To(Succeed())
   164  
   165  				By("assert that all resource has been created")
   166  
   167  				By("assert that entry node created")
   168  				Eventually(func() int {
   169  					workflowNodeList := v1alpha1.WorkflowNodeList{}
   170  					Expect(kubeClient.List(ctx, &workflowNodeList, &client.ListOptions{Namespace: ns})).To(Succeed())
   171  					return len(workflowNodeList.Items)
   172  				}, 10*time.Second, time.Second).Should(BeNumerically(">=", 1))
   173  
   174  				By("assert that network chaos has been created")
   175  				Eventually(func() bool {
   176  					chaosList := v1alpha1.NetworkChaosList{}
   177  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   178  					if len(chaosList.Items) != 1 {
   179  						return false
   180  					}
   181  					return strings.HasPrefix(chaosList.Items[0].Name, "network-chaos")
   182  				}, toleratedJitter, time.Second).Should(BeTrue())
   183  
   184  				By("assert that network chaos has been deleted")
   185  				Eventually(func() int {
   186  					chaosList := v1alpha1.NetworkChaosList{}
   187  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   188  					return len(chaosList.Items)
   189  				}, networkChaosDuration+toleratedJitter, time.Second).Should(BeZero())
   190  
   191  				By("assert that pod chaos has been created")
   192  				Eventually(func() bool {
   193  					chaosList := v1alpha1.PodChaosList{}
   194  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   195  					if len(chaosList.Items) != 1 {
   196  						return false
   197  					}
   198  					return strings.HasPrefix(chaosList.Items[0].Name, "pod-chaos")
   199  				}, toleratedJitter, time.Second).Should(BeTrue())
   200  
   201  				By("assert that pod chaos has been deleted")
   202  				Eventually(func() int {
   203  					chaosList := v1alpha1.PodChaosList{}
   204  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   205  					return len(chaosList.Items)
   206  				}, podChaosDuration+toleratedJitter, time.Second).Should(BeZero())
   207  
   208  				By("assert that stress chaos has been created")
   209  				Eventually(func() bool {
   210  					chaosList := v1alpha1.StressChaosList{}
   211  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   212  					if len(chaosList.Items) != 1 {
   213  						return false
   214  					}
   215  					return strings.HasPrefix(chaosList.Items[0].Name, "stress-chaos")
   216  				}, toleratedJitter, time.Second).Should(BeTrue())
   217  
   218  				By("assert that stress chaos has been deleted")
   219  				Eventually(func() int {
   220  					chaosList := v1alpha1.StressChaosList{}
   221  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   222  					return len(chaosList.Items)
   223  				}, stressChaosDuration+toleratedJitter, time.Second).Should(BeZero())
   224  
   225  				By("assert that serial node marked as finished")
   226  				Eventually(func() bool {
   227  					workflowNodeList := v1alpha1.WorkflowNodeList{}
   228  					Expect(kubeClient.List(ctx, &workflowNodeList, &client.ListOptions{Namespace: ns})).To(Succeed())
   229  					if len(workflowNodeList.Items) != 4 {
   230  						return false
   231  					}
   232  					entryFounded := false
   233  					var entry *v1alpha1.WorkflowNode = nil
   234  					for _, item := range workflowNodeList.Items {
   235  						item := item
   236  						if item.Spec.Type == v1alpha1.TypeSerial {
   237  							entryFounded = true
   238  							entry = &item
   239  						}
   240  					}
   241  					if !entryFounded || entry == nil {
   242  						return false
   243  					}
   244  					return ConditionEqualsTo(entry.Status, v1alpha1.ConditionAccomplished, corev1.ConditionTrue)
   245  				}, toleratedJitter, time.Second).Should(BeTrue())
   246  			})
   247  		})
   248  	})
   249  })
   250