From a600cc6eb7f9f215f07f7ddbad0b71e8b4bb05ec Mon Sep 17 00:00:00 2001 From: Mariell Hoversholm Date: Thu, 28 Nov 2024 14:03:26 +0100 Subject: [PATCH] POC/Provisioning: Import: Apply folder nesting properly (#97143) --- pkg/registry/apis/provisioning/register.go | 9 ++-- .../apis/provisioning/resources/replicator.go | 42 +++++++++---------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/pkg/registry/apis/provisioning/register.go b/pkg/registry/apis/provisioning/register.go index b4a011c68dc..abdf6e301c3 100644 --- a/pkg/registry/apis/provisioning/register.go +++ b/pkg/registry/apis/provisioning/register.go @@ -89,7 +89,8 @@ func RegisterAPIService( ghFactory github.ClientFactory, ) *ProvisioningAPIBuilder { if !(features.IsEnabledGlobally(featuremgmt.FlagProvisioning) || - features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs)) { + features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) || + features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerTestingWithExperimentalAPIs)) { return nil // skip registration unless opting into experimental apis OR the feature specifically } builder := NewProvisioningAPIBuilder(&repository.LocalFolderResolver{ @@ -279,11 +280,6 @@ func (b *ProvisioningAPIBuilder) beginUpdate(ctx context.Context, obj, old runti } func (b *ProvisioningAPIBuilder) ensureRepositoryFolderExists(ctx context.Context, cfg *provisioning.Repository) error { - if !b.features.IsEnabledGlobally(featuremgmt.FlagKubernetesFolders) && !b.features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerTestingWithExperimentalAPIs) { - // Nothing to do: we can't use the folders API. - return nil - } - if cfg.Spec.Folder == "" { // The root folder can't not exist, so we don't have to do anything. return nil @@ -293,6 +289,7 @@ func (b *ProvisioningAPIBuilder) ensureRepositoryFolderExists(ctx context.Contex if err != nil { return err } + // FIXME: make sure folders are actually enabled in the apiserver. folderIface := client.Resource(schema.GroupVersionResource{ Group: "folder.grafana.app", Version: "v0alpha1", diff --git a/pkg/registry/apis/provisioning/resources/replicator.go b/pkg/registry/apis/provisioning/resources/replicator.go index 47c0dd69343..79e8a0523a9 100644 --- a/pkg/registry/apis/provisioning/resources/replicator.go +++ b/pkg/registry/apis/provisioning/resources/replicator.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" "log/slog" - "path" "path/filepath" "strings" + apiutils "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,18 +45,20 @@ func (f *ReplicatorFactory) New() (repository.FileReplicator, error) { }) return &replicator{ - logger: slog.Default().With("logger", "replicator", "namespace", f.namespace), - parser: parser, - client: dynamicClient, - folders: folders, + logger: slog.Default().With("logger", "replicator", "namespace", f.namespace), + parser: parser, + client: dynamicClient, + folders: folders, + repository: f.repo, }, nil } type replicator struct { - logger *slog.Logger - client *DynamicClient - parser *FileParser - folders dynamic.ResourceInterface + logger *slog.Logger + client *DynamicClient + parser *FileParser + folders dynamic.ResourceInterface + repository repository.Repository } // Replicate creates a new resource in the cluster. @@ -99,13 +101,13 @@ func (r *replicator) Replicate(ctx context.Context, fileInfo *repository.FileInf func (r *replicator) createFolderPath(ctx context.Context, filePath string) (string, error) { dir := filepath.Dir(filePath) - if dir == "." || dir == "/" { - return "", nil + parent := r.repository.Config().Spec.Folder + if dir == "." { + return parent, nil } logger := r.logger.With("file", filePath) - - for _, folder := range strings.Split(dir, "/") { + for _, folder := range strings.Split(dir, string(filepath.Separator)) { logger := logger.With("folder", folder) obj, err := r.folders.Get(ctx, folder, metav1.GetOptions{}) // FIXME: Check for IsNotFound properly @@ -119,6 +121,9 @@ func (r *replicator) createFolderPath(ctx context.Context, filePath string) (str "metadata": map[string]any{ "name": folder, "namespace": r.client.GetNamespace(), + "annotations": map[string]any{ + apiutils.AnnoKeyFolder: parent, + }, }, "spec": map[string]any{ "title": folder, // TODO: how do we want to get this? @@ -127,18 +132,11 @@ func (r *replicator) createFolderPath(ctx context.Context, filePath string) (str }, }, metav1.CreateOptions{}) if err != nil { - return "", fmt.Errorf("failed to create folder %s: %w", folder, err) + return parent, fmt.Errorf("failed to create folder %s: %w", folder, err) } + parent = folder logger.InfoContext(ctx, "folder created") - - // TODO: folder parents - // TODO: the top-most folder's parent must be the repo folder. - } - - parent := path.Base(path.Dir(filePath)) - if parent == "." || parent == "/" { - return "", nil } return parent, nil