Slight refactor of Zanzana GRPC Client to use it in the IAM Folder Operator (#110120)
This commit is contained in:
+17
-4
@@ -9,21 +9,34 @@ import (
|
||||
"github.com/grafana/grafana-app-sdk/simple"
|
||||
foldersKind "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
|
||||
"github.com/grafana/grafana/apps/iam/pkg/reconcilers"
|
||||
"github.com/grafana/grafana/pkg/services/authz"
|
||||
)
|
||||
|
||||
type AppConfig = reconcilers.AppConfig
|
||||
|
||||
var appManifestData = app.ManifestData{
|
||||
AppName: "iam-folder-reconciler",
|
||||
Group: "iam.grafana.app",
|
||||
}
|
||||
|
||||
func Provider(appCfg AppConfig) app.Provider {
|
||||
type AppConfig struct {
|
||||
ZanzanaCfg authz.ZanzanaClientConfig
|
||||
FolderReconcilerNamespace string
|
||||
}
|
||||
|
||||
func Provider(appCfg app.SpecificConfig) app.Provider {
|
||||
return simple.NewAppProvider(app.NewEmbeddedManifest(appManifestData), appCfg, New)
|
||||
}
|
||||
|
||||
func New(cfg app.Config) (app.App, error) {
|
||||
folderReconciler, err := reconcilers.NewFolderReconciler(cfg)
|
||||
appSpecificConfig, ok := cfg.SpecificConfig.(AppConfig)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid config type: expected AppConfig, got %T", cfg.SpecificConfig)
|
||||
}
|
||||
|
||||
folderReconciler, err := reconcilers.NewFolderReconciler(reconcilers.ReconcilerConfig{
|
||||
ZanzanaCfg: appSpecificConfig.ZanzanaCfg,
|
||||
KubeConfig: &cfg.KubeConfig,
|
||||
FolderReconcilerNamespace: appSpecificConfig.FolderReconcilerNamespace,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create FolderReconciler: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,13 +5,11 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
"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/services/authz/zanzana"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"github.com/grafana/grafana/pkg/services/authz"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// FolderStore interface for retrieving folder information
|
||||
@@ -27,8 +25,9 @@ type PermissionStore interface {
|
||||
}
|
||||
|
||||
// AppConfig represents the app-specific configuration
|
||||
type AppConfig struct {
|
||||
ZanzanaAddr string
|
||||
type ReconcilerConfig struct {
|
||||
ZanzanaCfg authz.ZanzanaClientConfig
|
||||
KubeConfig *rest.Config
|
||||
FolderReconcilerNamespace string
|
||||
}
|
||||
|
||||
@@ -37,21 +36,16 @@ type FolderReconciler struct {
|
||||
folderStore FolderStore
|
||||
}
|
||||
|
||||
func NewFolderReconciler(cfg app.Config) (operator.Reconciler, error) {
|
||||
// Extract Zanzana address from config
|
||||
appCfg, ok := cfg.SpecificConfig.(AppConfig)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid config type: expected AppConfig, got %T", cfg.SpecificConfig)
|
||||
}
|
||||
|
||||
func NewFolderReconciler(cfg ReconcilerConfig) (operator.Reconciler, error) {
|
||||
// Create Zanzana client
|
||||
zanzanaClient, err := getZanzanaClient(appCfg.ZanzanaAddr)
|
||||
zanzanaClient, err := authz.NewZanzanaClient("*", cfg.ZanzanaCfg)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create zanzana client: %w", err)
|
||||
}
|
||||
|
||||
// Create dependencies
|
||||
folderStore := NewAPIFolderStore(&cfg.KubeConfig)
|
||||
folderStore := NewAPIFolderStore(cfg.KubeConfig)
|
||||
permissionStore := NewZanzanaPermissionStore(zanzanaClient)
|
||||
|
||||
folderReconciler := &FolderReconciler{
|
||||
@@ -66,34 +60,11 @@ func NewFolderReconciler(cfg app.Config) (operator.Reconciler, error) {
|
||||
return reconciler, nil
|
||||
}
|
||||
|
||||
func getZanzanaClient(addr string) (zanzana.Client, error) {
|
||||
transportCredentials := insecure.NewCredentials()
|
||||
|
||||
dialOptions := []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(transportCredentials),
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient(addr, dialOptions...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create zanzana client to remote server: %w", err)
|
||||
}
|
||||
|
||||
client, err := zanzana.NewClient(conn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize zanzana client: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (r *FolderReconciler) reconcile(ctx context.Context, req operator.TypedReconcileRequest[*foldersKind.Folder]) (operator.ReconcileResult, error) {
|
||||
// Add timeout to prevent hanging operations
|
||||
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
logger := logging.FromContext(ctx)
|
||||
logger.Info("Reconciling request", "req", req)
|
||||
|
||||
err := validateFolder(req.Object)
|
||||
if err != nil {
|
||||
return operator.ReconcileResult{}, err
|
||||
@@ -119,22 +90,24 @@ func (r *FolderReconciler) handleUpdateFolder(ctx context.Context, folder *folde
|
||||
|
||||
parentUID, err := r.folderStore.GetFolderParent(ctx, namespace, folderUID)
|
||||
if err != nil {
|
||||
logger.Error("Error getting folder parent", "error", err)
|
||||
return operator.ReconcileResult{}, err
|
||||
}
|
||||
|
||||
parents, err := r.permissionStore.GetFolderParents(ctx, namespace, folderUID)
|
||||
if err != nil {
|
||||
logger.Error("Error getting folder parents", "error", err)
|
||||
return operator.ReconcileResult{}, err
|
||||
}
|
||||
|
||||
if (len(parents) == 0 && parentUID == "") || (len(parents) == 1 && parents[0] == parentUID) {
|
||||
// Folder is already reconciled
|
||||
logger.Info("Folder is already reconciled", "folder", folderUID, "parent", parentUID, "namespace", namespace)
|
||||
return operator.ReconcileResult{}, nil
|
||||
}
|
||||
|
||||
err = r.permissionStore.SetFolderParent(ctx, namespace, folderUID, parentUID)
|
||||
if err != nil {
|
||||
logger.Error("Error setting folder parent", "error", err)
|
||||
return operator.ReconcileResult{}, err
|
||||
}
|
||||
|
||||
@@ -151,6 +124,7 @@ func (r *FolderReconciler) handleDeleteFolder(ctx context.Context, folder *folde
|
||||
|
||||
err := r.permissionStore.DeleteFolderParents(ctx, namespace, folderUID)
|
||||
if err != nil {
|
||||
logger.Error("Error deleting folder parents", "error", err)
|
||||
return operator.ReconcileResult{}, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user