diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 8f4953d2723..d56118429d2 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -23,6 +23,7 @@ import ( claims "github.com/grafana/authlib/types" "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1" @@ -1248,16 +1249,31 @@ func (dr *DashboardServiceImpl) FindDashboards(ctx context.Context, query *dashb } finalResults := make([]dashboards.DashboardSearchProjection, len(response.Hits)) + // Create a small runtime cache for folders to avoid extra calls to the folder service + foldersMap := make(map[string]*folder.Folder) for i, hit := range response.Hits { + f, ok := foldersMap[hit.Folder] + if !ok { + f, err = dr.folderService.Get(ctx, &folder.GetFolderQuery{ + UID: &hit.Folder, + OrgID: query.OrgId, + SignedInUser: query.SignedInUser, + }) + if err != nil { + return nil, err + } + foldersMap[hit.Folder] = f + } finalResults[i] = dashboards.DashboardSearchProjection{ - ID: hit.Field.GetNestedInt64(search.DASHBOARD_LEGACY_ID), - UID: hit.Name, - OrgID: query.OrgId, - Title: hit.Title, - Slug: slugify.Slugify(hit.Title), - IsFolder: false, - FolderUID: hit.Folder, - Tags: hit.Tags, + ID: hit.Field.GetNestedInt64(search.DASHBOARD_LEGACY_ID), + UID: hit.Name, + OrgID: query.OrgId, + Title: hit.Title, + Slug: slugify.Slugify(hit.Title), + IsFolder: false, + FolderUID: hit.Folder, + FolderTitle: f.Title, + Tags: hit.Tags, } } diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index d7adcd9ad9a..1ae6c4f5b90 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -10,6 +10,9 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/components/simplejson" @@ -28,8 +31,6 @@ import ( "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/storage/unified/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) func TestDashboardService(t *testing.T) { @@ -71,10 +72,10 @@ func TestDashboardService(t *testing.T) { t.Run("Should return validation error if message is too long", func(t *testing.T) { dto.Dashboard = dashboards.NewDashboard("Dash") dto.Message = `Here we go, 500+ characters for testing. I'm sorry that you're - having to read this. I spent too long trying to come up with something clever + having to read this. I spent too long trying to come up with something clever to say or a funny joke. Unforuntately, nothing came to mind. So instead, I'm will share this with you, as a form of payment for having to read this: - https://youtu.be/dQw4w9WgXcQ?si=KeoTIpn9tUtQnOBk! Enjoy :) Now lets see if + https://youtu.be/dQw4w9WgXcQ?si=KeoTIpn9tUtQnOBk! Enjoy :) Now lets see if this test passes or if the result is more exciting than these 500 characters I wrote. Best of luck to the both of us!` _, err := service.SaveDashboard(context.Background(), dto, false) @@ -1327,10 +1328,15 @@ func TestDeleteAllDashboards(t *testing.T) { func TestSearchDashboards(t *testing.T) { fakeStore := dashboards.FakeDashboardStore{} + fakeFolders := foldertest.NewFakeService() + fakeFolders.ExpectedFolder = &folder.Folder{ + Title: "testing-folder-1", + } defer fakeStore.AssertExpectations(t) service := &DashboardServiceImpl{ cfg: setting.NewCfg(), dashboardStore: &fakeStore, + folderService: fakeFolders, } expectedResult := model.HitList{ @@ -1345,15 +1351,17 @@ func TestSearchDashboards(t *testing.T) { "tag1", "tag2", }, + FolderTitle: "testing-folder-1", }, { - UID: "uid2", - OrgID: 1, - Title: "Dashboard 2", - Type: "dash-db", - URI: "db/dashboard-2", - URL: "/d/uid2/dashboard-2", - Tags: []string{}, + UID: "uid2", + OrgID: 1, + Title: "Dashboard 2", + Type: "dash-db", + URI: "db/dashboard-2", + URL: "/d/uid2/dashboard-2", + Tags: []string{}, + FolderTitle: "testing-folder-1", }, } query := dashboards.FindPersistedDashboardsQuery{ @@ -1363,17 +1371,19 @@ func TestSearchDashboards(t *testing.T) { service.features = featuremgmt.WithFeatures() fakeStore.On("FindDashboards", mock.Anything, mock.Anything).Return([]dashboards.DashboardSearchProjection{ { - UID: "uid1", - Slug: "dashboard-1", - OrgID: 1, - Title: "Dashboard 1", - Tags: []string{"tag1", "tag2"}, + UID: "uid1", + Slug: "dashboard-1", + OrgID: 1, + Title: "Dashboard 1", + Tags: []string{"tag1", "tag2"}, + FolderTitle: "testing-folder-1", }, { - UID: "uid2", - Slug: "dashboard-2", - OrgID: 1, - Title: "Dashboard 2", + UID: "uid2", + Slug: "dashboard-2", + OrgID: 1, + Title: "Dashboard 2", + FolderTitle: "testing-folder-1", }, }, nil).Once() result, err := service.SearchDashboards(context.Background(), &query)