...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package main
17
18 import (
19 "fmt"
20 "os"
21 "strings"
22
23 "gopkg.in/yaml.v2"
24 )
25
26 type Object struct {
27 ApiVersion string `yaml:"apiVersion"`
28 Kind string `yaml:"kind"`
29 Metadata yaml.MapSlice `yaml:"metadata"`
30 Spec yaml.MapSlice `yaml:"spec"`
31 }
32
33 func main() {
34 if len(os.Args) != 3 {
35 fmt.Println("migrator <old-yaml> <new-yaml>")
36 os.Exit(1)
37 }
38 data, err := os.ReadFile(os.Args[1])
39 if err != nil {
40 fmt.Println(err)
41 os.Exit(1)
42 }
43 var (
44 oldObj Object
45 newObj Object
46 )
47 err = yaml.Unmarshal(data, &oldObj)
48 if err != nil {
49 fmt.Println(err)
50 os.Exit(1)
51 }
52 {
53 var (
54 schedule yaml.MapSlice
55 findSchedule bool
56 )
57
58 if isIncompatibleChaos(oldObj) {
59 fmt.Printf("the define of %s is changed in v2.0, please modify it according to the document, refer to https://chaos-mesh.org/docs/\n", oldObj.Kind)
60 os.Exit(1)
61 }
62
63 for _, item := range oldObj.Spec {
64 if item.Key == "scheduler" {
65 schedule = item.Value.(yaml.MapSlice)
66 findSchedule = true
67 }
68 }
69
70 if findSchedule {
71 newObj = toScheduleObject(oldObj, schedule)
72 } else {
73 newObj = oldObj
74 newObj.Spec = transformChaosSpec(oldObj)
75 }
76 }
77 data, err = yaml.Marshal(newObj)
78 if err != nil {
79 fmt.Println(err)
80 os.Exit(1)
81 }
82 err = os.WriteFile(os.Args[2], data, 0644)
83 if err != nil {
84 fmt.Println(err)
85 os.Exit(1)
86 }
87 }
88
89 func getKeyName(name string) string {
90 s := strings.ToLower(name)
91 return strings.ReplaceAll(s, "chaos", "Chaos")
92 }
93
94 func toNewKind(kind string) string {
95 if kind == "IoChaos" {
96 return "IOChaos"
97 }
98 return kind
99 }
100
101 func toScheduleObject(oldObj Object, schedule yaml.MapSlice) Object {
102 var newObj Object
103 var cron string
104 for _, item := range schedule {
105 if item.Key == "cron" {
106 cron = item.Value.(string)
107 }
108 }
109 newObj.ApiVersion = oldObj.ApiVersion
110 newObj.Metadata = oldObj.Metadata
111 newObj.Kind = "Schedule"
112 newObj.Spec = append(newObj.Spec, yaml.MapItem{Key: "schedule", Value: cron})
113 newObj.Spec = append(newObj.Spec, yaml.MapItem{Key: "type", Value: toNewKind(oldObj.Kind)})
114 newObj.Spec = append(newObj.Spec, yaml.MapItem{Key: "historyLimit", Value: 5})
115 newObj.Spec = append(newObj.Spec, yaml.MapItem{Key: "concurrencyPolicy", Value: "Forbid"})
116
117 newSpec := transformChaosSpec(oldObj)
118 newObj.Spec = append(newObj.Spec, yaml.MapItem{Key: getKeyName(oldObj.Kind), Value: newSpec})
119 return newObj
120 }
121
122 func transformChaosSpec(obj Object) yaml.MapSlice {
123 var (
124 newSpec yaml.MapSlice
125 containerNames []string
126 )
127 for _, kv := range obj.Spec {
128 if kv.Key == "scheduler" {
129 continue
130 }
131
132 if kv.Key == "containerName" {
133 containerNames = append(containerNames, kv.Value.(string))
134 continue
135 }
136
137 if obj.Kind == "DNSChaos" {
138
139
140
141 if kv.Key == "scope" && kv.Value == "all" {
142 patterns := []string{"*"}
143 kv = yaml.MapItem{Key: "patterns", Value: patterns}
144 }
145 }
146
147 newSpec = append(newSpec, kv)
148 }
149
150 if len(containerNames) != 0 {
151 newSpec = append(newSpec, yaml.MapItem{Key: "containerNames", Value: containerNames})
152 }
153
154 return newSpec
155 }
156
157 func isIncompatibleChaos(obj Object) bool {
158 incompatible := false
159 switch obj.Kind {
160 case "DNSChaos":
161 for _, kv := range obj.Spec {
162
163
164
165 if kv.Key == "scope" && kv.Value != "all" {
166 incompatible = true
167 }
168 }
169 default:
170 }
171
172 return incompatible
173 }
174