diff --git a/cmd/initializer.go b/cmd/initializer.go index 636adf2..33fb3e8 100644 --- a/cmd/initializer.go +++ b/cmd/initializer.go @@ -31,7 +31,11 @@ var initializerCmd = &cobra.Command{ ctx, _, shutdown := pmcontext.StartContext(log, initializerCfg, defaultCfg.ShutdownTimeout) defer shutdown() - mgrCfg := ctrl.GetConfigOrDie() + restCfg, err := getKubeconfigFromPath(initializerCfg.KCP.Kubeconfig) + if err != nil { + log.Error().Err(err).Msg("unable to get KCP kubeconfig") + os.Exit(1) + } mgrOpts := ctrl.Options{ Scheme: scheme, @@ -57,7 +61,7 @@ var initializerCmd = &cobra.Command{ mgrOpts.LeaderElectionConfig = inClusterCfg } - provider, err := initializingworkspaces.New(mgrCfg, initializingworkspaces.Options{ + provider, err := initializingworkspaces.New(restCfg, initializingworkspaces.Options{ InitializerName: initializerCfg.InitializerName, Scheme: mgrOpts.Scheme, }) @@ -66,7 +70,7 @@ var initializerCmd = &cobra.Command{ os.Exit(1) } - mgr, err := mcmanager.New(mgrCfg, provider, mgrOpts) + mgr, err := mcmanager.New(restCfg, provider, mgrOpts) if err != nil { setupLog.Error(err, "Failed to create manager") os.Exit(1) @@ -82,13 +86,9 @@ var initializerCmd = &cobra.Command{ os.Exit(1) } - inClusterConfig, err := rest.InClusterConfig() - if err != nil { - log.Error().Err(err).Msg("Failed to create in cluster config") - os.Exit(1) - } + k8sCfg := ctrl.GetConfigOrDie() - inClusterClient, err := client.New(inClusterConfig, client.Options{Scheme: scheme}) + runtimeClient, err := client.New(k8sCfg, client.Options{Scheme: scheme}) if err != nil { log.Error().Err(err).Msg("Failed to create in cluster client") os.Exit(1) @@ -98,7 +98,7 @@ var initializerCmd = &cobra.Command{ initializerCfg.IDP.AdditionalRedirectURLs = []string{} } - if err := controller.NewLogicalClusterReconciler(log, orgClient, initializerCfg, inClusterClient, mgr). + if err := controller.NewLogicalClusterReconciler(log, orgClient, initializerCfg, runtimeClient, mgr). SetupWithManager(mgr, defaultCfg); err != nil { setupLog.Error(err, "unable to create controller", "controller", "LogicalCluster") os.Exit(1) diff --git a/cmd/model_generator.go b/cmd/model_generator.go index fa7f143..657ec87 100644 --- a/cmd/model_generator.go +++ b/cmd/model_generator.go @@ -26,13 +26,16 @@ import ( var modelGeneratorCmd = &cobra.Command{ Use: "model-generator", RunE: func(cmd *cobra.Command, args []string) error { - ctrl.SetLogger(log.ComponentLogger("controller-runtime").Logr()) ctx, _, shutdown := platformeshcontext.StartContext(log, defaultCfg, defaultCfg.ShutdownTimeout) defer shutdown() - cfg := ctrl.GetConfigOrDie() + restCfg, err := getKubeconfigFromPath(generatorCfg.KCP.Kubeconfig) + if err != nil { + log.Error().Err(err).Msg("unable to get KCP kubeconfig") + return err + } mgrOpts := manager.Options{ Scheme: scheme, @@ -67,7 +70,7 @@ var modelGeneratorCmd = &cobra.Command{ return fmt.Errorf("scheme should not be nil") } - provider, err := apiexport.New(cfg, apiexport.Options{ + provider, err := apiexport.New(restCfg, apiexport.Options{ Scheme: mgrOpts.Scheme, }) if err != nil { @@ -75,7 +78,7 @@ var modelGeneratorCmd = &cobra.Command{ return err } - mgr, err := mcmanager.New(cfg, provider, mgrOpts) + mgr, err := mcmanager.New(restCfg, provider, mgrOpts) if err != nil { log.Error().Err(err).Msg("Failed to create manager") return err diff --git a/cmd/operator.go b/cmd/operator.go index 2cdc15b..7fdfb88 100644 --- a/cmd/operator.go +++ b/cmd/operator.go @@ -77,6 +77,12 @@ var operatorCmd = &cobra.Command{ ctx, _, shutdown := platformeshcontext.StartContext(log, defaultCfg, defaultCfg.ShutdownTimeout) defer shutdown() + restCfg, err := getKubeconfigFromPath(operatorCfg.KCP.Kubeconfig) + if err != nil { + log.Error().Err(err).Msg("unable to get KCP kubeconfig") + return err + } + if defaultCfg.Sentry.Dsn != "" { err := sentry.Start(ctx, defaultCfg.Sentry.Dsn, defaultCfg.Environment, defaultCfg.Region, @@ -89,8 +95,6 @@ var operatorCmd = &cobra.Command{ defer platformeshcontext.Recover(log) } - cfg := ctrl.GetConfigOrDie() - mgrOpts := ctrl.Options{ Scheme: scheme, Metrics: metricsserver.Options{ @@ -121,7 +125,7 @@ var operatorCmd = &cobra.Command{ return fmt.Errorf("scheme should not be nil") } - provider, err := apiexport.New(cfg, apiexport.Options{ + provider, err := apiexport.New(restCfg, apiexport.Options{ Scheme: mgrOpts.Scheme, }) if err != nil { @@ -129,7 +133,7 @@ var operatorCmd = &cobra.Command{ return err } - mgr, err := mcmanager.New(cfg, provider, mgrOpts) + mgr, err := mcmanager.New(restCfg, provider, mgrOpts) if err != nil { setupLog.Error(err, "Failed to create manager") return err diff --git a/cmd/root.go b/cmd/root.go index c0b2c43..f1a4847 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "flag" "strings" @@ -9,6 +10,8 @@ import ( "github.com/platform-mesh/golang-commons/logger" "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "github.com/platform-mesh/security-operator/internal/config" @@ -18,6 +21,7 @@ var ( defaultCfg *platformeshconfig.CommonServiceConfig initializerCfg config.Config operatorCfg config.Config + generatorCfg config.Config log *logger.Logger setupLog logr.Logger ) @@ -43,6 +47,10 @@ func init() { if err := platformeshconfig.BindConfigToFlags(operatorV, operatorCmd, &operatorCfg); err != nil { panic(err) } + generatorV := newViper() + if err := platformeshconfig.BindConfigToFlags(generatorV, modelGeneratorCmd, &generatorCfg); err != nil { + panic(err) + } initializerV := newViper() if err := platformeshconfig.BindConfigToFlags(initializerV, initializerCmd, &initializerCfg); err != nil { panic(err) @@ -51,6 +59,21 @@ func init() { cobra.OnInitialize(initLog) } +func getKubeconfigFromPath(kubeconfigPath string) (*rest.Config, error) { + if kubeconfigPath == "" { + return nil, errors.New("missing value for required flag --kcp-kubeconfig") + } + cfg, err := clientcmd.LoadFromFile(kubeconfigPath) + if err != nil { + return nil, err + } + restCfg, err := clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + return restCfg, err + } + return restCfg, nil +} + func newViper() *viper.Viper { v := viper.NewWithOptions( viper.EnvKeyReplacer(strings.NewReplacer("-", "_")), diff --git a/internal/config/config.go b/internal/config/config.go index b1dc419..1ecad4b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,6 +12,9 @@ type Config struct { FGA struct { Target string `mapstructure:"fga-target"` } `mapstructure:",squash"` + KCP struct { + Kubeconfig string `mapstructure:"kcp-kubeconfig" default:"/api-kubeconfig/kubeconfig"` + } `mapstructure:",squash"` APIExportEndpointSliceName string `mapstructure:"api-export-endpoint-slice-name"` CoreModulePath string `mapstructure:"core-module-path"` WorkspaceDir string `mapstructure:"workspace-dir" default:"/operator/"` diff --git a/internal/controller/apibinding_controller.go b/internal/controller/apibinding_controller.go index 0a48e09..3afd184 100644 --- a/internal/controller/apibinding_controller.go +++ b/internal/controller/apibinding_controller.go @@ -11,7 +11,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/predicate" - lifecyclecontrollerruntime "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" + "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" "github.com/platform-mesh/security-operator/internal/subroutine" mccontext "sigs.k8s.io/multicluster-runtime/pkg/context" mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager" @@ -21,7 +21,7 @@ import ( func NewAPIBindingReconciler(logger *logger.Logger, mcMgr mcmanager.Manager) *APIBindingReconciler { return &APIBindingReconciler{ log: logger, - lifecycle: builder.NewBuilder("apibinding", "apibinding-controller", []lifecyclesubroutine.Subroutine{ + mclifecycle: builder.NewBuilder("apibinding", "apibinding-controller", []lifecyclesubroutine.Subroutine{ subroutine.NewAuthorizationModelGenerationSubroutine(mcMgr), }, logger). BuildMultiCluster(mcMgr), @@ -29,15 +29,15 @@ func NewAPIBindingReconciler(logger *logger.Logger, mcMgr mcmanager.Manager) *AP } type APIBindingReconciler struct { - log *logger.Logger - lifecycle *lifecyclecontrollerruntime.LifecycleManager + log *logger.Logger + mclifecycle *multicluster.LifecycleManager } func (r *APIBindingReconciler) Reconcile(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) { ctxWithCluster := mccontext.WithCluster(ctx, req.ClusterName) - return r.lifecycle.Reconcile(ctxWithCluster, req, &kcpv1alpha1.APIBinding{}) + return r.mclifecycle.Reconcile(ctxWithCluster, req, &kcpv1alpha1.APIBinding{}) } func (r *APIBindingReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platformeshconfig.CommonServiceConfig, evp ...predicate.Predicate) error { - return r.lifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "apibinding-controller", &kcpv1alpha1.APIBinding{}, cfg.DebugLabelValue, r, r.log, evp...) + return r.mclifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "apibinding-controller", &kcpv1alpha1.APIBinding{}, cfg.DebugLabelValue, r, r.log, evp...) } diff --git a/internal/controller/authorization_model_controller.go b/internal/controller/authorization_model_controller.go index f8e0e79..0f206dc 100644 --- a/internal/controller/authorization_model_controller.go +++ b/internal/controller/authorization_model_controller.go @@ -6,7 +6,7 @@ import ( openfgav1 "github.com/openfga/api/proto/openfga/v1" platformeshconfig "github.com/platform-mesh/golang-commons/config" "github.com/platform-mesh/golang-commons/controller/lifecycle/builder" - lifecyclecontrollerruntime "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" + "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" lifecyclesubroutine "github.com/platform-mesh/golang-commons/controller/lifecycle/subroutine" "github.com/platform-mesh/golang-commons/logger" corev1alpha1 "github.com/platform-mesh/security-operator/api/v1alpha1" @@ -19,14 +19,14 @@ import ( ) type AuthorizationModelReconciler struct { - log *logger.Logger - lifecycle *lifecyclecontrollerruntime.LifecycleManager + log *logger.Logger + mclifecycle *multicluster.LifecycleManager } func NewAuthorizationModelReconciler(log *logger.Logger, fga openfgav1.OpenFGAServiceClient, mcMgr mcmanager.Manager) *AuthorizationModelReconciler { return &AuthorizationModelReconciler{ log: log, - lifecycle: builder.NewBuilder("authorizationmodel", "AuthorizationModelReconciler", []lifecyclesubroutine.Subroutine{ + mclifecycle: builder.NewBuilder("authorizationmodel", "AuthorizationModelReconciler", []lifecyclesubroutine.Subroutine{ subroutine.NewTupleSubroutine(fga, mcMgr), }, log). BuildMultiCluster(mcMgr), @@ -35,9 +35,9 @@ func NewAuthorizationModelReconciler(log *logger.Logger, fga openfgav1.OpenFGASe func (r *AuthorizationModelReconciler) Reconcile(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) { ctxWithCluster := mccontext.WithCluster(ctx, req.ClusterName) - return r.lifecycle.Reconcile(ctxWithCluster, req, &corev1alpha1.AuthorizationModel{}) + return r.mclifecycle.Reconcile(ctxWithCluster, req, &corev1alpha1.AuthorizationModel{}) } func (r *AuthorizationModelReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platformeshconfig.CommonServiceConfig, evp ...predicate.Predicate) error { // coverage-ignore - return r.lifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "authorizationmodel", &corev1alpha1.AuthorizationModel{}, cfg.DebugLabelValue, r, r.log, evp...) + return r.mclifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "authorizationmodel", &corev1alpha1.AuthorizationModel{}, cfg.DebugLabelValue, r, r.log, evp...) } diff --git a/internal/controller/initializer_controller.go b/internal/controller/initializer_controller.go index 8d44f5b..2f6f4cc 100644 --- a/internal/controller/initializer_controller.go +++ b/internal/controller/initializer_controller.go @@ -6,7 +6,7 @@ import ( kcpcorev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1" platformeshconfig "github.com/platform-mesh/golang-commons/config" "github.com/platform-mesh/golang-commons/controller/lifecycle/builder" - lifecyclecontrollerruntime "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" + "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" lifecyclesubroutine "github.com/platform-mesh/golang-commons/controller/lifecycle/subroutine" "github.com/platform-mesh/golang-commons/logger" ctrl "sigs.k8s.io/controller-runtime" @@ -23,13 +23,13 @@ import ( type LogicalClusterReconciler struct { log *logger.Logger - lifecycle *lifecyclecontrollerruntime.LifecycleManager + mclifecycle *multicluster.LifecycleManager } func NewLogicalClusterReconciler(log *logger.Logger, orgClient client.Client, cfg config.Config, inClusterClient client.Client, mgr mcmanager.Manager) *LogicalClusterReconciler { return &LogicalClusterReconciler{ log: log, - lifecycle: builder.NewBuilder("logicalcluster", "LogicalClusterReconciler", []lifecyclesubroutine.Subroutine{ + mclifecycle: builder.NewBuilder("logicalcluster", "LogicalClusterReconciler", []lifecyclesubroutine.Subroutine{ subroutine.NewWorkspaceInitializer(orgClient, cfg, mgr), subroutine.NewWorkspaceAuthConfigurationSubroutine(orgClient, inClusterClient, cfg), subroutine.NewRealmSubroutine(inClusterClient, &cfg, cfg.BaseDomain), @@ -42,9 +42,9 @@ func NewLogicalClusterReconciler(log *logger.Logger, orgClient client.Client, cf func (r *LogicalClusterReconciler) Reconcile(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) { ctxWithCluster := mccontext.WithCluster(ctx, req.ClusterName) - return r.lifecycle.Reconcile(ctxWithCluster, req, &kcpcorev1alpha1.LogicalCluster{}) + return r.mclifecycle.Reconcile(ctxWithCluster, req, &kcpcorev1alpha1.LogicalCluster{}) } func (r *LogicalClusterReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platformeshconfig.CommonServiceConfig, evp ...predicate.Predicate) error { - return r.lifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "LogicalCluster", &kcpcorev1alpha1.LogicalCluster{}, cfg.DebugLabelValue, r, r.log, evp...) + return r.mclifecycle.SetupWithManager(mgr, cfg.MaxConcurrentReconciles, "LogicalCluster", &kcpcorev1alpha1.LogicalCluster{}, cfg.DebugLabelValue, r, r.log, evp...) } diff --git a/internal/controller/invite_controller.go b/internal/controller/invite_controller.go index 80fa618..d9d6839 100644 --- a/internal/controller/invite_controller.go +++ b/internal/controller/invite_controller.go @@ -6,7 +6,7 @@ import ( platformeshconfig "github.com/platform-mesh/golang-commons/config" "github.com/platform-mesh/golang-commons/controller/lifecycle/builder" - lifecycle "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" + "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" lifecyclesubroutine "github.com/platform-mesh/golang-commons/controller/lifecycle/subroutine" "github.com/platform-mesh/golang-commons/logger" ctrl "sigs.k8s.io/controller-runtime" @@ -20,7 +20,7 @@ import ( ) type InviteReconciler struct { - lifecycle *lifecycle.LifecycleManager + mclifecycle *multicluster.LifecycleManager } func NewInviteReconciler(ctx context.Context, mgr mcmanager.Manager, cfg *config.Config, log *logger.Logger) *InviteReconciler { @@ -35,7 +35,7 @@ func NewInviteReconciler(ctx context.Context, mgr mcmanager.Manager, cfg *config } return &InviteReconciler{ - lifecycle: builder.NewBuilder( + mclifecycle: builder.NewBuilder( "invite", "InviteReconciler", []lifecyclesubroutine.Subroutine{ @@ -46,11 +46,11 @@ func NewInviteReconciler(ctx context.Context, mgr mcmanager.Manager, cfg *config } func (r *InviteReconciler) Reconcile(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) { - return r.lifecycle.Reconcile(mccontext.WithCluster(ctx, req.ClusterName), req, &v1alpha1.Invite{}) + return r.mclifecycle.Reconcile(mccontext.WithCluster(ctx, req.ClusterName), req, &v1alpha1.Invite{}) } func (r *InviteReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platformeshconfig.CommonServiceConfig, log *logger.Logger) error { // coverage-ignore - return r.lifecycle. + return r.mclifecycle. SetupWithManager( mgr, cfg.MaxConcurrentReconciles, diff --git a/internal/controller/store_controller.go b/internal/controller/store_controller.go index c2a043c..8debd6b 100644 --- a/internal/controller/store_controller.go +++ b/internal/controller/store_controller.go @@ -13,7 +13,7 @@ import ( openfgav1 "github.com/openfga/api/proto/openfga/v1" platformeshconfig "github.com/platform-mesh/golang-commons/config" - lifecyclecontrollerruntime "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" + "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster" lifecyclesubroutine "github.com/platform-mesh/golang-commons/controller/lifecycle/subroutine" "github.com/platform-mesh/golang-commons/logger" corev1alpha1 "github.com/platform-mesh/security-operator/api/v1alpha1" @@ -26,16 +26,16 @@ import ( // StoreReconciler reconciles a Store object type StoreReconciler struct { - fga openfgav1.OpenFGAServiceClient - log *logger.Logger - lifecycle *lifecyclecontrollerruntime.LifecycleManager + fga openfgav1.OpenFGAServiceClient + log *logger.Logger + mclifecycle *multicluster.LifecycleManager } func NewStoreReconciler(log *logger.Logger, fga openfgav1.OpenFGAServiceClient, mcMgr mcmanager.Manager) *StoreReconciler { return &StoreReconciler{ fga: fga, log: log, - lifecycle: builder.NewBuilder("store", "StoreReconciler", []lifecyclesubroutine.Subroutine{ + mclifecycle: builder.NewBuilder("store", "StoreReconciler", []lifecyclesubroutine.Subroutine{ subroutine.NewStoreSubroutine(fga, mcMgr), subroutine.NewAuthorizationModelSubroutine(fga, mcMgr), subroutine.NewTupleSubroutine(fga, mcMgr), @@ -46,12 +46,12 @@ func NewStoreReconciler(log *logger.Logger, fga openfgav1.OpenFGAServiceClient, func (r *StoreReconciler) Reconcile(ctx context.Context, req mcreconcile.Request) (ctrl.Result, error) { ctxWithCluster := mccontext.WithCluster(ctx, req.ClusterName) - return r.lifecycle.Reconcile(ctxWithCluster, req, &corev1alpha1.Store{}) + return r.mclifecycle.Reconcile(ctxWithCluster, req, &corev1alpha1.Store{}) } // SetupWithManager sets up the controller with the Manager. func (r *StoreReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platformeshconfig.CommonServiceConfig, evp ...predicate.Predicate) error { // coverage-ignore - builder, err := r.lifecycle.SetupWithManagerBuilder(mgr, cfg.MaxConcurrentReconciles, "store", &corev1alpha1.Store{}, cfg.DebugLabelValue, r.log, evp...) + builder, err := r.mclifecycle.SetupWithManagerBuilder(mgr, cfg.MaxConcurrentReconciles, "store", &corev1alpha1.Store{}, cfg.DebugLabelValue, r.log, evp...) if err != nil { return err } @@ -59,7 +59,7 @@ func (r *StoreReconciler) SetupWithManager(mgr mcmanager.Manager, cfg *platforme Watches( &corev1alpha1.AuthorizationModel{}, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request { - model,ok := obj.(*corev1alpha1.AuthorizationModel) + model, ok := obj.(*corev1alpha1.AuthorizationModel) if !ok { return nil } diff --git a/internal/subroutine/tuples.go b/internal/subroutine/tuples.go index e04d658..998f85c 100644 --- a/internal/subroutine/tuples.go +++ b/internal/subroutine/tuples.go @@ -140,8 +140,8 @@ func (t *tupleSubroutine) Process(ctx context.Context, instance runtimeobject.Ru } storeCtx := mccontext.WithCluster(ctx, string(logicalcluster.Name(lc.Annotations[logicalcluster.AnnotationKey]))) - - storeCluster, err := t.mgr.GetCluster(ctx,obj.Spec.StoreRef.Path) + + storeCluster, err := t.mgr.GetCluster(ctx, obj.Spec.StoreRef.Path) if err != nil { return ctrl.Result{}, errors.NewOperatorError(fmt.Errorf("unable to get store cluster: %w", err), true, false) } diff --git a/internal/subroutine/workspace_initializer.go b/internal/subroutine/workspace_initializer.go index 978cf15..7ae591b 100644 --- a/internal/subroutine/workspace_initializer.go +++ b/internal/subroutine/workspace_initializer.go @@ -23,10 +23,8 @@ import ( ) func NewWorkspaceInitializer(orgsClient client.Client, cfg config.Config, mgr mcmanager.Manager) *workspaceInitializer { - coreModulePath := cfg.CoreModulePath - // read file from path - res, err := os.ReadFile(coreModulePath) + res, err := os.ReadFile(cfg.CoreModulePath) if err != nil { panic(err) }