...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package recorder
17
18 import (
19 "encoding"
20 "encoding/json"
21 "errors"
22 "reflect"
23 "strconv"
24
25 "github.com/iancoleman/strcase"
26 )
27
28 var ErrInvalidType = errors.New("invalid type of fields")
29 var ErrUknownType = errors.New("uknown type of fields")
30
31 var annotationPrefix = "chaos-mesh.org/"
32
33 func generateAnnotations(e ChaosEvent) (map[string]string, error) {
34 annotations := make(map[string]string)
35
36 if e == nil {
37 return annotations, nil
38 }
39
40 val := reflect.ValueOf(e)
41 val = reflect.Indirect(val)
42 for index := 0; index < val.NumField(); index++ {
43 fieldName := val.Type().Field(index).Name
44 key := annotationPrefix + strcase.ToKebab(fieldName)
45 field := val.Field(index)
46 switch field.Kind() {
47 case reflect.Invalid:
48 return nil, ErrInvalidType
49 case reflect.String:
50 annotations[key] = field.String()
51 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
52 annotations[key] = strconv.Itoa(int(field.Int()))
53 default:
54 if marshaler, ok := field.Interface().(encoding.TextMarshaler); ok {
55 text, err := marshaler.MarshalText()
56 if err != nil {
57 return nil, err
58 }
59
60 annotations[key] = string(text)
61 } else {
62 text, err := json.Marshal(field.Interface())
63 if err != nil {
64 return nil, err
65 }
66 annotations[key] = string(text)
67 }
68 }
69 }
70 annotations[annotationPrefix+"type"] = strcase.ToKebab(val.Type().Name())
71
72 return annotations, nil
73 }
74
75
76
77 func FromAnnotations(annotations map[string]string) (ChaosEvent, error) {
78 typeName := annotations[annotationPrefix+"type"]
79 ev := allEvents[typeName]
80
81 if ev == nil {
82 return nil, ErrUknownType
83 }
84
85 val := reflect.ValueOf(ev)
86 val = reflect.Indirect(val)
87 newEmptyValue := reflect.Indirect(reflect.New(val.Type()))
88
89 for index := 0; index < newEmptyValue.NumField(); index++ {
90 fieldName := newEmptyValue.Type().Field(index).Name
91 key := annotationPrefix + strcase.ToKebab(fieldName)
92 field := newEmptyValue.Field(index)
93 switch field.Kind() {
94 case reflect.Invalid:
95 return nil, ErrInvalidType
96 case reflect.String:
97 field.SetString(annotations[key])
98 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
99 num, err := strconv.Atoi(annotations[key])
100 if err != nil {
101 return nil, err
102 }
103 field.SetInt(int64(num))
104 default:
105 if unmarshaler, ok := field.Interface().(encoding.TextUnmarshaler); ok {
106 err := unmarshaler.UnmarshalText([]byte(annotations[key]))
107 if err != nil {
108 return nil, err
109 }
110 } else if unmarshaler, ok := field.Addr().Interface().(encoding.TextUnmarshaler); ok {
111 err := unmarshaler.UnmarshalText([]byte(annotations[key]))
112 if err != nil {
113 return nil, err
114 }
115 } else {
116 err := json.Unmarshal([]byte(annotations[key]), field.Addr().Interface())
117 if err != nil {
118 return nil, err
119 }
120 }
121 }
122 }
123 return newEmptyValue.Interface().(ChaosEvent), nil
124 }
125