...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package action
18
19 import (
20 "context"
21 "fmt"
22 "reflect"
23 "strings"
24
25 "k8s.io/apimachinery/pkg/runtime"
26
27 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
28 impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
29 )
30
31
32
33 var _ impltypes.ChaosImpl = (*Multiplexer)(nil)
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 type Multiplexer struct {
64 impl interface{}
65 }
66
67 func (i *Multiplexer) callAccordingToAction(action, methodName string, defaultPhase v1alpha1.Phase, args ...interface{}) (v1alpha1.Phase, error) {
68 implType := reflect.TypeOf(i.impl).Elem()
69 implVal := reflect.ValueOf(i.impl)
70
71 reflectArgs := []reflect.Value{}
72 for _, arg := range args {
73 reflectArgs = append(reflectArgs, reflect.ValueOf(arg))
74 }
75 for i := 0; i < implType.NumField(); i++ {
76 field := implType.Field(i)
77
78 actions := strings.Split(field.Tag.Get("action"), ",")
79 for i := range actions {
80 if actions[i] == action {
81 rets := implVal.Elem().FieldByIndex(field.Index).MethodByName(methodName).Call(reflectArgs)
82
83
84 err := rets[1].Interface()
85 if err == nil {
86 return rets[0].Interface().(v1alpha1.Phase), nil
87 }
88
89 return rets[0].Interface().(v1alpha1.Phase), err.(error)
90 }
91 }
92 }
93 var gvk = ""
94 if obj, ok := args[len(args)-1].(runtime.Object); ok {
95 gvk = obj.GetObjectKind().GroupVersionKind().String()
96 }
97 return defaultPhase, NewErrorUnknownAction(gvk, action)
98 }
99
100 type ErrorUnknownAction struct {
101 GroupVersionKind string
102 Action string
103 }
104
105 func NewErrorUnknownAction(GVK string, action string) ErrorUnknownAction {
106 return ErrorUnknownAction{GroupVersionKind: GVK, Action: action}
107 }
108
109 func (it ErrorUnknownAction) Error() string {
110 return fmt.Sprintf("unknown action: Action: %s, GroupVersionKind: %s", it.Action, it.GroupVersionKind)
111 }
112
113
114 func (i *Multiplexer) getAction(obj v1alpha1.InnerObject) string {
115 return reflect.ValueOf(obj).Elem().FieldByName("Spec").FieldByName("Action").String()
116 }
117
118 func (i *Multiplexer) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
119 return i.callAccordingToAction(i.getAction(obj), "Apply", v1alpha1.NotInjected, ctx, index, records, obj)
120 }
121
122 func (i *Multiplexer) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
123 return i.callAccordingToAction(i.getAction(obj), "Recover", v1alpha1.Injected, ctx, index, records, obj)
124 }
125
126
127
128 func NewMultiplexer(impl interface{}) Multiplexer {
129 return Multiplexer{
130 impl,
131 }
132 }
133