From 076d378adca18607df4cb39aacfada4b195631c8 Mon Sep 17 00:00:00 2001 From: Renato Costa <103441181+renatolabs@users.noreply.github.com> Date: Tue, 25 Nov 2025 13:38:26 -0500 Subject: [PATCH] fix: update search request for existing provisioned dashboards in modes 3+ (#114412) Fix search for existing provisioned dashboards in modes 3+ The search query was not requesting the dashboard's "legacy ID". As a result, the provisioning process would not find existing provisioned dashboards, making copies of these dashboards every time there was a change in the provisioned dashboard's definition. Signed-off-by: Maicon Costa --- pkg/extensions/enterprise_imports.go | 6 +++--- .../dashboards/service/dashboard_service.go | 9 ++++++++- .../service/dashboard_service_test.go | 20 +++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/pkg/extensions/enterprise_imports.go b/pkg/extensions/enterprise_imports.go index 472652cc103..113c2f8e4bb 100644 --- a/pkg/extensions/enterprise_imports.go +++ b/pkg/extensions/enterprise_imports.go @@ -15,7 +15,6 @@ import ( _ "github.com/blugelabs/bluge" _ "github.com/blugelabs/bluge_segment_api" _ "github.com/crewjam/saml" - _ "github.com/docker/go-connections/nat" _ "github.com/go-jose/go-jose/v4" _ "github.com/gobwas/glob" _ "github.com/googleapis/gax-go/v2" @@ -31,7 +30,6 @@ import ( _ "github.com/spf13/cobra" // used by the standalone apiserver cli _ "github.com/spyzhov/ajson" _ "github.com/stretchr/testify/require" - _ "github.com/testcontainers/testcontainers-go" _ "gocloud.dev/secrets/awskms" _ "gocloud.dev/secrets/azurekeyvault" _ "gocloud.dev/secrets/gcpkms" @@ -56,7 +54,9 @@ import ( _ "github.com/grafana/e2e" _ "github.com/grafana/gofpdf" _ "github.com/grafana/gomemcache/memcache" + _ "github.com/grafana/tempo/pkg/traceql" + _ "github.com/grafana/grafana/apps/alerting/alertenrichment/pkg/apis/alertenrichment/v1beta1" _ "github.com/grafana/grafana/apps/scope/pkg/apis/scope/v0alpha1" - _ "github.com/grafana/tempo/pkg/traceql" + _ "github.com/testcontainers/testcontainers-go" ) diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index ebf3f24beb6..fa5575d1d35 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -2009,7 +2009,14 @@ func (dr *DashboardServiceImpl) searchDashboardsThroughK8sRaw(ctx context.Contex request.Limit = query.Limit request.Page = query.Page request.Offset = (query.Page - 1) * query.Limit // only relevant when running in modes 3+ - request.Fields = dashboardsearch.IncludeFields + request.Fields = append( + dashboardsearch.IncludeFields, + // Include the dashboard legacy ID in the results, as it is needed when + // determining whether a provisioned dashboard exists or not, see + // `(*DashboardServiceImpl).searchProvisionedDashboardsThroughK8s`. + resource.SEARCH_FIELD_LEGACY_ID, + resource.SEARCH_FIELD_LABELS+"."+resource.SEARCH_FIELD_LEGACY_ID, + ) namespace := dr.k8sclient.GetNamespace(query.OrgId) var err error diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index 7aa0e07762c..464e47ae1bc 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -2016,6 +2016,26 @@ func TestSearchDashboardsThroughK8sRaw(t *testing.T) { _, err := service.searchDashboardsThroughK8s(ctx, query) require.NoError(t, err) }) + + t.Run("search will request legacy dashboard ID", func(t *testing.T) { + ctx := context.Background() + k8sCliMock := new(client.MockK8sHandler) + service := &DashboardServiceImpl{k8sclient: k8sCliMock} + query := &dashboards.FindPersistedDashboardsQuery{ + ManagedBy: utils.ManagerKindClassicFP, //nolint:staticcheck + OrgId: 1, + } + k8sCliMock.On("GetNamespace", mock.Anything, mock.Anything).Return("default") + k8sCliMock.On("Search", mock.Anything, mock.Anything, mock.MatchedBy(func(req *resourcepb.ResourceSearchRequest) bool { + return slices.Contains(req.Fields, "grafana.app/deprecatedInternalID") && + slices.Contains(req.Fields, "labels.grafana.app/deprecatedInternalID") + })).Return(&resourcepb.ResourceSearchResponse{ + Results: &resourcepb.ResourceTable{}, + TotalHits: 0, + }, nil) + _, err := service.searchDashboardsThroughK8s(ctx, query) + require.NoError(t, err) + }) } func TestSearchProvisionedDashboardsThroughK8sRaw(t *testing.T) {