-
Notifications
You must be signed in to change notification settings - Fork 0
/
gocassa.go
322 lines (289 loc) · 9.24 KB
/
gocassa.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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
package main
import (
"encoding/hex"
"flag"
"fmt"
"log"
"strings"
"github.com/ghodss/yaml"
"github.com/gocql/gocql"
)
// GoCassa main struct
type GoCassa struct {
session *gocql.Session
server *string
port *int
keyspace *string
action string
}
// Init function for GoCassa
func (gc *GoCassa) Init(server *string, port *int, keyspace *string, action string) (err error) {
gc.server = server
gc.port = port
gc.keyspace = keyspace
gc.action = action
cluster := gocql.NewCluster(*gc.server)
cluster.Keyspace = *gc.keyspace
cluster.Port = *gc.port
gc.session, err = cluster.CreateSession()
if err != nil {
return err
}
return nil
}
// Destroy GoCassa object
func (gc *GoCassa) Destroy() {
defer gc.session.Close()
}
// Print set GoCassa info
func (gc *GoCassa) Print() {
fmt.Println("Server: ", gc.server)
fmt.Println("Port: ", gc.port)
fmt.Println("Keyspace: ", gc.keyspace)
fmt.Println("Action: ", gc.action)
}
// GetInfoFromID - Get object info from database
func (gc *GoCassa) GetInfoFromID(id string) map[string]string {
var key, column1, value string
var data map[string]string
data = make(map[string]string)
query := `SELECT key, column1, value FROM obj_uuid_table WHERE key = ` + textAsBlob(id, false)
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
if strings.HasPrefix(column1, "type") || strings.HasPrefix(column1, "fq_name") || strings.HasPrefix(column1, "parent_type") {
// fmt.Println("\t", column1, value)
data[column1] = value
}
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
return data
}
// SearchInside returns all records which contains string str
func (gc *GoCassa) SearchInside(str string) {
var key, column1, value string
var tables []string
tables = append(tables, `obj_uuid_table`)
tables = append(tables, `obj_fq_name_table`)
for _, table := range tables {
query := `SELECT key, column1, value FROM ` + table
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
if strings.Contains(column1, str) || strings.Contains(key, str) || strings.Contains(value, str) {
fmt.Println(key, column1, value)
}
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
}
}
func textAsBlob(src string, underReplace bool) string {
len := len([]byte(src))
blob := make([]byte, hex.EncodedLen(len))
if underReplace {
hex.Encode(blob, []byte(strings.Replace(src, "-", "_", -1)))
} else {
hex.Encode(blob, []byte(src))
}
return "0x" + string(blob)
}
func (gc *GoCassa) findIDInFQTable(objType string, uid string) bool {
var key, column1, value string
var query string
if len(objType) == 0 {
query = `SELECT key, column1, value FROM obj_fq_name_table`
} else {
query = `SELECT key, column1, value FROM obj_fq_name_table WHERE key = ` + textAsBlob(objType, true)
}
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
if strings.Contains(column1, uid) {
return true
}
}
return false
}
func (gc *GoCassa) checkAllBackRefs() {
fmt.Println("Checking back reference for all objects")
var key, column1, value string
find := "backref"
query := `SELECT key, column1, value FROM obj_uuid_table`
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
if strings.HasPrefix(column1, find) {
record := strings.Split(column1, ":")
if !gc.findIDInFQTable(record[1], record[2]) {
fmt.Println("NOT FOUND object definition in fq_name_table for:", record[2], "as type: ", record[1], " based on: ", column1, "Source object of backref: ", key)
if len(gc.GetInfoFromID(record[2])) == 0 {
fmt.Println("OBJECT ", record[2], "hasn't defined attributes at all")
}
}
}
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
fmt.Printf("DONE %d records were checked\n", iter.NumRows())
}
// checkBackRefsFor will find all records which contains backrefs of ID
func (gc *GoCassa) checkBackRefsFor(id string) {
fmt.Println("Checking back reference for: ", id)
var key, column1, value string
find := "backref"
query := `SELECT key, column1, value FROM obj_uuid_table`
iter := gc.session.Query(query).Iter()
cntBr := 0
for iter.Scan(&key, &column1, &value) {
if strings.HasPrefix(column1, find) && strings.Contains(column1, id) {
fmt.Printf("key: %s value: %s \n", key, column1)
cntBr = cntBr + 1
record := strings.Split(column1, ":")
if !gc.findIDInFQTable(record[1], record[2]) {
fmt.Println("NOT FOUND record in fq_name_table for:", record[2], " as type ", record[1], " based on: ", column1, "Source object: ", key)
}
}
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
fmt.Printf("Backrefs count: %d\n", cntBr)
fmt.Println("DONE")
}
func (gc *GoCassa) deleteBackRefsRecord(keyIn string, column1In string) {
var key, column1, value string
query := `DELETE FROM obj_uuid_table WHERE key = ` + textAsBlob(keyIn, false) + ` and column1 = ` + textAsBlob(column1In, false)
fmt.Println(query)
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
fmt.Printf("Has been delete -> key: %s value: %s \n", key, column1)
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
}
// clearBackRefsFor will find all records which contains backrefs of ID
func (gc *GoCassa) clearBackRefsFor(id string) {
fmt.Printf("Check if object %s exists \n", id)
var key, column1, value string
if gc.findIDInFQTable("", id) {
fmt.Println("Object exists, backrefs cannot be deleted")
return
}
fmt.Println("Object doesn't exist, backrefs can be deleted")
find := "backref"
query := `SELECT key, column1, value FROM obj_uuid_table`
iter := gc.session.Query(query).Iter()
cntBr := 0
for iter.Scan(&key, &column1, &value) {
if strings.HasPrefix(column1, find) && strings.Contains(column1, id) {
gc.deleteBackRefsRecord(key, column1)
cntBr = cntBr + 1
}
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
fmt.Printf("Number of deleted backrefs: %d\n", cntBr)
fmt.Println("DONE")
}
func (gc *GoCassa) deletePropsRecord(keyIn string, column1In string) {
var key, column1, value string
query := `DELETE FROM obj_uuid_table WHERE key = ` + textAsBlob(keyIn, false) + ` and column1 = ` + textAsBlob(column1In, false)
fmt.Println(query)
iter := gc.session.Query(query).Iter()
for iter.Scan(&key, &column1, &value) {
fmt.Printf("Has been delete -> key: %s value: %s \n", key, column1)
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
}
// clearPropsFor will find all records which contains backrefs of ID
func (gc *GoCassa) clearPropsFor(id string) {
fmt.Printf("Check if object %s exists \n", id)
var key, column1, value string
if gc.findIDInFQTable("", id) {
fmt.Println("Object exists, properties cannot be deleted")
return
}
fmt.Println("Object doesn't exist, all properties can be deleted")
query := `SELECT key, column1, value FROM obj_uuid_table WHERE key = textAsBlob('` + id + `')`
iter := gc.session.Query(query).Iter()
cnt := 0
for iter.Scan(&key, &column1, &value) {
cnt++
fmt.Println(key, column1, value)
gc.deletePropsRecord(key, column1)
}
if err := iter.Close(); err != nil {
log.Fatal("ERROR: ", err)
}
fmt.Printf("Number of deleted props: %d\n", cnt)
fmt.Println("DONE")
}
func main() {
serverPtr := flag.String("server", "127.0.0.1", "Server IP address")
portPtr := flag.Int("port", 9041, "Cassandra port")
keyspacePtr := flag.String("keyspace", "config_db_uuid", "Cassandra KeySpace")
// tablePtr := flag.String("table", "obj_fq_name_table", "Table")
// findPtr := flag.String("find", "default", "String to search in records")
// checkBR := flag.Bool("check-backrefs", false, "Check backrefs inside Contrail cassandra database")
flag.Parse()
args := flag.Args()
if args[0] == "help" || len(args) < 2 {
PrintUsage()
return
}
gc := GoCassa{}
err := gc.Init(serverPtr, portPtr, keyspacePtr, "checkbr")
if err != nil {
fmt.Println("Error: ", err)
return
}
// gc.Print()
switch cmd := args[0]; cmd {
case "fulltext":
gc.SearchInside(args[1])
case "info":
fmt.Println("INFO for id: ", args[1])
PrintMap(gc.GetInfoFromID(args[1]))
case "check-backref":
if args[1] == "all" {
gc.checkAllBackRefs()
} else {
gc.checkBackRefsFor(args[1])
}
case "clear-backref":
gc.clearBackRefsFor(args[1])
case "clear-props":
gc.clearPropsFor(args[1])
default:
fmt.Println("\n------> Unknow command: ", args[0])
PrintUsage()
}
gc.Destroy()
}
// PrintUsage of application
func PrintUsage() {
fmt.Println("\n Usage: gocassa [--flag [--flag]] command \n Commands:")
PrintCmd()
fmt.Println("\n Flags:")
flag.PrintDefaults()
}
// PrintCmd help info
func PrintCmd() {
fmt.Println("\t help \t\t\t Print application usage")
fmt.Println("\t info <id> \t\t Returns base information about object with <ID>, stored in DB ")
fmt.Println("\t fulltext <string> \t Returns all records which contains <string>")
fmt.Println("\t check-backref <id>|all \t Check back reference inconsistency to <id> or all ids")
fmt.Println("\t clear-backref <id>|all \t Remove back references to <id> if object doesn't exist")
fmt.Println("\t clear-props <id> \t Remove properties of <id> only if object doesn't exist")
}
// PrintMap /
func PrintMap(data map[string]string) {
yml, _ := yaml.Marshal(&data)
fmt.Println("----")
fmt.Println(string(yml))
}