grafana/pkg/registry/apis/folders/conversions.go

97 lines
2.6 KiB
Go
Raw Normal View History

package folders
import (
"fmt"
"strconv"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
claims "github.com/grafana/authlib/types"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
"github.com/grafana/grafana/pkg/services/folder"
Dual Writer simplification (#93852) * All objects should have an UID * Now with a different error message * Simplify create on DW 2: use the same object to write to both storages * Run only one test * Add check for status code * Add name if it's not present in mode2 * Populate UID in legacy * Remove logs and commented code * Change dualwriter1 * Remove commented code * Fix list test * remove get on update from dualwriter 2 * Get object before updating. Better var renaming * Finish rebasing * Comment test * Uncomment tests * Update legacy first. Add preconditions * Remove preconditions * Fix update test * copy RV from unified to legacy objects * revert changes to playlist xorm store * Improve logging. Add go routines for mode3 * Add tests for async funcs in mode3 * Lint * Lint * Lint. Start to fix tests * Fix watcher tests * Fix store tests * Fiinish fixing watcher tests * Fix server tests * add name check * Update pkg/apiserver/rest/dualwriter_mode1.go Co-authored-by: Bruno Abrantes <bruno.abrantes@grafana.com> * All objects should have an UID * Now with a different error message * Simplify create on DW 2: use the same object to write to both storages * Run only one test * Add check for status code * Add name if it's not present in mode2 * Populate UID in legacy * Remove logs and commented code * Change dualwriter1 * Remove commented code * Fix list test * remove get on update from dualwriter 2 * Get object before updating. Better var renaming * Finish rebasing * Comment test * Uncomment tests * Fix update test * revert changes to playlist xorm store * Improve logging. Add go routines for mode3 * Lint * Fix watcher tests * Fiinish fixing watcher tests * Add mode 5 with etcd test case. Add early check to fail on populated RV in payload * we can't set RV to the found object when updating * Lint * Don't fail on update playlists * Name should not be different when updating and it should be not empty on creating * Fix tests * Update pkg/apiserver/rest/dualwriter_mode2.go Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com> * Lint * Fix mode 5 tests * Lint * Add generateName condition on every mode. Fix tests * Lint * Add condition on where name or generate name have to be set * Fix test * Lint * Fix folders test * We dont need to send name for mode1 * Fail if UID is not present * Remove change from not running test * Remove unused line * Lint * Update pkg/storage/unified/apistore/store.go Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com> * Improve error message * Fix broken watcher test * Fail on name mismatch on update * Remove log * Make sure UIDs match on create in both stores * Lint * Write first to unified storage * Remove uid setting * Remove RV only in mode2 * Fix test. Remove log line * test * No need to asser on RV in mode3 * Remove RV check due to race condition * Update dualwriter.go Co-authored-by: Georges Chaudy <chaudyg@gmail.com> * Update pkg/storage/unified/client.go * remove unused parameter * log an error for object is missing UID instead of returning an error * remove obj.SetResourceVersion("") * log an error for object is missing UID instead of returning an error * FInalise merge * Move RV check to where it was * Remove name check * Remove server check for backwards compatibility * Remove unused fn * Move test checks for another PR * Dont commit go work sum changes * Only log error if RV is present for now. --------- Co-authored-by: Todd Treece <todd.treece@grafana.com> Co-authored-by: Bruno Abrantes <bruno.abrantes@grafana.com> Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com> Co-authored-by: Georges Chaudy <chaudyg@gmail.com>
2024-10-23 16:29:41 +08:00
"github.com/grafana/grafana/pkg/util"
)
func LegacyCreateCommandToUnstructured(cmd *folder.CreateFolderCommand) (*unstructured.Unstructured, error) {
obj := &unstructured.Unstructured{
Object: map[string]any{
"spec": map[string]any{
"title": cmd.Title,
"description": cmd.Description,
"version": 1,
},
},
}
meta, err := utils.MetaAccessor(obj)
if err != nil {
return nil, err
}
2024-12-19 16:59:14 +08:00
if cmd.UID == "" {
cmd.UID = util.GenerateShortUID()
}
meta.SetName(cmd.UID)
meta.SetFolder(cmd.ParentUID)
return obj, nil
}
2025-04-11 20:09:52 +08:00
func LegacyFolderToUnstructured(v *folder.Folder, namespacer request.NamespaceMapper) (*folders.Folder, error) {
return convertToK8sResource(v, namespacer)
}
2025-04-11 20:09:52 +08:00
func convertToK8sResource(v *folder.Folder, namespacer request.NamespaceMapper) (*folders.Folder, error) {
f := &folders.Folder{
TypeMeta: folders.FolderResourceInfo.TypeMeta(),
ObjectMeta: metav1.ObjectMeta{
Name: v.UID,
ResourceVersion: fmt.Sprintf("%d", v.Updated.UnixMilli()),
CreationTimestamp: metav1.NewTime(v.Created),
Namespace: namespacer(v.OrgID),
Generation: int64(v.Version),
},
Spec: folders.FolderSpec{
Title: v.Title,
Description: &v.Description,
},
}
meta, err := utils.MetaAccessor(f)
if err != nil {
return nil, err
}
meta.SetUpdatedTimestamp(&v.Updated)
if v.ID > 0 { // nolint:staticcheck
meta.SetDeprecatedInternalID(v.ID) // nolint:staticcheck
}
// #TODO: turns out these get overwritten by Unified Storage (see pkg/storage/unified/apistore/prepare.go)
// We're going to have to align with that. For now we do need the user ID because the folder type stores it
// as the only user identifier
if v.Fullpath != "" {
meta.SetFullpath(v.Fullpath)
}
if v.FullpathUIDs != "" {
meta.SetFullpathUIDs(v.FullpathUIDs)
}
if v.CreatedBy != 0 {
meta.SetCreatedBy(claims.NewTypeID(claims.TypeUser, strconv.FormatInt(v.CreatedBy, 10)))
}
if v.UpdatedBy != 0 {
meta.SetUpdatedBy(claims.NewTypeID(claims.TypeUser, strconv.FormatInt(v.UpdatedBy, 10)))
}
if v.ParentUID != "" {
meta.SetFolder(v.ParentUID)
}
f.UID = gapiutil.CalculateClusterWideUID(f)
return f, nil
}