github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/networkdb/networkdbdiagnostic.go (about) 1 package networkdb 2 3 import ( 4 "context" 5 "encoding/base64" 6 "fmt" 7 "net/http" 8 "strings" 9 10 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/diagnostic" 11 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/internal/caller" 12 "github.com/containerd/log" 13 ) 14 15 const ( 16 missingParameter = "missing parameter" 17 dbNotAvailable = "database not available" 18 ) 19 20 // NetDbPaths2Func TODO 21 var NetDbPaths2Func = map[string]diagnostic.HTTPHandlerFunc{ 22 "/join": dbJoin, 23 "/networkpeers": dbPeers, 24 "/clusterpeers": dbClusterPeers, 25 "/joinnetwork": dbJoinNetwork, 26 "/leavenetwork": dbLeaveNetwork, 27 "/createentry": dbCreateEntry, 28 "/updateentry": dbUpdateEntry, 29 "/deleteentry": dbDeleteEntry, 30 "/getentry": dbGetEntry, 31 "/gettable": dbGetTable, 32 "/networkstats": dbNetworkStats, 33 } 34 35 func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) { 36 _ = r.ParseForm() 37 diagnostic.DebugHTTPForm(r) 38 _, json := diagnostic.ParseHTTPFormOptions(r) 39 40 // audit logs 41 logger := log.G(context.TODO()).WithFields(log.Fields{ 42 "component": "diagnostic", 43 "remoteIP": r.RemoteAddr, 44 "method": caller.Name(0), 45 "url": r.URL.String(), 46 }) 47 logger.Info("join cluster") 48 49 if len(r.Form["members"]) < 1 { 50 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?members=ip1,ip2,...", r.URL.Path)) 51 logger.Error("join cluster failed, wrong input") 52 diagnostic.HTTPReply(w, rsp, json) 53 return 54 } 55 56 nDB, ok := ctx.(*NetworkDB) 57 if ok { 58 err := nDB.Join(strings.Split(r.Form["members"][0], ",")) 59 if err != nil { 60 rsp := diagnostic.FailCommand(fmt.Errorf("%s error in the DB join %s", r.URL.Path, err)) 61 logger.WithError(err).Error("join cluster failed") 62 diagnostic.HTTPReply(w, rsp, json) 63 return 64 } 65 66 logger.Info("join cluster done") 67 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 68 return 69 } 70 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 71 } 72 73 func dbPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) { 74 _ = r.ParseForm() 75 diagnostic.DebugHTTPForm(r) 76 _, json := diagnostic.ParseHTTPFormOptions(r) 77 78 // audit logs 79 logger := log.G(context.TODO()).WithFields(log.Fields{ 80 "component": "diagnostic", 81 "remoteIP": r.RemoteAddr, 82 "method": caller.Name(0), 83 "url": r.URL.String(), 84 }) 85 logger.Info("network peers") 86 87 if len(r.Form["nid"]) < 1 { 88 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path)) 89 logger.Error("network peers failed, wrong input") 90 diagnostic.HTTPReply(w, rsp, json) 91 return 92 } 93 94 nDB, ok := ctx.(*NetworkDB) 95 if ok { 96 peers := nDB.Peers(r.Form["nid"][0]) 97 rsp := &diagnostic.TableObj{Length: len(peers)} 98 for i, peerInfo := range peers { 99 if peerInfo.IP == "unknown" { 100 rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: "orphan-" + peerInfo.Name, IP: peerInfo.IP}) 101 } else { 102 rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP}) 103 } 104 } 105 logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network peers done") 106 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json) 107 return 108 } 109 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 110 } 111 112 func dbClusterPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) { 113 _ = r.ParseForm() 114 diagnostic.DebugHTTPForm(r) 115 _, json := diagnostic.ParseHTTPFormOptions(r) 116 117 // audit logs 118 logger := log.G(context.TODO()).WithFields(log.Fields{ 119 "component": "diagnostic", 120 "remoteIP": r.RemoteAddr, 121 "method": caller.Name(0), 122 "url": r.URL.String(), 123 }) 124 logger.Info("cluster peers") 125 126 nDB, ok := ctx.(*NetworkDB) 127 if ok { 128 peers := nDB.ClusterPeers() 129 rsp := &diagnostic.TableObj{Length: len(peers)} 130 for i, peerInfo := range peers { 131 rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP}) 132 } 133 logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("cluster peers done") 134 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json) 135 return 136 } 137 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 138 } 139 140 func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { 141 _ = r.ParseForm() 142 diagnostic.DebugHTTPForm(r) 143 unsafe, json := diagnostic.ParseHTTPFormOptions(r) 144 145 // audit logs 146 logger := log.G(context.TODO()).WithFields(log.Fields{ 147 "component": "diagnostic", 148 "remoteIP": r.RemoteAddr, 149 "method": caller.Name(0), 150 "url": r.URL.String(), 151 }) 152 logger.Info("create entry") 153 154 if len(r.Form["tname"]) < 1 || 155 len(r.Form["nid"]) < 1 || 156 len(r.Form["key"]) < 1 || 157 len(r.Form["value"]) < 1 { 158 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path)) 159 logger.Error("create entry failed, wrong input") 160 diagnostic.HTTPReply(w, rsp, json) 161 return 162 } 163 164 tname := r.Form["tname"][0] 165 nid := r.Form["nid"][0] 166 key := r.Form["key"][0] 167 value := r.Form["value"][0] 168 decodedValue := []byte(value) 169 if !unsafe { 170 var err error 171 decodedValue, err = base64.StdEncoding.DecodeString(value) 172 if err != nil { 173 logger.WithError(err).Error("create entry failed") 174 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 175 return 176 } 177 } 178 179 nDB, ok := ctx.(*NetworkDB) 180 if ok { 181 if err := nDB.CreateEntry(tname, nid, key, decodedValue); err != nil { 182 rsp := diagnostic.FailCommand(err) 183 diagnostic.HTTPReply(w, rsp, json) 184 logger.WithError(err).Error("create entry failed") 185 return 186 } 187 logger.Info("create entry done") 188 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 189 return 190 } 191 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 192 } 193 194 func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { 195 _ = r.ParseForm() 196 diagnostic.DebugHTTPForm(r) 197 unsafe, json := diagnostic.ParseHTTPFormOptions(r) 198 199 // audit logs 200 logger := log.G(context.TODO()).WithFields(log.Fields{ 201 "component": "diagnostic", 202 "remoteIP": r.RemoteAddr, 203 "method": caller.Name(0), 204 "url": r.URL.String(), 205 }) 206 logger.Info("update entry") 207 208 if len(r.Form["tname"]) < 1 || 209 len(r.Form["nid"]) < 1 || 210 len(r.Form["key"]) < 1 || 211 len(r.Form["value"]) < 1 { 212 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path)) 213 logger.Error("update entry failed, wrong input") 214 diagnostic.HTTPReply(w, rsp, json) 215 return 216 } 217 218 tname := r.Form["tname"][0] 219 nid := r.Form["nid"][0] 220 key := r.Form["key"][0] 221 value := r.Form["value"][0] 222 decodedValue := []byte(value) 223 if !unsafe { 224 var err error 225 decodedValue, err = base64.StdEncoding.DecodeString(value) 226 if err != nil { 227 logger.WithError(err).Error("update entry failed") 228 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 229 return 230 } 231 } 232 233 nDB, ok := ctx.(*NetworkDB) 234 if ok { 235 if err := nDB.UpdateEntry(tname, nid, key, decodedValue); err != nil { 236 logger.WithError(err).Error("update entry failed") 237 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 238 return 239 } 240 logger.Info("update entry done") 241 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 242 return 243 } 244 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 245 } 246 247 func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { 248 _ = r.ParseForm() 249 diagnostic.DebugHTTPForm(r) 250 _, json := diagnostic.ParseHTTPFormOptions(r) 251 252 // audit logs 253 logger := log.G(context.TODO()).WithFields(log.Fields{ 254 "component": "diagnostic", 255 "remoteIP": r.RemoteAddr, 256 "method": caller.Name(0), 257 "url": r.URL.String(), 258 }) 259 logger.Info("delete entry") 260 261 if len(r.Form["tname"]) < 1 || 262 len(r.Form["nid"]) < 1 || 263 len(r.Form["key"]) < 1 { 264 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path)) 265 logger.Error("delete entry failed, wrong input") 266 diagnostic.HTTPReply(w, rsp, json) 267 return 268 } 269 270 tname := r.Form["tname"][0] 271 nid := r.Form["nid"][0] 272 key := r.Form["key"][0] 273 274 nDB, ok := ctx.(*NetworkDB) 275 if ok { 276 err := nDB.DeleteEntry(tname, nid, key) 277 if err != nil { 278 logger.WithError(err).Error("delete entry failed") 279 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 280 return 281 } 282 logger.Info("delete entry done") 283 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 284 return 285 } 286 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 287 } 288 289 func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { 290 _ = r.ParseForm() 291 diagnostic.DebugHTTPForm(r) 292 unsafe, json := diagnostic.ParseHTTPFormOptions(r) 293 294 // audit logs 295 logger := log.G(context.TODO()).WithFields(log.Fields{ 296 "component": "diagnostic", 297 "remoteIP": r.RemoteAddr, 298 "method": caller.Name(0), 299 "url": r.URL.String(), 300 }) 301 logger.Info("get entry") 302 303 if len(r.Form["tname"]) < 1 || 304 len(r.Form["nid"]) < 1 || 305 len(r.Form["key"]) < 1 { 306 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path)) 307 logger.Error("get entry failed, wrong input") 308 diagnostic.HTTPReply(w, rsp, json) 309 return 310 } 311 312 tname := r.Form["tname"][0] 313 nid := r.Form["nid"][0] 314 key := r.Form["key"][0] 315 316 nDB, ok := ctx.(*NetworkDB) 317 if ok { 318 value, err := nDB.GetEntry(tname, nid, key) 319 if err != nil { 320 logger.WithError(err).Error("get entry failed") 321 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 322 return 323 } 324 325 var encodedValue string 326 if unsafe { 327 encodedValue = string(value) 328 } else { 329 encodedValue = base64.StdEncoding.EncodeToString(value) 330 } 331 332 rsp := &diagnostic.TableEntryObj{Key: key, Value: encodedValue} 333 logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get entry done") 334 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json) 335 return 336 } 337 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 338 } 339 340 func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) { 341 _ = r.ParseForm() 342 diagnostic.DebugHTTPForm(r) 343 _, json := diagnostic.ParseHTTPFormOptions(r) 344 345 // audit logs 346 logger := log.G(context.TODO()).WithFields(log.Fields{ 347 "component": "diagnostic", 348 "remoteIP": r.RemoteAddr, 349 "method": caller.Name(0), 350 "url": r.URL.String(), 351 }) 352 logger.Info("join network") 353 354 if len(r.Form["nid"]) < 1 { 355 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path)) 356 logger.Error("join network failed, wrong input") 357 diagnostic.HTTPReply(w, rsp, json) 358 return 359 } 360 361 nid := r.Form["nid"][0] 362 363 nDB, ok := ctx.(*NetworkDB) 364 if ok { 365 if err := nDB.JoinNetwork(nid); err != nil { 366 logger.WithError(err).Error("join network failed") 367 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 368 return 369 } 370 logger.Info("join network done") 371 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 372 return 373 } 374 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 375 } 376 377 func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) { 378 _ = r.ParseForm() 379 diagnostic.DebugHTTPForm(r) 380 _, json := diagnostic.ParseHTTPFormOptions(r) 381 382 // audit logs 383 logger := log.G(context.TODO()).WithFields(log.Fields{ 384 "component": "diagnostic", 385 "remoteIP": r.RemoteAddr, 386 "method": caller.Name(0), 387 "url": r.URL.String(), 388 }) 389 logger.Info("leave network") 390 391 if len(r.Form["nid"]) < 1 { 392 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path)) 393 logger.Error("leave network failed, wrong input") 394 diagnostic.HTTPReply(w, rsp, json) 395 return 396 } 397 398 nid := r.Form["nid"][0] 399 400 nDB, ok := ctx.(*NetworkDB) 401 if ok { 402 if err := nDB.LeaveNetwork(nid); err != nil { 403 logger.WithError(err).Error("leave network failed") 404 diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json) 405 return 406 } 407 logger.Info("leave network done") 408 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json) 409 return 410 } 411 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 412 } 413 414 func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) { 415 _ = r.ParseForm() 416 diagnostic.DebugHTTPForm(r) 417 unsafe, json := diagnostic.ParseHTTPFormOptions(r) 418 419 // audit logs 420 logger := log.G(context.TODO()).WithFields(log.Fields{ 421 "component": "diagnostic", 422 "remoteIP": r.RemoteAddr, 423 "method": caller.Name(0), 424 "url": r.URL.String(), 425 }) 426 logger.Info("get table") 427 428 if len(r.Form["tname"]) < 1 || 429 len(r.Form["nid"]) < 1 { 430 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id", r.URL.Path)) 431 logger.Error("get table failed, wrong input") 432 diagnostic.HTTPReply(w, rsp, json) 433 return 434 } 435 436 tname := r.Form["tname"][0] 437 nid := r.Form["nid"][0] 438 439 nDB, ok := ctx.(*NetworkDB) 440 if ok { 441 table := nDB.GetTableByNetwork(tname, nid) 442 rsp := &diagnostic.TableObj{Length: len(table)} 443 i := 0 444 for k, v := range table { 445 var encodedValue string 446 if unsafe { 447 encodedValue = string(v.Value) 448 } else { 449 encodedValue = base64.StdEncoding.EncodeToString(v.Value) 450 } 451 rsp.Elements = append(rsp.Elements, 452 &diagnostic.TableEntryObj{ 453 Index: i, 454 Key: k, 455 Value: encodedValue, 456 Owner: v.owner, 457 }) 458 i++ 459 } 460 logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done") 461 diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json) 462 return 463 } 464 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 465 } 466 467 func dbNetworkStats(ctx interface{}, w http.ResponseWriter, r *http.Request) { 468 _ = r.ParseForm() 469 diagnostic.DebugHTTPForm(r) 470 _, json := diagnostic.ParseHTTPFormOptions(r) 471 472 // audit logs 473 logger := log.G(context.TODO()).WithFields(log.Fields{ 474 "component": "diagnostic", 475 "remoteIP": r.RemoteAddr, 476 "method": caller.Name(0), 477 "url": r.URL.String(), 478 }) 479 logger.Info("network stats") 480 481 if len(r.Form["nid"]) < 1 { 482 rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path)) 483 logger.Error("network stats failed, wrong input") 484 diagnostic.HTTPReply(w, rsp, json) 485 return 486 } 487 488 nDB, ok := ctx.(*NetworkDB) 489 if ok { 490 nDB.RLock() 491 networks := nDB.networks[nDB.config.NodeID] 492 network, ok := networks[r.Form["nid"][0]] 493 494 entries := -1 495 qLen := -1 496 if ok { 497 entries = int(network.entriesNumber.Load()) 498 qLen = network.tableBroadcasts.NumQueued() 499 } 500 nDB.RUnlock() 501 502 rsp := diagnostic.CommandSucceed(&diagnostic.NetworkStatsResult{Entries: entries, QueueLen: qLen}) 503 logger.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network stats done") 504 diagnostic.HTTPReply(w, rsp, json) 505 return 506 } 507 diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf(dbNotAvailable)), json) 508 }