K8s: Folders: Modify GetChildren to return only Folder References (#103072)
* Return FolderReference instead of Folder on GetChildren Signed-off-by: Maicon Costa <maiconscosta@gmail.com> --------- Signed-off-by: Maicon Costa <maiconscosta@gmail.com>
This commit is contained in:
@@ -385,14 +385,14 @@ func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, user identi
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
if s.features.IsEnabledGlobally(featuremgmt.FlagKubernetesClientDashboardsFolders) {
|
||||
return s.getChildrenFromApiServer(ctx, q)
|
||||
}
|
||||
return s.GetChildrenLegacy(ctx, q)
|
||||
}
|
||||
|
||||
func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
defer func(t time.Time) {
|
||||
parent := q.UID
|
||||
if q.UID != folder.SharedWithMeFolderUID {
|
||||
@@ -465,7 +465,7 @@ func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQu
|
||||
return children, nil
|
||||
}
|
||||
|
||||
func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
permissions := q.SignedInUser.GetPermissions()
|
||||
var folderPermissions []string
|
||||
if q.Permission == dashboardaccess.PERMISSION_EDIT {
|
||||
@@ -513,7 +513,7 @@ func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery
|
||||
// fetch folder from dashboard store
|
||||
dashFolder, ok := dashFolders[f.UID]
|
||||
if !ok {
|
||||
s.log.Error("failed to fetch folder by UID from dashboard store", "orgID", f.OrgID, "uid", f.UID)
|
||||
s.log.Error("failed to fetch folder by UID from dashboard store", "orgID", q.OrgID, "uid", f.UID)
|
||||
}
|
||||
// always expose the dashboard store sequential ID
|
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
|
||||
@@ -527,21 +527,21 @@ func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery
|
||||
|
||||
// add "shared with me" folder on the 1st page
|
||||
if (q.Page == 0 || q.Page == 1) && len(q.FolderUIDs) != 0 {
|
||||
children = append([]*folder.Folder{&folder.SharedWithMeFolder}, children...)
|
||||
children = append([]*folder.FolderReference{folder.SharedWithMeFolder.ToFolderReference()}, children...)
|
||||
}
|
||||
|
||||
return children, nil
|
||||
}
|
||||
|
||||
// GetSharedWithMe returns folders available to user, which cannot be accessed from the root folders
|
||||
func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.Folder, error) {
|
||||
func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.FolderReference, error) {
|
||||
start := time.Now()
|
||||
availableNonRootFolders, err := s.getAvailableNonRootFolders(ctx, q, forceLegacy)
|
||||
if err != nil {
|
||||
s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("failure").Observe(time.Since(start).Seconds())
|
||||
return nil, folder.ErrInternal.Errorf("failed to fetch subfolders to which the user has explicit access: %w", err)
|
||||
}
|
||||
var rootFolders []*folder.Folder
|
||||
var rootFolders []*folder.FolderReference
|
||||
if forceLegacy {
|
||||
rootFolders, err = s.GetChildrenLegacy(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser, Permission: q.Permission})
|
||||
} else {
|
||||
@@ -552,9 +552,9 @@ 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)
|
||||
}
|
||||
|
||||
availableNonRootFolders = s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders, q.OrgID)
|
||||
dedupAvailableNonRootFolders := s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders, q.OrgID)
|
||||
s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("success").Observe(time.Since(start).Seconds())
|
||||
return availableNonRootFolders, nil
|
||||
return dedupAvailableNonRootFolders, nil
|
||||
}
|
||||
|
||||
func (s *Service) getAvailableNonRootFolders(ctx context.Context, q *folder.GetChildrenQuery, forceLegacy bool) ([]*folder.Folder, error) {
|
||||
@@ -618,12 +618,17 @@ 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.Folder, orgID int64) []*folder.Folder {
|
||||
allFolders := append(folders, rootFolders...)
|
||||
foldersDedup := make([]*folder.Folder, 0)
|
||||
func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*folder.Folder, rootFolders []*folder.FolderReference, orgID int64) []*folder.FolderReference {
|
||||
foldersRef := make([]*folder.FolderReference, len(folders))
|
||||
for i, f := range folders {
|
||||
foldersRef[i] = f.ToFolderReference()
|
||||
}
|
||||
|
||||
allFolders := append(foldersRef, rootFolders...)
|
||||
foldersDedup := make([]*folder.FolderReference, 0)
|
||||
|
||||
for _, f := range folders {
|
||||
isSubfolder := slices.ContainsFunc(allFolders, func(folder *folder.Folder) bool {
|
||||
isSubfolder := slices.ContainsFunc(allFolders, func(folder *folder.FolderReference) bool {
|
||||
return f.ParentUID == folder.UID
|
||||
})
|
||||
|
||||
@@ -638,7 +643,7 @@ func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*fo
|
||||
}
|
||||
|
||||
for _, parentUID := range parentUIDs {
|
||||
contains := slices.ContainsFunc(allFolders, func(f *folder.Folder) bool {
|
||||
contains := slices.ContainsFunc(allFolders, func(f *folder.FolderReference) bool {
|
||||
return f.UID == parentUID
|
||||
})
|
||||
if contains {
|
||||
@@ -649,7 +654,7 @@ func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*fo
|
||||
}
|
||||
|
||||
if !isSubfolder {
|
||||
foldersDedup = append(foldersDedup, f)
|
||||
foldersDedup = append(foldersDedup, f.ToFolderReference())
|
||||
}
|
||||
}
|
||||
return foldersDedup
|
||||
|
||||
@@ -343,7 +343,7 @@ func (s *Service) getFolderByTitleFromApiServer(ctx context.Context, orgID int64
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
defer func(t time.Time) {
|
||||
parent := q.UID
|
||||
if q.UID != folder.SharedWithMeFolderUID {
|
||||
@@ -397,7 +397,7 @@ func (s *Service) getChildrenFromApiServer(ctx context.Context, q *folder.GetChi
|
||||
return children, nil
|
||||
}
|
||||
|
||||
func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
permissions := q.SignedInUser.GetPermissions()
|
||||
var folderPermissions []string
|
||||
if q.Permission == dashboardaccess.PERMISSION_EDIT {
|
||||
@@ -432,7 +432,7 @@ func (s *Service) getRootFoldersFromApiServer(ctx context.Context, q *folder.Get
|
||||
|
||||
// add "shared with me" folder on the 1st page
|
||||
if (q.Page == 0 || q.Page == 1) && len(q.FolderUIDs) != 0 {
|
||||
children = append([]*folder.Folder{&folder.SharedWithMeFolder}, children...)
|
||||
children = append([]*folder.FolderReference{folder.SharedWithMeFolder.ToFolderReference()}, children...)
|
||||
}
|
||||
|
||||
return children, nil
|
||||
|
||||
@@ -321,8 +321,8 @@ func (ss *FolderStoreImpl) GetParents(ctx context.Context, q folder.GetParentsQu
|
||||
return util.Reverse(folders[1:]), nil
|
||||
}
|
||||
|
||||
func (ss *FolderStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
var folders []*folder.Folder
|
||||
func (ss *FolderStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
var folders []*folder.FolderReference
|
||||
|
||||
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
sql := strings.Builder{}
|
||||
@@ -368,12 +368,6 @@ func (ss *FolderStoreImpl) GetChildren(ctx context.Context, q folder.GetChildren
|
||||
return folder.ErrDatabaseError.Errorf("failed to get folder children: %w", err)
|
||||
}
|
||||
|
||||
if err := concurrency.ForEachJob(ctx, len(folders), runtime.NumCPU(), func(ctx context.Context, idx int) error {
|
||||
folders[idx].WithURL()
|
||||
return nil
|
||||
}); err != nil {
|
||||
ss.log.Debug("failed to set URL to folders", "err", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return folders, err
|
||||
|
||||
@@ -633,7 +633,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs := make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
@@ -650,7 +649,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs := make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
assert.Equal(t, []string{parent.UID}, childrenUIDs)
|
||||
@@ -683,7 +681,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs = make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
@@ -701,7 +698,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs = make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
@@ -721,7 +717,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs = make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
@@ -739,7 +734,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs = make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
@@ -757,7 +751,6 @@ func TestIntegrationGetChildren(t *testing.T) {
|
||||
|
||||
childrenUIDs = make([]string, 0, len(children))
|
||||
for _, c := range children {
|
||||
assert.NotEmpty(t, c.URL)
|
||||
childrenUIDs = append(childrenUIDs, c.UID)
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ func (ss *FolderUnifiedStoreImpl) GetParents(ctx context.Context, q folder.GetPa
|
||||
return hits, nil
|
||||
}
|
||||
|
||||
func (ss *FolderUnifiedStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) {
|
||||
func (ss *FolderUnifiedStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.FolderReference, error) {
|
||||
// the general folder is saved as an empty string in the database
|
||||
if q.UID == folder.GeneralFolderUID {
|
||||
q.UID = ""
|
||||
@@ -230,36 +230,22 @@ func (ss *FolderUnifiedStoreImpl) GetChildren(ctx context.Context, q folder.GetC
|
||||
}
|
||||
|
||||
allowK6Folder := (q.SignedInUser != nil && q.SignedInUser.IsIdentityType(claims.TypeServiceAccount))
|
||||
hits := make([]*folder.Folder, 0)
|
||||
hits := make([]*folder.FolderReference, 0)
|
||||
for _, item := range res.Hits {
|
||||
// filter out k6 folders if request is not from a service account
|
||||
if item.Name == accesscontrol.K6FolderUID && !allowK6Folder {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: Remove this once we migrate the alerting use case.
|
||||
// This is a temporary flag, and will be removed once we migrate the alerting use case to
|
||||
// expect a folder ref too for children folders.
|
||||
if q.RefOnly { // nolint:staticcheck
|
||||
f := &folder.Folder{
|
||||
ID: item.Field.GetNestedInt64(search.DASHBOARD_LEGACY_ID),
|
||||
UID: item.Name,
|
||||
Title: item.Title,
|
||||
ParentUID: item.Folder,
|
||||
}
|
||||
|
||||
if item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND) != "" {
|
||||
f.ManagedBy = utils.ParseManagerKindString(item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND))
|
||||
}
|
||||
|
||||
hits = append(hits, f)
|
||||
continue
|
||||
f := &folder.FolderReference{
|
||||
ID: item.Field.GetNestedInt64(search.DASHBOARD_LEGACY_ID),
|
||||
UID: item.Name,
|
||||
Title: item.Title,
|
||||
ParentUID: item.Folder,
|
||||
}
|
||||
|
||||
// search only returns a subset of info, get all info of the folder
|
||||
f, err := ss.Get(ctx, folder.GetFolderQuery{UID: &item.Name, OrgID: q.OrgID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND) != "" {
|
||||
f.ManagedBy = utils.ParseManagerKindString(item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND))
|
||||
}
|
||||
|
||||
hits = append(hits, f)
|
||||
|
||||
@@ -430,9 +430,8 @@ func TestGetChildren(t *testing.T) {
|
||||
|
||||
// don't set page or limit - should be automatically added
|
||||
result, err := store.GetChildren(ctx, folder.GetChildrenQuery{
|
||||
UID: "folder1",
|
||||
OrgID: orgID,
|
||||
RefOnly: true, // nolint:staticcheck
|
||||
UID: "folder1",
|
||||
OrgID: orgID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result, 2)
|
||||
|
||||
Reference in New Issue
Block a user