github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/dashboards/dashboards.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package dashboards 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "os" 24 "strconv" 25 "strings" 26 "sync" 27 28 "github.com/google/uuid" 29 "github.com/valyala/fasthttp" 30 31 "github.com/siglens/siglens/pkg/blob" 32 "github.com/siglens/siglens/pkg/config" 33 "github.com/siglens/siglens/pkg/utils" 34 log "github.com/sirupsen/logrus" 35 ) 36 37 var allidsBaseFname string 38 var allDashIdsLock map[uint64]*sync.Mutex = make(map[uint64]*sync.Mutex) 39 var latestDashboardReadTimeMillis map[uint64]uint64 40 41 // map of "orgid" => "dashboardId" ==> "dashboardName" 42 // e.g. "1234567890" => "11812083241622924684" => "dashboard-1" 43 var allDashboardsIds map[uint64]map[string]string = make(map[uint64]map[string]string) 44 var allDashboardsIdsLock *sync.RWMutex = &sync.RWMutex{} 45 46 func readSavedDashboards(orgid uint64) ([]byte, error) { 47 var dashboardData []byte 48 allidsFname := getDashboardFileName(orgid) 49 _, err := os.Stat(allidsFname) 50 if err != nil { 51 if errors.Is(err, os.ErrNotExist) { 52 return nil, nil 53 } 54 } 55 56 dashboardData, err = os.ReadFile(allidsFname) 57 if err != nil { 58 if errors.Is(err, os.ErrNotExist) { 59 return nil, nil 60 } 61 log.Errorf("readSavedDashboards: Failed to read dashboard file fname=%v, err=%v", allidsFname, err) 62 return nil, err 63 } 64 65 allDashboardsIdsLock.Lock() 66 if _, ok := allDashboardsIds[orgid]; !ok { 67 allDashboardsIds[orgid] = make(map[string]string) 68 } 69 var dashboardDetails map[string]string 70 err = json.Unmarshal(dashboardData, &dashboardDetails) 71 if err != nil { 72 allDashboardsIdsLock.Unlock() 73 log.Errorf("readSavedDashboards: Failed to unmarshall dashboard file fname=%v, err=%v", allidsFname, err) 74 return nil, err 75 } 76 allDashboardsIds[orgid] = dashboardDetails 77 latestDashboardReadTimeMillis[orgid] = utils.GetCurrentTimeInMs() 78 allDashboardsIdsLock.Unlock() 79 return dashboardData, nil 80 } 81 82 func readSavedDefaultDashboards(orgid uint64) ([]byte, error) { 83 var dashboardData []byte 84 allidsFname := getDefaultDashboardFileName() 85 _, err := os.Stat(allidsFname) 86 if err != nil { 87 if errors.Is(err, os.ErrNotExist) { 88 return nil, nil 89 } 90 log.Errorf("readSavedDashboards: Failed to stat dashboard file fname=%v, err=%v", allidsFname, err) 91 return nil, err 92 } 93 94 dashboardData, err = os.ReadFile(allidsFname) 95 if err != nil { 96 if errors.Is(err, os.ErrNotExist) { 97 return nil, nil 98 } 99 log.Errorf("readSavedDashboards: Failed to read dashboard file fname=%v, err=%v", allidsFname, err) 100 return nil, err 101 } 102 103 allDashboardsIdsLock.Lock() 104 if _, ok := allDashboardsIds[orgid]; !ok { 105 allDashboardsIds[orgid] = make(map[string]string) 106 } 107 var dashboardDetails map[string]string 108 err = json.Unmarshal(dashboardData, &dashboardDetails) 109 if err != nil { 110 allDashboardsIdsLock.Unlock() 111 log.Errorf("readSavedDashboards: Failed to unmarshall dashboard file fname=%v, err=%v", allidsFname, err) 112 return nil, err 113 } 114 allDashboardsIds[orgid] = dashboardDetails 115 latestDashboardReadTimeMillis[orgid] = utils.GetCurrentTimeInMs() 116 allDashboardsIdsLock.Unlock() 117 return dashboardData, nil 118 } 119 120 func getDashboardFileName(orgid uint64) string { 121 var allidsFname string 122 if orgid == 0 { 123 allidsFname = allidsBaseFname + ".json" 124 } else { 125 allidsFname = allidsBaseFname + "-" + strconv.FormatUint(orgid, 10) + ".json" 126 } 127 return allidsFname 128 } 129 130 func getDefaultDashboardFileName() string { 131 var allidsFname string 132 var defaultDBsAllidsBaseFname string = "defaultDBs/allids" 133 allidsFname = defaultDBsAllidsBaseFname + ".json" 134 return allidsFname 135 } 136 137 func InitDashboards() error { 138 var sb strings.Builder 139 140 sb.WriteString(config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards") 141 baseDir := sb.String() 142 allidsBaseFname = baseDir + "/allids" 143 latestDashboardReadTimeMillis = make(map[uint64]uint64) 144 145 err := os.MkdirAll(baseDir, 0764) 146 if err != nil { 147 log.Errorf("InitDashboard: failed to create basedir=%v, err=%v", baseDir, err) 148 return err 149 } 150 151 err = os.MkdirAll(baseDir+"/details", 0764) 152 if err != nil { 153 log.Errorf("InitDashboard: failed to create basedir=%v, err=%v", baseDir, err) 154 return err 155 } 156 157 createOrAcquireLock(0) 158 _, err = readSavedDashboards(0) 159 if err != nil { 160 releaseLock(0) 161 log.Errorf("InitDashboard: failed to read saved dashboards, err=%v", err) 162 return err 163 } 164 releaseLock(0) 165 166 return nil 167 } 168 169 func createOrAcquireLock(orgid uint64) { 170 if _, ok := allDashIdsLock[orgid]; !ok { 171 allDashIdsLock[orgid] = &sync.Mutex{} 172 } 173 allDashIdsLock[orgid].Lock() 174 } 175 176 func releaseLock(orgid uint64) { 177 allDashIdsLock[orgid].Unlock() 178 } 179 180 func getAllDashboardIds(orgid uint64) (map[string]string, error) { 181 createOrAcquireLock(orgid) 182 _, err := readSavedDashboards(orgid) 183 if err != nil { 184 releaseLock(orgid) 185 log.Errorf("getAllDashboardIds: failed to read, err=%v", err) 186 return nil, err 187 } 188 releaseLock(orgid) 189 allDashboardsIdsLock.RLock() 190 defer allDashboardsIdsLock.RUnlock() 191 return allDashboardsIds[orgid], nil 192 } 193 194 func getAllDefaultDashboardIds(orgid uint64) (map[string]string, error) { 195 createOrAcquireLock(orgid) 196 _, err := readSavedDefaultDashboards(orgid) 197 if err != nil { 198 releaseLock(orgid) 199 log.Errorf("getAllDashboardIds: failed to read, err=%v", err) 200 return nil, err 201 } 202 releaseLock(orgid) 203 allDashboardsIdsLock.RLock() 204 defer allDashboardsIdsLock.RUnlock() 205 return allDashboardsIds[orgid], nil 206 } 207 208 // Generate the uniq uuid for the dashboard 209 func createUniqId(dname string) string { 210 newId := uuid.New().String() 211 return newId 212 } 213 214 // method to check if the dashboard name already exists 215 func dashboardNameExists(dname string, orgid uint64) bool { 216 allDashboardIds, err := getAllDashboardIds(orgid) 217 if err != nil { 218 log.Errorf("Error getting all dashboard IDs: %v", err) 219 return false 220 } 221 for _, name := range allDashboardIds { 222 if name == dname { 223 return true 224 } 225 } 226 return false 227 } 228 229 func createDashboard(dname string, orgid uint64) (map[string]string, error) { 230 if dname == "" { 231 log.Errorf("createDashboard: failed to create Dashboard, with empty dashboard name") 232 return nil, errors.New("createDashboard: failed to create Dashboard, with empty dashboard name") 233 } 234 235 newId := createUniqId(dname) 236 237 if dashboardNameExists(dname, orgid) { 238 log.Errorf("Dashboard with name %s already exists", dname) 239 return nil, errors.New("dashboard name already exists") 240 } 241 242 dashBoardIds, err := getAllDashboardIds(orgid) 243 if err != nil { 244 log.Errorf("createDashboard: Failed to get all dashboard ids err=%v", err) 245 return nil, err 246 } 247 for _, dId := range dashBoardIds { 248 if dId == newId { 249 log.Errorf("createDashboard: Failed to create dashboard, dashboard id already exists=%v", dname) 250 return nil, errors.New("createDashboard: Failed to create dashboard, dashboard id already exists") 251 } 252 } 253 254 allDashboardsIdsLock.Lock() 255 if _, ok := allDashboardsIds[orgid]; !ok { 256 allDashboardsIds[orgid] = make(map[string]string) 257 } 258 allDashboardsIds[orgid][newId] = dname 259 orgDashboards := allDashboardsIds[orgid] 260 jdata, err := json.Marshal(&orgDashboards) 261 allDashboardsIdsLock.Unlock() 262 if err != nil { 263 log.Errorf("createDashboard: Failed to marshall err=%v", err) 264 return nil, err 265 } 266 267 allidsFname := getDashboardFileName(orgid) 268 err = os.WriteFile(allidsFname, jdata, 0644) 269 if err != nil { 270 log.Errorf("createDashboard: Failed to write file=%v, err=%v", allidsFname, err) 271 return nil, err 272 } 273 274 dashboardDetailsFname := config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + newId + ".json" 275 276 err = os.WriteFile(dashboardDetailsFname, []byte("{}"), 0644) 277 if err != nil { 278 log.Errorf("createDashboard: Error creating empty local file %s: %v", dashboardDetailsFname, err) 279 return nil, err 280 } 281 282 log.Infof("createDashboard: Successfully created file %v", dashboardDetailsFname) 283 err = blob.UploadQueryNodeDir() 284 if err != nil { 285 log.Errorf("createDashboard: Failed to upload query nodes dir err=%v", err) 286 return nil, err 287 } 288 289 retval := make(map[string]string) 290 allDashboardsIdsLock.RLock() 291 orgDashboardsIds := allDashboardsIds[orgid] 292 allDashboardsIdsLock.RUnlock() 293 for k, v := range orgDashboardsIds { 294 if k == newId { 295 retval[k] = v 296 break 297 } 298 } 299 300 return retval, nil 301 } 302 303 func dashboardIsDefault(id string) bool { 304 defaultIds := []string{ 305 "10329b95-47a8-48df-8b1d-0a0a01ec6c42", 306 "a28f485c-4747-4024-bb6b-d230f101f852", 307 "bd74f11e-26c8-4827-bf65-c0b464e1f2a4", 308 "53cb3dde-fd78-4253-808c-18e4077ef0f1", 309 } 310 311 for _, defaultId := range defaultIds { 312 if id == defaultId { 313 return true 314 } 315 } 316 317 return false 318 } 319 320 func toggleFavorite(id string) (bool, error) { 321 // Load the dashboard JSON file 322 var dashboardDetailsFname string 323 if dashboardIsDefault(id) { 324 dashboardDetailsFname = "defaultDBs/details/" + id + ".json" 325 } else { 326 dashboardDetailsFname = config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + id + ".json" 327 } 328 dashboardJson, err := os.ReadFile(dashboardDetailsFname) 329 if err != nil { 330 log.Errorf("toggleFavorite: Failed to read file=%v, err=%v", dashboardDetailsFname, err) 331 return false, err 332 } 333 334 // Unmarshal JSON file into a map 335 var dashboard map[string]interface{} 336 err = json.Unmarshal(dashboardJson, &dashboard) 337 if err != nil { 338 log.Errorf("toggleFavorite: Failed to unmarshal json, err=%v", err) 339 return false, err 340 } 341 342 // Toggle the "isFavorite" field 343 isFavorite, ok := dashboard["isFavorite"].(bool) 344 if !ok { 345 // If the "isFavorite" field does not exist or is not a bool, treat the dashboard as not favorited 346 isFavorite = false 347 } 348 dashboard["isFavorite"] = !isFavorite 349 350 // Marshal the updated dashboard back into JSON 351 updatedDashboardJson, err := json.Marshal(dashboard) 352 if err != nil { 353 log.Errorf("toggleFavorite: Failed to marshal json, err=%v", err) 354 return false, err 355 } 356 357 // Save the updated dashboard back to the JSON file 358 err = os.WriteFile(dashboardDetailsFname, updatedDashboardJson, 0644) 359 if err != nil { 360 log.Errorf("toggleFavorite: Failed to write file=%v, err=%v", dashboardDetailsFname, err) 361 return false, err 362 } 363 364 return !isFavorite, nil 365 } 366 func getDashboard(id string) (map[string]interface{}, error) { 367 var dashboardDetailsFname string 368 if dashboardIsDefault(id) { 369 dashboardDetailsFname = "defaultDBs/details/" + id + ".json" 370 } else { 371 dashboardDetailsFname = config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + id + ".json" 372 } 373 rdata, err := os.ReadFile(dashboardDetailsFname) 374 if err != nil { 375 if errors.Is(err, os.ErrNotExist) { 376 return nil, err 377 } 378 log.Errorf("getDashboard: Failed to read dashboard file fname=%v, err=%v", dashboardDetailsFname, err) 379 return nil, err 380 } 381 382 var detailDashboardInfo map[string]interface{} = make(map[string]interface{}) 383 384 err = json.Unmarshal(rdata, &detailDashboardInfo) 385 if err != nil { 386 log.Errorf("getDashboard: Failed to unmarshall dashboard file fname=%v, err=%v", dashboardDetailsFname, err) 387 return nil, err 388 } 389 390 retval := detailDashboardInfo 391 return retval, nil 392 } 393 394 func updateDashboard(id string, dName string, dashboardDetails map[string]interface{}, orgid uint64) error { 395 396 // Check if the dashboard exists 397 allDashboards, err := getAllDashboardIds(orgid) 398 if err != nil { 399 log.Errorf("updateDashboard: Failed to get all dashboard ids err=%v", err) 400 return err 401 } 402 _, ok := allDashboards[id] 403 if !ok { 404 log.Errorf("updateDashboard: Dashboard id %v does not exist", id) 405 return errors.New("updateDashboard: Dashboard id does not exist") 406 } 407 408 currentDashboardDetails, err := getDashboard(id) 409 if err != nil { 410 log.Errorf("ProcessGetDashboardRequest: could not get Dashboard=%v, err=%v", id, err) 411 return errors.New("updateDashboard: Error fetching dashboard details") 412 } 413 414 // Check if isFavorite is provided in the update 415 if _, exists := currentDashboardDetails["isFavorite"]; !exists { 416 // If isFavorite does not exist in currentDashboardDetails, set it to false 417 dashboardDetails["isFavorite"] = false 418 currentDashboardDetails["isFavorite"] = false 419 } else if _, ok := dashboardDetails["isFavorite"].(bool); !ok { 420 // If isFavorite is not provided in the update, keep the current value 421 dashboardDetails["isFavorite"] = currentDashboardDetails["isFavorite"] 422 } 423 // Update the dashboard name if it is different 424 if allDashboards[id] != dName { 425 if dashboardNameExists(dName, orgid) { 426 log.Errorf("Dashboard with name %s already exists", dName) 427 return errors.New("dashboard name already exists") 428 } else { 429 allDashboardsIds[orgid][id] = dName 430 } 431 } 432 allDashboardsIdsLock.RLock() 433 orgDashboards := allDashboardsIds[orgid] 434 allDashboardsIdsLock.RUnlock() 435 jdata, err := json.Marshal(&orgDashboards) 436 if err != nil { 437 log.Errorf("updateDashboard: Failed to marshall err=%v", err) 438 return err 439 } 440 441 allidsFname := getDashboardFileName(orgid) 442 err = os.WriteFile(allidsFname, jdata, 0644) 443 if err != nil { 444 log.Errorf("updateDashboard: Failed to write file=%v, err=%v", allidsFname, err) 445 return err 446 } 447 448 dashboardDetailsFname := config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + id + ".json" 449 450 jdata, err = json.Marshal(&dashboardDetails) 451 if err != nil { 452 log.Errorf("updateDashboard: Failed to marshall err=%v", err) 453 return err 454 } 455 456 err = os.WriteFile(dashboardDetailsFname, jdata, 0644) 457 if err != nil { 458 log.Errorf("updateDashboard: Failed to writefile fullname=%v, err=%v", dashboardDetailsFname, err) 459 return err 460 } 461 log.Infof("updateDashboard: Successfully updated dashboard details in file %v", dashboardDetailsFname) 462 463 // Update the query node dir 464 err = blob.UploadQueryNodeDir() 465 if err != nil { 466 log.Errorf("updateDashboard: Failed to upload query nodes dir err=%v", err) 467 return err 468 } 469 470 return nil 471 } 472 473 func deleteDashboard(id string, orgid uint64) error { 474 475 createOrAcquireLock(orgid) 476 dashboardData, err := readSavedDashboards(orgid) 477 if err != nil { 478 releaseLock(orgid) 479 log.Errorf("deleteDashboard: failed to read saved dashboards, err=%v", err) 480 return err 481 } 482 releaseLock(orgid) 483 484 var dashboardDetails map[string]string 485 err = json.Unmarshal(dashboardData, &dashboardDetails) 486 if err != nil { 487 log.Errorf("deleteDashboard: Failed to unmarshall dashboard file for orgid=%v, err=%v", orgid, err) 488 return err 489 } 490 491 // Delete entry from dashboardInfo and write to file allids.json 492 allDashboardsIdsLock.Lock() 493 delete(allDashboardsIds[orgid], id) 494 allDashboardsIdsLock.Unlock() 495 496 // Update the file with latest dashboard info 497 allDashboardsIdsLock.RLock() 498 orgDashboardIds := allDashboardsIds[orgid] 499 allDashboardsIdsLock.RUnlock() 500 jdata, err := json.Marshal(&orgDashboardIds) 501 if err != nil { 502 log.Errorf("deleteDashboard: Failed to marshall err=%v", err) 503 return err 504 } 505 506 allidsFname := getDashboardFileName(orgid) 507 err = os.WriteFile(allidsFname, jdata, 0644) 508 if err != nil { 509 log.Errorf("deleteDashboard: Failed to write file=%v, err=%v", allidsFname, err) 510 return err 511 } 512 513 // Delete dashboard details file 514 dashboardDetailsFname := config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + id + ".json" 515 err = os.Remove(dashboardDetailsFname) 516 if err != nil { 517 log.Errorf("deleteDashboard: Error deleting file %s: %v", dashboardDetailsFname, err) 518 return err 519 } 520 521 // Update the query node dir 522 err = blob.UploadQueryNodeDir() 523 if err != nil { 524 log.Errorf("deleteDashboard: Failed to upload query nodes dir err=%v", err) 525 return err 526 } 527 528 return nil 529 } 530 531 // method to set conflict message and 409 status code 532 func setConflictMsg(ctx *fasthttp.RequestCtx) { 533 var httpResp utils.HttpServerResponse 534 ctx.SetStatusCode(fasthttp.StatusConflict) 535 httpResp.Message = "Conflict: Dashboard name already exists" 536 httpResp.StatusCode = fasthttp.StatusConflict 537 utils.WriteResponse(ctx, httpResp) 538 } 539 540 func ProcessCreateDashboardRequest(ctx *fasthttp.RequestCtx, myid uint64) { 541 rawJSON := ctx.PostBody() 542 if rawJSON == nil { 543 log.Errorf("ProcessCreateDashboardRequest: received empty user query") 544 utils.SetBadMsg(ctx, "") 545 return 546 } 547 548 var dname string 549 550 err := json.Unmarshal(rawJSON, &dname) 551 if err != nil { 552 log.Errorf("ProcessCreateDashboardRequest: could not unmarshall user query, err=%v", err) 553 utils.SetBadMsg(ctx, "") 554 return 555 } 556 dashboardInfo, err := createDashboard(dname, myid) 557 558 if err != nil { 559 if err.Error() == "dashboard name already exists" { 560 setConflictMsg(ctx) 561 return 562 } else { 563 log.Errorf("ProcessCreateDashboardRequest: could not create Dashboard=%v, err=%v", dname, err) 564 utils.SetBadMsg(ctx, "") 565 return 566 } 567 } 568 569 utils.WriteJsonResponse(ctx, dashboardInfo) 570 ctx.SetStatusCode(fasthttp.StatusOK) 571 } 572 573 func ProcessFavoriteRequest(ctx *fasthttp.RequestCtx) { 574 dId := utils.ExtractParamAsString(ctx.UserValue("dashboard-id")) 575 if dId == "" { 576 log.Errorf("ProcessFavoriteRequest: received empty dashboard id") 577 utils.SetBadMsg(ctx, "") 578 return 579 } 580 581 isFavorite, err := toggleFavorite(dId) 582 if err != nil { 583 log.Errorf("ProcessFavoriteRequest: could not toggle favorite status for Dashboard=%v, err=%v", dId, err) 584 utils.SetBadMsg(ctx, "") 585 return 586 } 587 588 response := map[string]bool{"isFavorite": isFavorite} 589 utils.WriteJsonResponse(ctx, response) 590 ctx.SetStatusCode(fasthttp.StatusOK) 591 } 592 593 func ProcessListFavoritesRequest(ctx *fasthttp.RequestCtx, myid uint64) { 594 dIds, err := getAllFavoriteDashboardIds(myid) 595 596 if err != nil { 597 log.Errorf("ProcessListFavoritesRequest: could not get favorite dashboard ids, err=%v", err) 598 utils.SetBadMsg(ctx, "") 599 return 600 } 601 utils.WriteJsonResponse(ctx, dIds) 602 ctx.SetStatusCode(fasthttp.StatusOK) 603 } 604 605 func getAllFavoriteDashboardIds(orgId uint64) (map[string]string, error) { 606 allDashboards, err := getAllDashboardIds(orgId) 607 if err != nil { 608 return nil, err 609 } 610 611 favoriteDashboards := make(map[string]string) 612 for id, name := range allDashboards { 613 isFavorite, err := isDashboardFavorite(id) 614 if err != nil { 615 return nil, err 616 } 617 618 if isFavorite { 619 favoriteDashboards[id] = name 620 } 621 } 622 623 return favoriteDashboards, nil 624 } 625 626 func isDashboardFavorite(id string) (bool, error) { 627 var dashboardDetailsFname string 628 629 if dashboardIsDefault(id) { 630 dashboardDetailsFname = "defaultDBs/details/" + id + ".json" 631 } else { 632 dashboardDetailsFname = config.GetDataPath() + "querynodes/" + config.GetHostID() + "/dashboards/details/" + id + ".json" 633 } 634 635 dashboardJson, err := os.ReadFile(dashboardDetailsFname) 636 if err != nil { 637 return false, err 638 } 639 640 var dashboard map[string]interface{} 641 err = json.Unmarshal(dashboardJson, &dashboard) 642 if err != nil { 643 log.Errorf("isDashboardFavorite: Failed to unmarshal json, err=%v", err) 644 return false, err 645 } 646 647 isFav, ok := dashboard["isFavorite"].(bool) 648 if !ok { 649 isFav = false 650 } 651 652 return isFav, nil 653 } 654 655 func ProcessListAllRequest(ctx *fasthttp.RequestCtx, myid uint64) { 656 dIds, err := getAllDashboardIds(myid) 657 658 if err != nil { 659 log.Errorf("ProcessListAllRequest: could not get dashboard ids, err=%v", err) 660 utils.SetBadMsg(ctx, "") 661 return 662 } 663 utils.WriteJsonResponse(ctx, dIds) 664 ctx.SetStatusCode(fasthttp.StatusOK) 665 } 666 667 func ProcessListAllDefaultDBRequest(ctx *fasthttp.RequestCtx, myid uint64) { 668 dIds, err := getAllDefaultDashboardIds(myid) 669 670 if err != nil { 671 log.Errorf("ProcessListAllRequest: could not get dashboard ids, err=%v", err) 672 utils.SetBadMsg(ctx, "") 673 return 674 } 675 utils.WriteJsonResponse(ctx, dIds) 676 ctx.SetStatusCode(fasthttp.StatusOK) 677 } 678 679 func ProcessUpdateDashboardRequest(ctx *fasthttp.RequestCtx, myid uint64) { 680 rawJSON := ctx.PostBody() 681 if rawJSON == nil { 682 log.Errorf("ProcessCreateDashboardRequest: received empty user query") 683 utils.SetBadMsg(ctx, "") 684 return 685 } 686 687 readJSON := make(map[string]interface{}) 688 689 err := json.Unmarshal(rawJSON, &readJSON) 690 if err != nil { 691 log.Errorf("ProcessCreateDashboardRequest: could not unmarshall user query, err=%v", err) 692 utils.SetBadMsg(ctx, "") 693 return 694 } 695 696 dId := readJSON["id"].(string) 697 dName := readJSON["name"].(string) 698 dashboardDetails := readJSON["details"].(map[string]interface{}) 699 err = updateDashboard(dId, dName, dashboardDetails, myid) 700 if err != nil { 701 if err.Error() == "dashboard name already exists" { 702 setConflictMsg(ctx) 703 return 704 } else { 705 log.Errorf("ProcessCreateDashboardRequest: could not create Dashboard=%v, err=%v", dId, err) 706 utils.SetBadMsg(ctx, "") 707 return 708 } 709 } 710 response := "Dashboard updated successfully" 711 utils.WriteJsonResponse(ctx, response) 712 ctx.SetStatusCode(fasthttp.StatusOK) 713 } 714 715 func ProcessGetDashboardRequest(ctx *fasthttp.RequestCtx) { 716 dId := utils.ExtractParamAsString(ctx.UserValue("dashboard-id")) 717 dashboardDetails, err := getDashboard(dId) 718 if err != nil { 719 log.Errorf("ProcessGetDashboardRequest: could not get Dashboard=%v, err=%v", dId, err) 720 utils.SetBadMsg(ctx, "") 721 return 722 } 723 utils.WriteJsonResponse(ctx, dashboardDetails) 724 ctx.SetStatusCode(fasthttp.StatusOK) 725 } 726 727 func ProcessDeleteDashboardRequest(ctx *fasthttp.RequestCtx, myid uint64) { 728 dId := utils.ExtractParamAsString(ctx.UserValue("dashboard-id")) 729 err := deleteDashboard(dId, myid) 730 if err != nil { 731 log.Errorf("ProcessDeleteDashboardRequest: Failed to delete dashboard=%v, err=%v", dId, err) 732 utils.SetBadMsg(ctx, "") 733 return 734 } 735 736 log.Infof("ProcessDeleteDashboardRequest: Successfully deleted dashboard %v", dId) 737 err = blob.UploadQueryNodeDir() 738 if err != nil { 739 log.Errorf("ProcessDeleteDashboardRequest: Failed to upload query nodes dir err=%v", err) 740 return 741 } 742 response := "Dashboard deleted successfully" 743 utils.WriteJsonResponse(ctx, response) 744 ctx.SetStatusCode(fasthttp.StatusOK) 745 } 746 747 func ProcessDeleteDashboardsByOrgId(orgid uint64) error { 748 dIds, err := getAllDashboardIds(orgid) 749 if err != nil { 750 log.Errorf("ProcessDeleteDashboardsByOrgId: Failed to get all dashboard ids err=%v", err) 751 return err 752 } 753 for dId := range dIds { 754 err = deleteDashboard(dId, orgid) 755 if err != nil { 756 log.Errorf("ProcessDeleteDashboardsByOrgId: Failed to delete dashboard=%v, err=%v", dId, err) 757 } 758 759 log.Infof("ProcessDeleteDashboardsByOrgId: Successfully deleted dashboard %v", dId) 760 err = blob.UploadQueryNodeDir() 761 if err != nil { 762 log.Errorf("ProcessDeleteDashboardsByOrgId: Failed to upload query nodes dir, err=%v", err) 763 // Move on to the next dashboard for now 764 } 765 } 766 767 dashboardAllIdsFilename := config.GetDataPath() + "querynodes/" + config.GetHostname() + "/dashboards/allids-" + fmt.Sprint(orgid) + ".json" 768 769 err = os.Remove(dashboardAllIdsFilename) 770 if err != nil { 771 log.Warnf("ProcessDeleteDashboardsByOrgId: Failed to delete the dashboard allids file: %v", dashboardAllIdsFilename) 772 } 773 return nil 774 }