forked from chaosblade-io/chaosblade
-
Notifications
You must be signed in to change notification settings - Fork 0
/
experiment.go
221 lines (199 loc) · 5.02 KB
/
experiment.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package data
import (
"time"
"database/sql"
"fmt"
"github.com/sirupsen/logrus"
)
type ExperimentModel struct {
Uid string
Command string
SubCommand string
Flag string
Status string
Error string
CreateTime string
UpdateTime string
}
type ExperimentSource interface {
// CheckAndInitExperimentTable, if experiment table not exists, then init it
CheckAndInitExperimentTable()
// ExperimentTableExists return true if experiment exists
ExperimentTableExists() (bool, error)
// InitExperimentTable for first executed
InitExperimentTable() error
// InsertExperimentModel for creating chaos experiment
InsertExperimentModel(model *ExperimentModel) error
// UpdateExperimentModelByUid
UpdateExperimentModelByUid(uid, status, errMsg string) error
// QueryExperimentModelByUid
QueryExperimentModelByUid(uid string) (*ExperimentModel, error)
// ListExperimentModels
ListExperimentModels() ([]*ExperimentModel, error)
// QueryExperimentModelsByCommand
QueryExperimentModelsByCommand(target string) ([]*ExperimentModel, error)
}
const expTableDDL = `CREATE TABLE IF NOT EXISTS experiment (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid VARCHAR(32) UNIQUE,
command VARCHAR NOT NULL,
sub_command VARCHAR,
flag VARCHAR,
status VARCHAR,
error VARCHAR,
create_time VARCHAR,
update_time VARCHAR
)`
var expIndexDDL = []string{
`CREATE INDEX exp_uid_uidx ON experiment (uid)`,
`CREATE INDEX exp_command_idx ON experiment (command)`,
`CREATE INDEX exp_status_idx ON experiment (status)`,
}
var insertExpDML = `INSERT INTO
experiment (uid, command, sub_command, flag, status, error, create_time, update_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`
func (s *Source) CheckAndInitExperimentTable() {
exists, err := s.ExperimentTableExists()
if err != nil {
logrus.Fatalf(err.Error())
}
if !exists {
err = s.InitExperimentTable()
if err != nil {
logrus.Fatalf(err.Error())
}
}
}
func (s *Source) ExperimentTableExists() (bool, error) {
stmt, err := s.DB.Prepare(tableExistsDQL)
if err != nil {
return false, fmt.Errorf("select experiment table exists err when invoke db prepare, %s", err)
}
defer stmt.Close()
rows, err := stmt.Query("experiment")
if err != nil {
return false, fmt.Errorf("select experiment table exists or not err, %s", err)
}
defer rows.Close()
var c int
for rows.Next() {
rows.Scan(&c)
break
}
return c != 0, nil
}
func (s *Source) InitExperimentTable() error {
_, err := s.DB.Exec(expTableDDL)
if err != nil {
return fmt.Errorf("create experiment table err, %s", err)
}
for _, sql := range expIndexDDL {
s.DB.Exec(sql)
}
return nil
}
func (s *Source) InsertExperimentModel(model *ExperimentModel) error {
stmt, err := s.DB.Prepare(insertExpDML)
if err != nil {
return err
}
defer stmt.Close()
_, err = stmt.Exec(
model.Uid,
model.Command,
model.SubCommand,
model.Flag,
model.Status,
model.Error,
model.CreateTime,
model.UpdateTime,
)
if err != nil {
return err
}
return nil
}
func (s *Source) UpdateExperimentModelByUid(uid, status, errMsg string) error {
stmt, err := s.DB.Prepare(`UPDATE experiment
SET status = ?, error = ?, update_time = ?
WHERE uid = ?
`)
if err != nil {
return err
}
defer stmt.Close()
_, err = stmt.Exec(status, errMsg, time.Now().Format(time.RFC3339Nano), uid)
if err != nil {
return err
}
return nil
}
func (s *Source) QueryExperimentModelByUid(uid string) (*ExperimentModel, error) {
stmt, err := s.DB.Prepare(`SELECT * FROM experiment WHERE uid = ?`)
if err != nil {
return nil, err
}
rows, err := stmt.Query(uid)
if err != nil {
return nil, err
}
defer rows.Close()
models, err := getExperimentModelsFrom(rows)
if err != nil {
return nil, err
}
if len(models) == 0 {
return nil, nil
}
return models[0], nil
}
func (s *Source) ListExperimentModels() ([]*ExperimentModel, error) {
stmt, err := s.DB.Prepare(`SELECT * FROM experiment`)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
return nil, err
}
defer rows.Close()
return getExperimentModelsFrom(rows)
}
func (s *Source) QueryExperimentModelsByCommand(target string) ([]*ExperimentModel, error) {
stmt, err := s.DB.Prepare(`SELECT * FROM experiment where command = ?`)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err := stmt.Query(target)
if err != nil {
return nil, err
}
defer rows.Close()
return getExperimentModelsFrom(rows)
}
func getExperimentModelsFrom(rows *sql.Rows) ([]*ExperimentModel, error) {
models := make([]*ExperimentModel, 0)
for rows.Next() {
var id int
var uid, command, subCommand, flag, status, error, createTime, updateTime string
err := rows.Scan(&id, &uid, &command, &subCommand, &flag, &status, &error, &createTime, &updateTime)
if err != nil {
return nil, err
}
model := &ExperimentModel{
Uid: uid,
Command: command,
SubCommand: subCommand,
Flag: flag,
Status: status,
Error: error,
CreateTime: createTime,
UpdateTime: updateTime,
}
models = append(models, model)
}
return models, nil
}