mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 06:12:16 +08:00
198 lines
5.0 KiB
Go
198 lines
5.0 KiB
Go
package folderimpl
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
authlib "github.com/grafana/authlib/types"
|
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
|
"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 convertUnstructuredToFolder(item *unstructured.Unstructured, identifiers map[string]*user.User) (*folder.Folder, error) {
|
|
meta, err := utils.MetaAccessor(item)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
info, _ := authlib.ParseNamespace(meta.GetNamespace())
|
|
if info.OrgID < 0 {
|
|
info.OrgID = 1 // This resolves all test cases that assume org 1
|
|
}
|
|
|
|
title, _, _ := unstructured.NestedString(item.Object, "spec", "title")
|
|
description, _, _ := unstructured.NestedString(item.Object, "spec", "description")
|
|
|
|
uid := meta.GetName()
|
|
url := ""
|
|
if uid != folder.RootFolder.UID {
|
|
slug := slugify.Slugify(title)
|
|
url = dashboards.GetFolderURL(uid, slug)
|
|
}
|
|
|
|
created := meta.GetCreationTimestamp().Local()
|
|
updated, _ := meta.GetUpdatedTimestamp()
|
|
if updated == nil {
|
|
updated = &created
|
|
} else {
|
|
tmp := updated.Local()
|
|
updated = &tmp
|
|
}
|
|
|
|
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()
|
|
return &folder.Folder{
|
|
UID: uid,
|
|
Title: title,
|
|
Description: description,
|
|
ID: meta.GetDeprecatedInternalID(), // nolint:staticcheck
|
|
ParentUID: meta.GetFolder(),
|
|
Version: int(meta.GetGeneration()),
|
|
ManagedBy: manager.Kind,
|
|
|
|
Fullpath: meta.GetFullpath(),
|
|
FullpathUIDs: meta.GetFullpathUIDs(),
|
|
URL: url,
|
|
Created: created,
|
|
Updated: *updated,
|
|
OrgID: info.OrgID,
|
|
|
|
CreatedBy: createdBy,
|
|
CreatedByUID: createdByUID,
|
|
UpdatedBy: updatedBy,
|
|
UpdatedByUID: updatedByUID,
|
|
}, nil
|
|
}
|
|
|
|
func (ss *FolderUnifiedStoreImpl) UnstructuredToLegacyFolder(ctx context.Context, item *unstructured.Unstructured) (*folder.Folder, error) {
|
|
meta, err := utils.MetaAccessor(item)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
folder, err := convertUnstructuredToFolder(item, folderUserIdentifiers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return folder, nil
|
|
}
|
|
|
|
func (ss *FolderUnifiedStoreImpl) UnstructuredToLegacyFolderList(ctx context.Context, unstructuredList *unstructured.UnstructuredList) ([]*folder.Folder, error) {
|
|
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[meta.GetCreatedBy()] = struct{}{}
|
|
identifiers[meta.GetUpdatedBy()] = struct{}{}
|
|
}
|
|
|
|
folderUserIdentifiers, err := ss.getFolderIdentifiers(ctx, identifiers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
folders := make([]*folder.Folder, 0)
|
|
for _, item := range unstructuredList.Items {
|
|
folder, err := convertUnstructuredToFolder(&item, folderUserIdentifiers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
folders = append(folders, folder)
|
|
}
|
|
|
|
return folders, nil
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
if _, ok := identifierMap[fmt.Sprintf("user:%s", u.UID)]; ok {
|
|
userMap[fmt.Sprintf("user:%s", u.UID)] = u
|
|
}
|
|
}
|
|
return userMap, nil
|
|
}
|
|
|
|
func parseIdentifier(identifier string) string {
|
|
parts := strings.Split(identifier, ":")
|
|
if len(parts) < 2 {
|
|
return ""
|
|
}
|
|
if parts[0] != "user" {
|
|
return ""
|
|
}
|
|
return parts[1]
|
|
}
|
|
|
|
func separateUIDsAndIDs(identifiers map[string]struct{}) (map[string]string, []string, []int64) {
|
|
uids := make([]string, 0)
|
|
ids := make([]int64, 0)
|
|
identifierMap := make(map[string]string, 0)
|
|
|
|
for identifier := range identifiers {
|
|
value := parseIdentifier(identifier)
|
|
if value == "" {
|
|
continue
|
|
}
|
|
|
|
identifierMap[identifier] = value
|
|
|
|
id, err := strconv.ParseInt(value, 10, 64)
|
|
if err == nil {
|
|
ids = append(ids, id)
|
|
} else {
|
|
uids = append(uids, value)
|
|
}
|
|
}
|
|
|
|
return identifierMap, uids, ids
|
|
}
|