...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package podiochaosmanager
17
18 import (
19 "context"
20
21 "github.com/go-logr/logr"
22 "github.com/pkg/errors"
23 v1 "k8s.io/api/core/v1"
24 k8sError "k8s.io/apimachinery/pkg/api/errors"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/runtime"
27 "k8s.io/apimachinery/pkg/types"
28 "k8s.io/client-go/util/retry"
29 "sigs.k8s.io/controller-runtime/pkg/client"
30
31 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
32 )
33
34 var (
35
36 ErrPodNotFound = errors.New("pod not found")
37
38
39
40 ErrPodNotRunning = errors.New("pod not running")
41 )
42
43
44 type PodIOManager struct {
45 Source string
46
47 Log logr.Logger
48 client.Client
49 client.Reader
50 scheme *runtime.Scheme
51
52 Key types.NamespacedName
53 T *PodIOTransaction
54 }
55
56
57 type CommitResponse struct {
58 Key types.NamespacedName
59 Err error
60 }
61
62
63 func (m *PodIOManager) Commit(ctx context.Context, owner *v1alpha1.IOChaos) (int64, error) {
64 m.Log.Info("running modification on pod", "key", m.Key, "modification", m.T)
65 updateError := retry.RetryOnConflict(retry.DefaultRetry, func() error {
66 chaos := &v1alpha1.PodIOChaos{}
67
68 err := m.Client.Get(ctx, m.Key, chaos)
69 if err != nil {
70 if !k8sError.IsNotFound(err) {
71 m.Log.Error(err, "error while getting podiochaos")
72 return err
73 }
74
75 err := m.CreateNewPodIOChaos(ctx)
76 if err != nil {
77 m.Log.Error(err, "error while creating new podiochaos")
78 return err
79 }
80
81 return nil
82 }
83
84 err = m.T.Apply(chaos)
85 if err != nil {
86 m.Log.Error(err, "error while applying transactions", "transaction", m.T)
87 return err
88 }
89
90 return m.Client.Update(ctx, chaos)
91 })
92 if updateError != nil {
93 return 0, updateError
94 }
95
96 chaos := &v1alpha1.PodIOChaos{}
97 err := m.Reader.Get(ctx, m.Key, chaos)
98 if err != nil {
99 m.Log.Error(err, "error while getting the latest generation number")
100 return 0, err
101 }
102 return chaos.GetGeneration(), nil
103 }
104
105 func (m *PodIOManager) CreateNewPodIOChaos(ctx context.Context) error {
106 var err error
107 chaos := &v1alpha1.PodIOChaos{}
108
109 pod := v1.Pod{}
110 err = m.Client.Get(ctx, m.Key, &pod)
111 if err != nil {
112 if !k8sError.IsNotFound(err) {
113 m.Log.Error(err, "error while finding pod")
114 return err
115 }
116
117 m.Log.Info("pod not found", "key", m.Key, "error", err.Error())
118 err = ErrPodNotFound
119 return err
120 }
121
122 if pod.Status.Phase != v1.PodRunning {
123 m.Log.Info("pod is not running", "key", m.Key)
124 err = ErrPodNotRunning
125 return err
126 }
127
128 chaos.Name = m.Key.Name
129 chaos.Namespace = m.Key.Namespace
130 chaos.OwnerReferences = []metav1.OwnerReference{
131 {
132 APIVersion: pod.APIVersion,
133 Kind: pod.Kind,
134 Name: pod.Name,
135 UID: pod.UID,
136 },
137 }
138 err = m.T.Apply(chaos)
139 if err != nil {
140 m.Log.Error(err, "error while applying transactions", "transaction", m.T)
141 return err
142 }
143
144 return m.Client.Create(ctx, chaos)
145 }
146