From 52ed9c650154ad0188ee3edfb7d6c58dcba998ec Mon Sep 17 00:00:00 2001 From: Samir F Date: Thu, 16 Jan 2025 12:54:07 -0500 Subject: [PATCH] Updating behavior or dashboard to not be so intrusive. (#337) Fixes #296 Previous behavior: 1. Delete all monitored dashboards 2. Upload all dashboards from backup. New Behavior: 1. Upload all dashboards from backup overwriting existing Dashboards. 2. Delete any dashboards that exists in grafana but are missing from backup. --- internal/service/dashboards.go | 28 +++++++++++++++++++++--- test/connections_integration_test.go | 3 --- test/dashboard_integration_test.go | 17 -------------- test/folder_integration_test.go | 3 --- test/libraryelements_integration_test.go | 4 ---- test/organizations_integration_test.go | 9 -------- test/team_integration_test.go | 3 --- website/content/docs/releases/gdg_0.7.md | 10 +++++++-- 8 files changed, 33 insertions(+), 44 deletions(-) diff --git a/internal/service/dashboards.go b/internal/service/dashboards.go index cd823bdc..26633ae1 100644 --- a/internal/service/dashboards.go +++ b/internal/service/dashboards.go @@ -526,8 +526,7 @@ func (s *DashNGoImpl) UploadDashboards(filterReq filters.Filter) error { } - // Delete all dashboards that match prior to import - s.DeleteAllDashboards(filterReq) + currentDashboards := s.ListDashboards(filterReq) folderUidMap := s.getFolderNameUIDMap(s.ListFolders(NewFolderFilter())) @@ -641,9 +640,32 @@ func (s *DashNGoImpl) UploadDashboards(filterReq filters.Filter) error { } } + + for _, item := range currentDashboards { + if ok := alreadyProcessed[item.UID]; !ok { + slog.Info("Deleting Dashboard not found in backup", "folder", item.FolderTitle, "dashboard", item.Title) + err := s.deleteDashboard(item) + if err != nil { + slog.Error("Unable to delete dashboard", "folder", item.FolderTitle, "dashboard", item.Title) + } + } + } return nil } +// deleteDashboard removes a dashboard from grafana. If the dashboard doesn't exist, +// an error is returned. +// +// Parameters: +// item - dashboard to be deleted +// +// Returns: +// error - error returned from the grafana API +func (s *DashNGoImpl) deleteDashboard(item *models.Hit) error { + _, err := s.GetClient().Dashboards.DeleteDashboardByUID(item.UID) + return err +} + // DeleteAllDashboards clears all current dashboards being monitored. Any folder not white listed // will not be affected func (s *DashNGoImpl) DeleteAllDashboards(filter filters.Filter) []string { @@ -652,7 +674,7 @@ func (s *DashNGoImpl) DeleteAllDashboards(filter filters.Filter) []string { items := s.ListDashboards(filter) for _, item := range items { if filter.ValidateAll(map[filters.FilterType]string{filters.FolderFilter: item.FolderTitle, filters.DashFilter: item.Slug}) { - _, err := s.GetClient().Dashboards.DeleteDashboardByUID(item.UID) + err := s.deleteDashboard(item) if err == nil { dashboardListing = append(dashboardListing, item.Title) } else { diff --git a/test/connections_integration_test.go b/test/connections_integration_test.go index 7badc1c3..0fd156bd 100644 --- a/test/connections_integration_test.go +++ b/test/connections_integration_test.go @@ -141,9 +141,6 @@ func TestConnectionsCRUD(t *testing.T) { // TestConnectionFilter ensures the regex matching and datasource type filters work as expected func TestConnectionFilter(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } _, _, _, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer func() { cleanErr := cleanup() diff --git a/test/dashboard_integration_test.go b/test/dashboard_integration_test.go index c3abef9e..054c42d0 100644 --- a/test/dashboard_integration_test.go +++ b/test/dashboard_integration_test.go @@ -90,9 +90,6 @@ func TestDashboardNestedFolderCRUD(t *testing.T) { } func TestDashboardCRUD(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } config.InitGdgConfig("testing") apiClient, _, cleanup := test_tooling.InitTest(t, service.DefaultConfigProvider, nil) defer func() { @@ -151,10 +148,6 @@ func TestDashboardCRUD(t *testing.T) { // If a duplicate file with the same UID exists, the upload should fail. Having a cleanup flag turned on, should // fix that issue. func TestDashboardCleanUpCrud(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - config.InitGdgConfig("testing") cfgProvider := func() *config.Configuration { cfg := config.Config() @@ -196,9 +189,6 @@ func TestDashboardCleanUpCrud(t *testing.T) { } func TestDashboardCRUDTags(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } apiClient, _, container, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer func() { err := cleanup() @@ -260,9 +250,6 @@ func TestDashboardCRUDTags(t *testing.T) { } func TestDashboardTagsFilter(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } apiClient, _, _, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer cleanup() emptyFilter := filters.NewBaseFilter() @@ -365,10 +352,6 @@ func TestDashboardPermissionsCrud(t *testing.T) { } func TestWildcardFilter(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - // Setup Filters apiClient, _, _, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer cleanup() diff --git a/test/folder_integration_test.go b/test/folder_integration_test.go index b7371da9..e385e9f5 100644 --- a/test/folder_integration_test.go +++ b/test/folder_integration_test.go @@ -24,9 +24,6 @@ import ( ) func TestFolderCRUD(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } apiClient, _, _, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer cleanup() slog.Info("Exporting all folders") diff --git a/test/libraryelements_integration_test.go b/test/libraryelements_integration_test.go index 5a2d0b08..6e352951 100644 --- a/test/libraryelements_integration_test.go +++ b/test/libraryelements_integration_test.go @@ -12,10 +12,6 @@ import ( ) func TestLibraryElementsCRUD(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - apiClient, _, _, cleanup := test_tooling.InitTestLegacy(t, nil, nil) defer cleanup() filtersEntity := service.NewDashboardFilter("", "", "") diff --git a/test/organizations_integration_test.go b/test/organizations_integration_test.go index 0044c62b..a06139d5 100644 --- a/test/organizations_integration_test.go +++ b/test/organizations_integration_test.go @@ -15,9 +15,6 @@ import ( ) func TestOrganizationCrud(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } if os.Getenv("TEST_TOKEN_CONFIG") == "1" { t.Skip("Skipping Token configuration, Organization CRUD requires Basic SecureData") } @@ -40,9 +37,6 @@ func TestOrganizationCrud(t *testing.T) { } func TestOrganizationUserMembership(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } if os.Getenv(test_tooling.EnableTokenTestsEnv) == "1" { t.Skip("Skipping Token configuration, Organization CRUD requires Basic SecureData") } @@ -93,9 +87,6 @@ func TestOrganizationUserMembership(t *testing.T) { } func TestOrganizationProperties(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } if os.Getenv(test_tooling.EnableTokenTestsEnv) == "1" { t.Skip("Skipping Token configuration, Organization CRUD requires Basic SecureData") } diff --git a/test/team_integration_test.go b/test/team_integration_test.go index 1a69b29e..2d9d670d 100644 --- a/test/team_integration_test.go +++ b/test/team_integration_test.go @@ -14,9 +14,6 @@ import ( ) func TestTeamCRUD(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } if os.Getenv("TEST_TOKEN_CONFIG") == "1" { t.Skip("Skipping Token configuration, Team and User CRUD requires Basic SecureData") } diff --git a/website/content/docs/releases/gdg_0.7.md b/website/content/docs/releases/gdg_0.7.md index 7b575d7e..1c540641 100644 --- a/website/content/docs/releases/gdg_0.7.md +++ b/website/content/docs/releases/gdg_0.7.md @@ -10,7 +10,7 @@ toc: true ## Release Notes for v0.7.2 -**Release Date: TBD** +**Release Date: 01/17/2025** ### Breaking Changes - [#318](https://github.com/esnet/gdg/pull/318) Only affects those with no valid configuration present. Removed the default @@ -18,9 +18,10 @@ toc: true which will print an example configuration to stdout. ### Feature Changes - [#319](https://github.com/esnet/gdg/pull/319) Remove the requirement for GF_FEATURE_TOGGLES_ENABLE for nested folder as it was incorrectly required in 0.7.1 - - [#302](https://github.com/esnet/gdg/pull/302) Adding Contact Points support. + - [#302](https://github.com/esnet/gdg/pull/302) Adding Alerting Contact Points support. (Beta Feature, API/format may change in the next release) - [#303](https://github.com/esnet/gdg/pull/303) Cleaning up Permission based listings. (Visualization) - [#274](https://github.com/esnet/gdg/pull/274) Adding Dashboard Permissions, enterprise feature. + - [#337](https://github.com/esnet/gdg/pull/337) Fix to maintain UIDs when updating dashboards - [#324](https://github.com/esnet/gdg/pull/324) Introducing a new config option to disregard bad folders Example: @@ -28,12 +29,17 @@ Example: dashboard_settings: ignore_bad_folders: true ``` +### Bug Fixes + - [#330](https://github.com/esnet/gdg/pull/330) Fix bug with leading prefix in path when using cloud storage + - [#333](https://github.com/esnet/gdg/pull/333) Fix bug with documentation search + - [#314](https://github.com/esnet/gdg/pull/314) Update README to reflected newly supported features ### Security Fixes / Technical Debt - [#326](https://github.com/esnet/gdg/pull/326) Bump golang.org/x/crypto from 0.28.0 to 0.31.0 - [#327](https://github.com/esnet/gdg/pull/327) Security Fix: Non-linear parsing of case-insensitive content in net/html - [#328](https://github.com/esnet/gdg/pull/328) Security: Fixing NPM security issues. #328 - [320](https://github.com/esnet/gdg/pull/320) Changed default branch from `master` to `main` + - [332](https://github.com/esnet/gdg/pull/332) Added a VHS tape to programmatically re-generate quickstart.gif ## Release Notes for v0.7.1