diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage.go b/pkg/services/folder/folderimpl/folder_unifiedstorage.go index d9473e3659b..7794ef4d767 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage.go @@ -121,8 +121,10 @@ func (s *Service) getFromApiServer(ctx context.Context, q *folder.GetFolderQuery return nil, toFolderError(err) } case q.Title != nil: - // not implemented - return nil, folder.ErrBadRequest.Errorf("not implemented") + dashFolder, err = s.getFolderByTitleFromApiServer(ctx, q.OrgID, *q.Title, q.ParentUID) + if err != nil { + return nil, toFolderError(err) + } default: return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present") } @@ -224,6 +226,70 @@ func (s *Service) getFolderByIDFromApiServer(ctx context.Context, id int64, orgI return f, nil } +func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64, title string, parentUID *string) (*folder.Folder, error) { + if title == "" { + return nil, dashboards.ErrFolderTitleEmpty + } + + folderkey := &resource.ResourceKey{ + Namespace: s.k8sclient.getNamespace(orgID), + Group: v0alpha1.FolderResourceInfo.GroupVersionResource().Group, + Resource: v0alpha1.FolderResourceInfo.GroupVersionResource().Resource, + } + + request := &resource.ResourceSearchRequest{ + Options: &resource.ListOptions{ + Key: folderkey, + Fields: []*resource.Requirement{ + { + Key: resource.SEARCH_FIELD_TITLE, + Operator: string(selection.In), + Values: []string{title}, + }, + }, + Labels: []*resource.Requirement{}, + }, + Limit: 100000} + + if parentUID != nil { + req := []*resource.Requirement{{ + Key: resource.SEARCH_FIELD_FOLDER, + Operator: string(selection.In), + Values: []string{*parentUID}, + }} + request.Options.Fields = append(request.Options.Fields, req...) + } + + client := s.k8sclient.getSearcher(ctx) + + res, err := client.Search(ctx, request) + if err != nil { + return nil, err + } + + hits, err := dashboardsearch.ParseResults(res, 0) + if err != nil { + return nil, err + } + + if len(hits.Hits) == 0 { + return nil, dashboards.ErrFolderNotFound + } + + uid := hits.Hits[0].Name + user, err := identity.GetRequester(ctx) + if err != nil { + return nil, err + } + + f, err := s.Get(ctx, &folder.GetFolderQuery{UID: &uid, SignedInUser: user, OrgID: orgID}) + if err != nil { + return nil, err + } + + return f, nil +} + func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) { defer func(t time.Time) { parent := q.UID diff --git a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go index ff445b16832..5ec969918c4 100644 --- a/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go +++ b/pkg/services/folder/folderimpl/folder_unifiedstorage_test.go @@ -438,16 +438,31 @@ func TestIntegrationFolderServiceViaUnifiedStorage(t *testing.T) { require.ErrorIs(t, err, dashboards.ErrFolderNotFound) }) - // TODO!! - /* - t.Run("When get folder by title should return folder", func(t *testing.T) { - expected := folder.NewFolder("TEST-"+util.GenerateShortUID(), "") + t.Run("When get folder by Title should return folder", func(t *testing.T) { + title := "foo" + query := &folder.GetFolderQuery{ + Title: &title, + OrgID: 1, + SignedInUser: usr, + } - actual, err := service.getFolderByTitle(context.Background(), orgID, expected.Title, nil) - require.Equal(t, expected, actual) - require.NoError(t, err) - }) - */ + actual, err := folderService.Get(context.Background(), query) + require.Equal(t, fooFolder, actual) + require.NoError(t, err) + }) + + t.Run("When get folder by non existing Title should return not found error", func(t *testing.T) { + title := "does not exists" + query := &folder.GetFolderQuery{ + Title: &title, + OrgID: 1, + SignedInUser: usr, + } + + actual, err := folderService.Get(context.Background(), query) + require.Nil(t, actual) + require.ErrorIs(t, err, dashboards.ErrFolderNotFound) + }) t.Cleanup(func() { guardian.New = origNewGuardian @@ -534,6 +549,45 @@ func (r resourceClientMock) Search(ctx context.Context, in *resource.ResourceSea }, nil } + if len(in.Options.Fields) > 0 && + in.Options.Fields[0].Key == resource.SEARCH_FIELD_TITLE && + in.Options.Fields[0].Operator == "in" && + len(in.Options.Fields[0].Values) > 0 && + in.Options.Fields[0].Values[0] == "foo" { + return &resource.ResourceSearchResponse{ + Results: &resource.ResourceTable{ + Columns: []*resource.ResourceTableColumnDefinition{ + { + Name: "_id", + Type: resource.ResourceTableColumnDefinition_STRING, + }, + { + Name: "title", + Type: resource.ResourceTableColumnDefinition_STRING, + }, + { + Name: "folder", + Type: resource.ResourceTableColumnDefinition_STRING, + }, + }, + Rows: []*resource.ResourceTableRow{ + { + Key: &resource.ResourceKey{ + Name: "foo", + Resource: "folders", + }, + Cells: [][]byte{ + []byte("123"), + []byte("folder1"), + []byte(""), + }, + }, + }, + }, + TotalHits: 1, + }, nil + } + // not found return &resource.ResourceSearchResponse{ Results: &resource.ResourceTable{},