fix(unified-storage): make full path setting optional on get folders (#104757)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user