1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package main
17
18 import (
19 "bytes"
20 "fmt"
21 "text/template"
22 )
23
24 const scheduleTemplate = `
25 allScheduleItem.register(Kind{{.Type}}, &ChaosKind{
26 chaos: &{{.Type}}{},
27 list: &{{.Type}}List{},
28 })
29 `
30
31 func generateScheduleRegister(name string) string {
32 tmpl, err := template.New("ini").Parse(scheduleTemplate)
33 if err != nil {
34 log.Error(err, "fail to build template")
35 panic(err)
36 }
37
38 buf := new(bytes.Buffer)
39 err = tmpl.Execute(buf, &metadata{
40 Type: name,
41 })
42 if err != nil {
43 log.Error(err, "fail to execute template")
44 panic(err)
45 }
46
47 return buf.String()
48 }
49
50 type scheduleCodeGenerator struct {
51
52 chaosTypes []string
53 }
54
55 func newScheduleCodeGenerator(types []string) *scheduleCodeGenerator {
56 return &scheduleCodeGenerator{chaosTypes: types}
57 }
58
59 func (it *scheduleCodeGenerator) AppendTypes(typeName string) {
60 it.chaosTypes = append(it.chaosTypes, typeName)
61 }
62
63 func (it *scheduleCodeGenerator) Render() string {
64
65 scheduleTemplateTypesEntries := ""
66 for _, item := range it.chaosTypes {
67 scheduleTemplateTypesEntries += generateScheduleTemplateTypes(item)
68 }
69
70 embedChaosEntries := ""
71 for _, item := range it.chaosTypes {
72 embedChaosEntries += generateScheduleItem(item)
73 }
74
75 scheduleTemplateTypeEntries := ""
76 for _, item := range it.chaosTypes {
77 scheduleTemplateTypeEntries += fmt.Sprintf(` ScheduleType%s,
78 `, item)
79 }
80
81 spawnMethod := ""
82 for _, item := range it.chaosTypes {
83 spawnMethod += generateFillingMethodScheduleItem(item, scheduleFillingEntryTemplate)
84 }
85
86 restoreMethod := ""
87 for _, item := range it.chaosTypes {
88 restoreMethod += generateFillingMethodScheduleItem(item, scheduleRestoreEntryTemplate)
89 }
90
91 imports := `import (
92 "github.com/pkg/errors"
93 )
94 `
95
96 scheduleTemplateTypesCodes := fmt.Sprintf(`%s
97
98 %s
99
100 const (
101 %s
102 )
103
104 var allScheduleTemplateType = []ScheduleTemplateType{
105 %s
106 }
107
108 func (it *ScheduleItem) SpawnNewObject(templateType ScheduleTemplateType) (GenericChaos, error) {
109 switch templateType {
110 %s
111 default:
112 return nil, errors.Wrapf(errInvalidValue, "unknown template type %%s", templateType)
113 }
114 }
115
116 func (it *ScheduleItem) RestoreChaosSpec(root interface{}) error {
117 switch chaos := root.(type) {
118 %s
119 default:
120 return errors.Wrapf(errInvalidValue, "unknown chaos %%#v", root)
121 }
122 }
123 `,
124 boilerplate,
125 imports,
126 scheduleTemplateTypesEntries,
127 scheduleTemplateTypeEntries,
128 spawnMethod,
129 restoreMethod,
130 )
131
132 return scheduleTemplateTypesCodes
133 }
134
135 const scheduleTemplateTypeEntryTemplate = ` ScheduleType{{.Type}} ScheduleTemplateType = "{{.Type}}"
136 `
137
138 func generateScheduleTemplateTypes(typeName string) string {
139 tmpl, err := template.New("scheduleTemplates").Parse(scheduleTemplateTypeEntryTemplate)
140 if err != nil {
141 log.Error(err, "fail to build template")
142 return ""
143 }
144
145 buf := new(bytes.Buffer)
146 err = tmpl.Execute(buf, &metadata{
147 Type: typeName,
148 })
149 if err != nil {
150 log.Error(err, "fail to execute template")
151 return ""
152 }
153
154 return buf.String()
155 }
156
157 const scheduleItemTemplate = ` // +optional
158 {{.Type}} *{{.Type}}Spec ` + "`" + `json:"{{.JsonField}},omitempty"` + "`" + `
159 `
160
161 func generateScheduleItem(typeName string) string {
162 value := struct {
163 Type string
164 JsonField string
165 }{
166 Type: typeName,
167 JsonField: lowercaseCamelCase(typeName),
168 }
169 tmpl, err := template.New("scheduleTemplates").Parse(scheduleItemTemplate)
170 if err != nil {
171 log.Error(err, "fail to build template")
172 return ""
173 }
174
175 buf := new(bytes.Buffer)
176 err = tmpl.Execute(buf, &value)
177 if err != nil {
178 log.Error(err, "fail to execute template")
179 return ""
180 }
181
182 return buf.String()
183 }
184
185 const scheduleFillingEntryTemplate = ` case ScheduleType{{.Type}}:
186 result := {{.Type}}{}
187 result.Spec = *it.{{.Type}}
188 return &result, nil
189 `
190
191 const scheduleRestoreEntryTemplate = ` case *{{.Type}}:
192 *it.{{.Type}} = chaos.Spec
193 return nil
194 `
195
196 func generateFillingMethodScheduleItem(typeName, methodTemplate string) string {
197 tmpl, err := template.New("fillingMethod").Parse(methodTemplate)
198 if err != nil {
199 log.Error(err, "fail to build template")
200 return ""
201 }
202
203 buf := new(bytes.Buffer)
204 err = tmpl.Execute(buf, &metadata{
205 Type: typeName,
206 })
207 if err != nil {
208 log.Error(err, "fail to execute template")
209 return ""
210 }
211
212 return buf.String()
213 }
214