1
2
3
4
5
6
7
8
9
10
11
12
13
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
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