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