From dc63f8003cdfe1085b3122d566d847dc518897b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Sencer=20=C3=96zcan?= <32759850+mustafasencer@users.noreply.github.com> Date: Tue, 6 May 2025 16:20:49 +0200 Subject: [PATCH] fix(unified-storage): make full path setting optional on get folders (#104757) --- pkg/services/folder/folderimpl/conversions.go | 141 ++++++++-------- .../folder/folderimpl/conversions_test.go | 151 ++++++++++-------- pkg/services/folder/folderimpl/folder.go | 21 +-- .../folderimpl/folder_unifiedstorage.go | 15 +- .../folderimpl/folder_unifiedstorage_test.go | 128 ++++++++------- 5 files changed, 223 insertions(+), 233 deletions(-) diff --git a/pkg/services/folder/folderimpl/conversions.go b/pkg/services/folder/folderimpl/conversions.go index d682ad604d0..eb718350b0a 100644 --- a/pkg/services/folder/folderimpl/conversions.go +++ b/pkg/services/folder/folderimpl/conversions.go @@ -13,12 +13,13 @@ import ( "github.com/grafana/grafana/pkg/infra/slugify" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/user" ) -func parseUnstructuredToLegacyFolder(item *unstructured.Unstructured) (*folder.Folder, string, string, error) { +func convertUnstructuredToFolder(item *unstructured.Unstructured, identifiers map[string]*user.User) (*folder.Folder, error) { meta, err := utils.MetaAccessor(item) if err != nil { - return nil, "", "", err + return nil, err } info, _ := authlib.ParseNamespace(meta.GetNamespace()) @@ -45,10 +46,20 @@ func parseUnstructuredToLegacyFolder(item *unstructured.Unstructured) (*folder.F updated = &tmp } - creator := meta.GetCreatedBy() - updater := meta.GetUpdatedBy() - if updater == "" { - updater = creator + createdBy, updatedBy := int64(0), int64(0) + createdByUID, updatedByUID := "", "" + + if len(identifiers) > 0 { + user, ok := identifiers[meta.GetCreatedBy()] + if ok { + createdBy = user.ID + createdByUID = user.UID + } + user, ok = identifiers[meta.GetUpdatedBy()] + if ok { + updatedBy = user.ID + updatedByUID = user.UID + } } manager, _ := meta.GetManagerProperties() @@ -67,90 +78,91 @@ func parseUnstructuredToLegacyFolder(item *unstructured.Unstructured) (*folder.F Created: created, Updated: *updated, OrgID: info.OrgID, - }, creator, updater, nil + + CreatedBy: createdBy, + CreatedByUID: createdByUID, + UpdatedBy: updatedBy, + UpdatedByUID: updatedByUID, + }, nil } func (ss *FolderUnifiedStoreImpl) UnstructuredToLegacyFolder(ctx context.Context, item *unstructured.Unstructured) (*folder.Folder, error) { - folder, creatorRaw, updaterRaw, err := parseUnstructuredToLegacyFolder(item) + meta, err := utils.MetaAccessor(item) if err != nil { return nil, err } - userUIDtoIDmapping, err := ss.getUserUIDtoIDmappingFromIdentifiers(ctx, []string{creatorRaw, updaterRaw}) + identifiers := make(map[string]struct{}, 0) + identifiers[meta.GetCreatedBy()] = struct{}{} + identifiers[meta.GetUpdatedBy()] = struct{}{} + + folderUserIdentifiers, err := ss.getFolderIdentifiers(ctx, identifiers) if err != nil { return nil, err } - creatorId := getIdFromMapping(creatorRaw, userUIDtoIDmapping) - updaterId := getIdFromMapping(updaterRaw, userUIDtoIDmapping) - - if updaterId == 0 { - updaterId = creatorId + folder, err := convertUnstructuredToFolder(item, folderUserIdentifiers) + if err != nil { + return nil, err } - folder.Version = int(item.GetGeneration()) - folder.CreatedBy = creatorId - folder.UpdatedBy = updaterId - return folder, nil } func (ss *FolderUnifiedStoreImpl) UnstructuredToLegacyFolderList(ctx context.Context, unstructuredList *unstructured.UnstructuredList) ([]*folder.Folder, error) { - folders := make([]*folder.Folder, 0) - identifiers := make([]string, 0) + identifiers := make(map[string]struct{}, 0) for _, item := range unstructuredList.Items { meta, err := utils.MetaAccessor(&item) if err != nil { return nil, fmt.Errorf("unable to convert unstructured item to legacy folder %w", err) } - identifiers = append(identifiers, meta.GetCreatedBy(), meta.GetUpdatedBy()) + identifiers[meta.GetCreatedBy()] = struct{}{} + identifiers[meta.GetUpdatedBy()] = struct{}{} } - userUIDtoIDmapping, err := ss.getUserUIDtoIDmappingFromIdentifiers(ctx, identifiers) + folderUserIdentifiers, err := ss.getFolderIdentifiers(ctx, identifiers) if err != nil { return nil, err } - + folders := make([]*folder.Folder, 0) for _, item := range unstructuredList.Items { - folder, creatorRaw, updaterRaw, err := parseUnstructuredToLegacyFolder(&item) + folder, err := convertUnstructuredToFolder(&item, folderUserIdentifiers) if err != nil { return nil, err } - - creatorId := getIdFromMapping(creatorRaw, userUIDtoIDmapping) - updaterId := getIdFromMapping(updaterRaw, userUIDtoIDmapping) - - if updaterId == 0 { - updaterId = creatorId - } - - folder.Version = int(item.GetGeneration()) - folder.CreatedBy = creatorId - folder.UpdatedBy = updaterId folders = append(folders, folder) } return folders, nil } -func (ss *FolderUnifiedStoreImpl) getUserUIDtoIDmappingFromIdentifiers(ctx context.Context, rawIdentifiers []string) (map[string]int64, error) { - userUIDs, userIds := parseIdentifiers(rawIdentifiers) - allUsers, err := ss.userService.ListByIdOrUID(ctx, userUIDs, userIds) +func (ss *FolderUnifiedStoreImpl) getFolderIdentifiers(ctx context.Context, identifiers map[string]struct{}) (map[string]*user.User, error) { + identifierMap, userUIDs, userIds := separateUIDsAndIDs(identifiers) + if len(userUIDs) == 0 && len(userIds) == 0 { + return nil, nil + } + + users, err := ss.userService.ListByIdOrUID(ctx, userUIDs, userIds) if err != nil { return nil, err } - mapping := make(map[string]int64) - for _, user := range allUsers { - mapping[user.UID] = user.ID - } + userMap := make(map[string]*user.User, len(users)) + for _, u := range users { + if _, ok := identifierMap[fmt.Sprintf("user:%d", u.ID)]; ok { + userMap[fmt.Sprintf("user:%d", u.ID)] = u + } - return mapping, nil + if _, ok := identifierMap[fmt.Sprintf("user:%s", u.UID)]; ok { + userMap[fmt.Sprintf("user:%s", u.UID)] = u + } + } + return userMap, nil } -func getIdentifier(rawIdentifier string) string { - parts := strings.Split(rawIdentifier, ":") +func parseIdentifier(identifier string) string { + parts := strings.Split(identifier, ":") if len(parts) < 2 { return "" } @@ -160,41 +172,26 @@ func getIdentifier(rawIdentifier string) string { return parts[1] } -func parseIdentifiers(rawIdentifiers []string) ([]string, []int64) { +func separateUIDsAndIDs(identifiers map[string]struct{}) (map[string]string, []string, []int64) { uids := make([]string, 0) ids := make([]int64, 0) - for _, rawIdentifier := range rawIdentifiers { - identifier := getIdentifier(rawIdentifier) - if identifier == "" { + identifierMap := make(map[string]string, 0) + + for identifier := range identifiers { + value := parseIdentifier(identifier) + if value == "" { continue } - id, err := strconv.ParseInt(identifier, 10, 64) + identifierMap[identifier] = value + + id, err := strconv.ParseInt(value, 10, 64) if err == nil { ids = append(ids, id) - } else if identifier != "" { - uids = append(uids, identifier) + } else { + uids = append(uids, value) } } - return uids, ids -} - -func getIdFromMapping(rawIdentifier string, mapping map[string]int64) int64 { - identifier := getIdentifier(rawIdentifier) - if identifier == "" { - return 0 - } - - id, err := strconv.ParseInt(identifier, 10, 64) - if err == nil { - return id - } - - uid, ok := mapping[identifier] - if ok { - return uid - } - - return 0 + return identifierMap, uids, ids } diff --git a/pkg/services/folder/folderimpl/conversions_test.go b/pkg/services/folder/folderimpl/conversions_test.go index 1ad648a1e0b..a88202ce69c 100644 --- a/pkg/services/folder/folderimpl/conversions_test.go +++ b/pkg/services/folder/folderimpl/conversions_test.go @@ -25,7 +25,7 @@ func TestFolderConversions(t *testing.T) { "uid": "wfi3RARqQREzEKtUJCWurWevwbQ7i9ii0cA7JUIbMtEX", "resourceVersion": "1734509107000", "creationTimestamp": "2022-12-02T02:02:02Z", - "generation": 4, + "generation": 4, "labels": { "grafana.app/deprecatedInternalID": "234" }, @@ -67,19 +67,21 @@ func TestFolderConversions(t *testing.T) { require.Equal(t, 1, len(fake.ListUsersByIdOrUidCalls)) // only one call to the user service require.Equal(t, usertest.ListUsersByIdOrUidCall{Uids: []string{"useruid"}, Ids: []int64{2}}, fake.ListUsersByIdOrUidCalls[0]) require.Equal(t, folder.Folder{ - ID: 234, - OrgID: 1, - Version: 4, - UID: "be79sztagf20wd", - ParentUID: "parent-folder-name", - Title: "test folder", - Description: "Something set in the file", - URL: "/dashboards/f/be79sztagf20wd/test-folder", - ManagedBy: utils.ManagerKindRepo, - Created: created, - Updated: created.Add(time.Hour * 5), - CreatedBy: 1, - UpdatedBy: 2, + ID: 234, + OrgID: 1, + Version: 4, + UID: "be79sztagf20wd", + ParentUID: "parent-folder-name", + Title: "test folder", + Description: "Something set in the file", + URL: "/dashboards/f/be79sztagf20wd/test-folder", + ManagedBy: utils.ManagerKindRepo, + Created: created, + Updated: created.Add(time.Hour * 5), + CreatedBy: 1, + UpdatedBy: 2, + CreatedByUID: "useruid", + UpdatedByUID: "useruid2", }, *converted) } @@ -117,7 +119,8 @@ func TestFolderListConversions(t *testing.T) { "kind": "Folder", "metadata": { "annotations": { - "grafana.app/createdBy": "user:uuuuuuuuuuuuuu" + "grafana.app/createdBy": "user:uuuuuuuuuuuuuu", + "grafana.app/updatedBy": "user:uuuuuuuuuuuuuu" }, "creationTimestamp": "2022-12-02T02:02:02Z", "generation": 1, @@ -162,7 +165,8 @@ func TestFolderListConversions(t *testing.T) { "kind": "Folder", "metadata": { "annotations": { - "grafana.app/createdBy": "user:1" + "grafana.app/createdBy": "user:1", + "grafana.app/updatedBy": "user:1" }, "creationTimestamp": "2022-12-02T02:02:02Z", "generation": 1, @@ -268,7 +272,8 @@ func TestFolderListConversions(t *testing.T) { converted, err := fs.UnstructuredToLegacyFolderList(context.Background(), input) require.NoError(t, err) require.Equal(t, 1, len(fake.ListUsersByIdOrUidCalls)) // only one call to the user service - require.Equal(t, usertest.ListUsersByIdOrUidCall{Uids: []string{"uuuuuuuuuuuuuu", "iiiiiiiiiiiiii", "jjjjjjjjjjjjjj"}, Ids: []int64{1, 2, 3}}, fake.ListUsersByIdOrUidCalls[0]) + require.ElementsMatch(t, []string{"uuuuuuuuuuuuuu", "iiiiiiiiiiiiii", "jjjjjjjjjjjjjj"}, fake.ListUsersByIdOrUidCalls[0].Uids) + require.ElementsMatch(t, []int64{1, 2, 3}, fake.ListUsersByIdOrUidCalls[0].Ids) require.Equal(t, 6, len(converted)) require.Equal(t, []*folder.Folder{ { @@ -287,64 +292,72 @@ func TestFolderListConversions(t *testing.T) { UpdatedBy: 0, // service account, }, { - ID: 149, - OrgID: 1, - Version: 1, - UID: "foldername2", - ParentUID: "", - Title: "yeye", - Description: "description yeye", - URL: "/dashboards/f/foldername2/yeye", - ManagedBy: "", - Created: created, - Updated: created, - CreatedBy: 4, - UpdatedBy: 4, + ID: 149, + OrgID: 1, + Version: 1, + UID: "foldername2", + ParentUID: "", + Title: "yeye", + Description: "description yeye", + URL: "/dashboards/f/foldername2/yeye", + ManagedBy: "", + Created: created, + Updated: created, + CreatedBy: 4, + UpdatedBy: 4, + CreatedByUID: "uuuuuuuuuuuuuu", + UpdatedByUID: "uuuuuuuuuuuuuu", }, { - ID: 145, - OrgID: 1, - Version: 1, - UID: "foldername3", - ParentUID: "", - Title: "yoyo", - Description: "description yoyo", - URL: "/dashboards/f/foldername3/yoyo", - ManagedBy: "", - Created: created, - Updated: created, - CreatedBy: 5, - UpdatedBy: 6, + ID: 145, + OrgID: 1, + Version: 1, + UID: "foldername3", + ParentUID: "", + Title: "yoyo", + Description: "description yoyo", + URL: "/dashboards/f/foldername3/yoyo", + ManagedBy: "", + Created: created, + Updated: created, + CreatedBy: 5, + UpdatedBy: 6, + CreatedByUID: "iiiiiiiiiiiiii", + UpdatedByUID: "jjjjjjjjjjjjjj", }, { - ID: 146, - OrgID: 1, - Version: 1, - UID: "foldername4", - ParentUID: "", - Title: "yaya", - Description: "description yaya", - URL: "/dashboards/f/foldername4/yaya", - ManagedBy: "", - Created: created, - Updated: created, - CreatedBy: 1, - UpdatedBy: 1, + ID: 146, + OrgID: 1, + Version: 1, + UID: "foldername4", + ParentUID: "", + Title: "yaya", + Description: "description yaya", + URL: "/dashboards/f/foldername4/yaya", + ManagedBy: "", + Created: created, + Updated: created, + CreatedBy: 1, + UpdatedBy: 1, + CreatedByUID: "aaaaaaaaaaaaaa", + UpdatedByUID: "aaaaaaaaaaaaaa", }, { - ID: 147, - OrgID: 1, - Version: 1, - UID: "foldername5", - ParentUID: "", - Title: "yiyi", - Description: "description yiyi", - URL: "/dashboards/f/foldername5/yiyi", - ManagedBy: "", - Created: created, - Updated: created, - CreatedBy: 2, - UpdatedBy: 3, + ID: 147, + OrgID: 1, + Version: 1, + UID: "foldername5", + ParentUID: "", + Title: "yiyi", + Description: "description yiyi", + URL: "/dashboards/f/foldername5/yiyi", + ManagedBy: "", + Created: created, + Updated: created, + CreatedBy: 2, + UpdatedBy: 3, + CreatedByUID: "oooooooooooooo", + UpdatedByUID: "eeeeeeeeeeeeee", }, { ID: 148, diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index ed286327c02..245542700b7 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -353,14 +353,9 @@ func (s *Service) GetLegacy(ctx context.Context, q *folder.GetFolderQuery) (*fol return f, err } -func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identity.Requester, forceLegacy bool) (*folder.Folder, error) { +func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, forceLegacy bool) (*folder.Folder, error) { ctx, span := s.tracer.Start(ctx, "folder.setFullpath") defer span.End() - // #TODO is some kind of intermediate conversion required as is the case with user id where - // it gets parsed using UserIdentifier(). Also is there some kind of validation taking place as - // part of the parsing? - f.CreatedByUID = user.GetUID() - f.UpdatedByUID = user.GetUID() if f.ParentUID == "" { return f, nil @@ -386,15 +381,7 @@ func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identi } // #TODO revisit setting permissions so that we can centralise the logic for escaping slashes in titles // Escape forward slashes in the title - escapedSlash := "\\/" - title := strings.ReplaceAll(f.Title, "/", escapedSlash) - f.Fullpath = title - f.FullpathUIDs = f.UID - for _, p := range parents { - pt := strings.ReplaceAll(p.Title, "/", escapedSlash) - f.Fullpath = f.Fullpath + "/" + pt - f.FullpathUIDs = f.FullpathUIDs + "/" + p.UID - } + f.Fullpath, f.FullpathUIDs = computeFullPath(append(parents, f)) return f, nil } @@ -573,7 +560,7 @@ func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuer return nil, folder.ErrInternal.Errorf("failed to fetch root folders to which the user has access: %w", err) } - dedupAvailableNonRootFolders := s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders, q.OrgID) + dedupAvailableNonRootFolders := s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders) s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("success").Observe(time.Since(start).Seconds()) return dedupAvailableNonRootFolders, nil } @@ -641,7 +628,7 @@ func (s *Service) getAvailableNonRootFolders(ctx context.Context, q *folder.GetC return nonRootFolders, nil } -func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*folder.Folder, rootFolders []*folder.FolderReference, orgID int64) []*folder.FolderReference { +func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*folder.Folder, rootFolders []*folder.FolderReference) []*folder.FolderReference { foldersRef := make([]*folder.FolderReference, len(folders)) for i, f := range folders { foldersRef[i] = f.ToFolderReference() diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage.go b/pkg/services/folder/folderimpl/folder_unifiedstorage.go index 8a7f5134e3d..355342ff87f 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage.go @@ -151,9 +151,11 @@ func (s *Service) getFromApiServer(ctx context.Context, q *folder.GetFolderQuery f.ID = dashFolder.ID f.Version = dashFolder.Version - f, err = s.setFullpath(ctx, f, q.SignedInUser, false) - if err != nil { - return nil, err + if q.WithFullpath || q.WithFullpathUIDs { + f, err = s.setFullpath(ctx, f, false) + if err != nil { + return nil, err + } } return f, err @@ -512,8 +514,6 @@ func (s *Service) createOnApiServer(ctx context.Context, cmd *folder.CreateFolde return nil, dashboards.ErrFolderInvalidUID } - user := cmd.SignedInUser - cmd = &folder.CreateFolderCommand{ // TODO: Today, if a UID isn't specified, the dashboard store // generates a new UID. The new folder store will need to do this as @@ -531,11 +531,6 @@ func (s *Service) createOnApiServer(ctx context.Context, cmd *folder.CreateFolde return nil, err } - f, err = s.setFullpath(ctx, f, user, false) - if err != nil { - return nil, err - } - return f, nil } diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go index b0f9439e58e..cdb42e38ce7 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go @@ -15,7 +15,7 @@ import ( "k8s.io/apimachinery/pkg/selection" clientrest "k8s.io/client-go/rest" - foldersv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/bus" @@ -77,19 +77,19 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { t.Skip("skipping integration test") } - m := map[string]foldersv1.Folder{} + m := map[string]folderv1.Folder{} - unifiedStorageFolder := &foldersv1.Folder{} + unifiedStorageFolder := &folderv1.Folder{} unifiedStorageFolder.Kind = "folder" fooFolder := &folder.Folder{ - ID: 123, - Title: "Foo Folder", - OrgID: orgID, - UID: "foo", - URL: "/dashboards/f/foo/foo-folder", - CreatedByUID: "user:1", - UpdatedByUID: "user:1", + ID: 123, + Title: "Foo Folder", + OrgID: orgID, + UID: "foo", + URL: "/dashboards/f/foo/foo-folder", + CreatedBy: 1, + UpdatedBy: 1, } updateFolder := &folder.Folder{ @@ -106,7 +106,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { mux.HandleFunc("GET /apis/folder.grafana.app/v1beta1/namespaces/default/folders", func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") - l := &foldersv1.FolderList{} + l := &folderv1.FolderList{} l.Kind = "Folder" err := json.NewEncoder(w).Encode(l) require.NoError(t, err) @@ -137,7 +137,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { buf, err := io.ReadAll(req.Body) require.NoError(t, err) - var foldr foldersv1.Folder + var foldr folderv1.Folder err = json.Unmarshal(buf, &foldr) require.NoError(t, err) @@ -166,7 +166,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { buf, err := io.ReadAll(req.Body) require.NoError(t, err) - var folder foldersv1.Folder + var folder folderv1.Folder err = json.Unmarshal(buf, &folder) require.NoError(t, err) @@ -202,7 +202,7 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { features := featuremgmt.WithFeatures(featuresArr...) dashboardStore := dashboards.NewFakeDashboardStore(t) - k8sCli := client.NewK8sHandler(dualwrite.ProvideTestService(), request.GetNamespaceMapper(cfg), foldersv1.FolderResourceInfo.GroupVersionResource(), restCfgProvider.GetRestConfig, dashboardStore, userService, nil, sort.ProvideService()) + k8sCli := client.NewK8sHandler(dualwrite.ProvideTestService(), request.GetNamespaceMapper(cfg), folderv1.FolderResourceInfo.GroupVersionResource(), restCfgProvider.GetRestConfig, dashboardStore, userService, nil, sort.ProvideService()) unifiedStore := ProvideUnifiedStore(k8sCli, userService) ctx := context.Background() @@ -315,12 +315,12 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { ctx = identity.WithRequester(context.Background(), usr) f := &folder.Folder{ - OrgID: orgID, - Title: "Test-Folder", - UID: "testfolder", - URL: "/dashboards/f/testfolder/test-folder", - CreatedByUID: "user:1", - UpdatedByUID: "user:1", + OrgID: orgID, + Title: "Test-Folder", + UID: "testfolder", + URL: "/dashboards/f/testfolder/test-folder", + CreatedBy: 1, + UpdatedBy: 1, } t.Run("When creating folder should not return access denied error", func(t *testing.T) { @@ -559,8 +559,8 @@ func TestSearchFoldersFromApiServer(t *testing.T) { Options: &resource.ListOptions{ Key: &resource.ResourceKey{ Namespace: "default", - Group: foldersv1.FolderResourceInfo.GroupVersionResource().Group, - Resource: foldersv1.FolderResourceInfo.GroupVersionResource().Resource, + Group: folderv1.FolderResourceInfo.GroupVersionResource().Group, + Resource: folderv1.FolderResourceInfo.GroupVersionResource().Resource, }, Fields: []*resource.Requirement{ { @@ -649,8 +649,8 @@ func TestSearchFoldersFromApiServer(t *testing.T) { Options: &resource.ListOptions{ Key: &resource.ResourceKey{ Namespace: "default", - Group: foldersv1.FolderResourceInfo.GroupVersionResource().Group, - Resource: foldersv1.FolderResourceInfo.GroupVersionResource().Resource, + Group: folderv1.FolderResourceInfo.GroupVersionResource().Group, + Resource: folderv1.FolderResourceInfo.GroupVersionResource().Resource, }, Fields: []*resource.Requirement{}, Labels: []*resource.Requirement{ @@ -718,8 +718,8 @@ func TestSearchFoldersFromApiServer(t *testing.T) { Options: &resource.ListOptions{ Key: &resource.ResourceKey{ Namespace: "default", - Group: foldersv1.FolderResourceInfo.GroupVersionResource().Group, - Resource: foldersv1.FolderResourceInfo.GroupVersionResource().Resource, + Group: folderv1.FolderResourceInfo.GroupVersionResource().Group, + Resource: folderv1.FolderResourceInfo.GroupVersionResource().Resource, }, Fields: []*resource.Requirement{}, Labels: []*resource.Requirement{}, @@ -798,8 +798,13 @@ func TestGetFoldersFromApiServer(t *testing.T) { user := &user.SignedInUser{OrgID: 1} ctx := identity.WithRequester(context.Background(), user) fakeK8sClient.On("GetNamespace", mock.Anything, mock.Anything).Return("default") + folderkey := &resource.ResourceKey{ + Namespace: "default", + Group: folderv1.FolderResourceInfo.GroupVersionResource().Group, + Resource: folderv1.FolderResourceInfo.GroupVersionResource().Resource, + } - t.Run("Get folder by title)", func(t *testing.T) { + t.Run("Get folder by title", func(t *testing.T) { // the search here will return a parent, this will be the parent folder returned when we query for it to add to the hit info fakeFolderStore := folder.NewFakeStore() fakeFolderStore.ExpectedFolder = &folder.Folder{ @@ -813,57 +818,50 @@ func TestGetFoldersFromApiServer(t *testing.T) { service.unifiedStore = fakeFolderStore fakeK8sClient.On("Search", mock.Anything, int64(1), &resource.ResourceSearchRequest{ Options: &resource.ListOptions{ - Key: &resource.ResourceKey{ - Namespace: "default", - Group: foldersv1.FolderResourceInfo.GroupVersionResource().Group, - Resource: foldersv1.FolderResourceInfo.GroupVersionResource().Resource, - }, + Key: folderkey, Fields: []*resource.Requirement{}, Labels: []*resource.Requirement{}, }, Query: "foo title", - Limit: folderSearchLimit}).Return(&resource.ResourceSearchResponse{ - Results: &resource.ResourceTable{ - Columns: []*resource.ResourceTableColumnDefinition{ - { - Name: "title", - Type: resource.ResourceTableColumnDefinition_STRING, - }, - { - Name: "folder", - Type: resource.ResourceTableColumnDefinition_STRING, - }, - }, - Rows: []*resource.ResourceTableRow{ - { - Key: &resource.ResourceKey{ - Name: "uid", - Resource: "folder", + Limit: folderSearchLimit}). + Return(&resource.ResourceSearchResponse{ + Results: &resource.ResourceTable{ + Columns: []*resource.ResourceTableColumnDefinition{ + { + Name: "title", + Type: resource.ResourceTableColumnDefinition_STRING, }, - Cells: [][]byte{ - []byte("foouid"), - []byte("parentuid"), + { + Name: "folder", + Type: resource.ResourceTableColumnDefinition_STRING, + }, + }, + Rows: []*resource.ResourceTableRow{ + { + Key: &resource.ResourceKey{ + Name: "uid", + Resource: "folder", + }, + Cells: [][]byte{ + []byte("foouid"), + []byte("parentuid"), + }, }, }, }, - }, - TotalHits: 1, - }, nil).Once() + TotalHits: 1, + }, nil).Once() result, err := service.getFolderByTitleFromApiServer(ctx, 1, "foo title", nil) require.NoError(t, err) expectedResult := &folder.Folder{ - ID: 2, - UID: "foouid", - ParentUID: "parentuid", - Title: "foo title", - OrgID: 1, - URL: "/dashboards/f/foouid/foo-title", - Fullpath: "foo title", - FullpathUIDs: "foouid", - CreatedByUID: ":0", - UpdatedByUID: ":0", + ID: 2, + UID: "foouid", + ParentUID: "parentuid", + Title: "foo title", + OrgID: 1, + URL: "/dashboards/f/foouid/foo-title", } compareFoldersNormalizeTime(t, expectedResult, result) fakeK8sClient.AssertExpectations(t)