IAM Folder Reconciler - revert fetching latest folder info from the folder to improve perf (#111779)
This commit is contained in:
@@ -79,7 +79,6 @@ func New(cfg app.Config) (app.App, error) {
|
||||
|
||||
folderReconciler, err := reconcilers.NewFolderReconciler(reconcilers.ReconcilerConfig{
|
||||
ZanzanaCfg: appSpecificConfig.ZanzanaClientCfg,
|
||||
KubeConfig: &cfg.KubeConfig,
|
||||
Metrics: metrics,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -8,19 +8,14 @@ import (
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
"github.com/grafana/grafana-app-sdk/operator"
|
||||
foldersKind "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"github.com/grafana/grafana/pkg/services/authz"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// FolderStore interface for retrieving folder information
|
||||
type FolderStore interface {
|
||||
GetFolderParent(ctx context.Context, namespace, uid string) (string, error)
|
||||
}
|
||||
|
||||
// PermissionStore interface for managing folder permissions
|
||||
type PermissionStore interface {
|
||||
GetFolderParents(ctx context.Context, namespace, folderUID string) ([]string, error)
|
||||
@@ -31,13 +26,11 @@ type PermissionStore interface {
|
||||
// ReconcilerConfig represents the app-specific configuration
|
||||
type ReconcilerConfig struct {
|
||||
ZanzanaCfg authz.ZanzanaClientConfig
|
||||
KubeConfig *rest.Config
|
||||
Metrics *ReconcilerMetrics
|
||||
}
|
||||
|
||||
type FolderReconciler struct {
|
||||
permissionStore PermissionStore
|
||||
folderStore FolderStore
|
||||
metrics *ReconcilerMetrics
|
||||
}
|
||||
|
||||
@@ -50,12 +43,10 @@ func NewFolderReconciler(cfg ReconcilerConfig) (operator.Reconciler, error) {
|
||||
}
|
||||
|
||||
// Create dependencies
|
||||
folderStore := NewAPIFolderStore(cfg.KubeConfig)
|
||||
permissionStore := NewZanzanaPermissionStore(zanzanaClient)
|
||||
|
||||
folderReconciler := &FolderReconciler{
|
||||
permissionStore: permissionStore,
|
||||
folderStore: folderStore,
|
||||
metrics: cfg.Metrics,
|
||||
}
|
||||
|
||||
@@ -137,11 +128,11 @@ func (r *FolderReconciler) handleUpdateFolder(ctx context.Context, folder *folde
|
||||
folderUID := folder.Name
|
||||
namespace := folder.Namespace
|
||||
|
||||
parentUID, err := r.folderStore.GetFolderParent(ctx, namespace, folderUID)
|
||||
parentUID, err := getFolderParent(ctx, folder)
|
||||
if err != nil {
|
||||
logger.Error("Error getting folder parent", "error", err)
|
||||
if r.metrics != nil {
|
||||
r.metrics.RecordReconcileFailure(action, "folder_store")
|
||||
r.metrics.RecordReconcileFailure(action, "failure_informer")
|
||||
}
|
||||
return operator.ReconcileResult{}, err
|
||||
}
|
||||
@@ -217,3 +208,21 @@ func validateFolder(folder *foldersKind.Folder) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFolderParent(ctx context.Context, folder *foldersKind.Folder) (string, error) {
|
||||
tracer := otel.GetTracerProvider().Tracer("iam-folder-reconciler")
|
||||
_, span := tracer.Start(ctx, "get-folder-parent",
|
||||
trace.WithAttributes(
|
||||
attribute.String("folder.uid", folder.Name),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
folderMeta, err := utils.MetaAccessor(folder)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "failed to get folder meta accessor")
|
||||
return "", err
|
||||
}
|
||||
return folderMeta.GetFolder(), nil
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package reconcilers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
foldersKind "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var _ FolderStore = (*APIFolderStore)(nil)
|
||||
|
||||
func NewAPIFolderStore(config *rest.Config) FolderStore {
|
||||
return &APIFolderStore{config}
|
||||
}
|
||||
|
||||
type APIFolderStore struct {
|
||||
config *rest.Config
|
||||
}
|
||||
|
||||
func (s *APIFolderStore) GetFolderParent(ctx context.Context, namespace, uid string) (string, error) {
|
||||
tracer := otel.GetTracerProvider().Tracer("iam-folder-reconciler")
|
||||
ctx, span := tracer.Start(ctx, "APIFolderStore.GetFolderParent",
|
||||
trace.WithAttributes(
|
||||
attribute.String("folder.uid", uid),
|
||||
attribute.String("folder.namespace", namespace),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
client, err := s.client(namespace)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "failed to create kubernetes client")
|
||||
return "", fmt.Errorf("create resource client: %w", err)
|
||||
}
|
||||
|
||||
// Get the folder by UID
|
||||
unstructuredObj, err := client.Get(ctx, uid, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "failed to get folder from kubernetes API")
|
||||
return "", fmt.Errorf("get folder %s: %w", uid, err)
|
||||
}
|
||||
|
||||
object, err := utils.MetaAccessor(unstructuredObj)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "failed to get meta accessor from folder object")
|
||||
return "", fmt.Errorf("get meta accessor: %w", err)
|
||||
}
|
||||
|
||||
parentUID := object.GetFolder()
|
||||
span.SetAttributes(attribute.String("folder.parent_uid", parentUID))
|
||||
span.SetStatus(codes.Ok, "successfully retrieved folder parent")
|
||||
span.AddEvent("folder.parent.retrieved", trace.WithAttributes(
|
||||
attribute.String("parent.uid", parentUID),
|
||||
))
|
||||
|
||||
return parentUID, nil
|
||||
}
|
||||
|
||||
func (s *APIFolderStore) client(namespace string) (dynamic.ResourceInterface, error) {
|
||||
client, err := dynamic.NewForConfig(s.config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.Resource(foldersKind.FolderResourceInfo.GroupVersionResource()).Namespace(namespace), nil
|
||||
}
|
||||
@@ -22,7 +22,6 @@ func NewReconcilerMetrics(registerer prometheus.Registerer, namespace string) *R
|
||||
"success_no_changes_needed",
|
||||
"failure_informer",
|
||||
"failure_permission_store",
|
||||
"failure_folder_store",
|
||||
"failure_unknown",
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user