diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 38b14645dc..835652ec96 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -39,6 +39,8 @@ import ( klog "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" + + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/register" ) var logger = klog.Log.WithName("setup") diff --git a/pkg/controller/direct/alloydb/cluster_controller.go b/pkg/controller/direct/alloydb/cluster_controller.go index 1b56654199..8bb13cc2e7 100644 --- a/pkg/controller/direct/alloydb/cluster_controller.go +++ b/pkg/controller/direct/alloydb/cluster_controller.go @@ -28,30 +28,23 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" krm "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/alloydb/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" ) -// AddClusterController creates a new controller and adds it to the Manager. -// The Manager will set fields on the Controller and start it when the Manager is started. -func AddClusterController(mgr manager.Manager, config *controller.Config, opts directbase.Deps) error { - gvk := krm.AlloyDBClusterGVK +func init() { + directbase.ControllerBuilder.RegisterModel(krm.AlloyDBClusterGVK, NewModel) +} - // TODO: Share gcp client (any value in doing so)? - ctx := context.TODO() - gcpClient, err := newGCPClient(ctx, config) - if err != nil { - return err - } - m := &clusterModel{gcpClient: gcpClient} - return directbase.Add(mgr, gvk, m, opts) +func NewModel(config *controller.Config) directbase.Model { + return &clusterModel{config: config} } type clusterModel struct { - *gcpClient + // *gcpClient + config *controller.Config } // model implements the Model interface. @@ -73,11 +66,11 @@ var _ directbase.Adapter = &clusterAdapter{} // AdapterForObject implements the Model interface. func (m *clusterModel) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { klog.FromContext(ctx).V(0).Info("creating adapter", "u", u) - client, err := m.newAlloyDBAdminClient(ctx) + gcpClient, err := newGCPClient(ctx, m.config) if err != nil { return nil, err } - + client, err := gcpClient.newAlloyDBAdminClient(ctx) obj := &krm.AlloyDBCluster{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &obj); err != nil { return nil, fmt.Errorf("error converting to %T: %w", obj, err) diff --git a/pkg/controller/direct/apikeys/apikeyskey_controller.go b/pkg/controller/direct/apikeys/apikeyskey_controller.go index ac6b228151..cd1b92c22d 100644 --- a/pkg/controller/direct/apikeys/apikeyskey_controller.go +++ b/pkg/controller/direct/apikeys/apikeyskey_controller.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" krm "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/apikeys/v1alpha1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" @@ -36,12 +35,12 @@ import ( . "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/mappings" //nolint:revive ) -// AddKeyReconciler creates a new controller and adds it to the Manager. -// The Manager will set fields on the Controller and start it when the Manager is started. -func AddKeyReconciler(mgr manager.Manager, config *controller.Config, opts directbase.Deps) error { - gvk := krm.APIKeysKeyGVK +func init() { + directbase.ControllerBuilder.RegisterModel(krm.APIKeysKeyGVK, NewModel) +} - return directbase.Add(mgr, gvk, &model{config: *config}, opts) +func NewModel(config *controller.Config) directbase.Model { + return &model{config: *config} } type model struct { diff --git a/pkg/controller/direct/directbase/directbase_controller.go b/pkg/controller/direct/directbase/directbase_controller.go index 073069ab2d..d9ccfd6abe 100644 --- a/pkg/controller/direct/directbase/directbase_controller.go +++ b/pkg/controller/direct/directbase/directbase_controller.go @@ -23,6 +23,7 @@ import ( "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/apis/core/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/kccstate" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" kcciamclient "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/jitter" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/lifecyclehandler" @@ -34,6 +35,7 @@ import ( "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/execution" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/util" + apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "golang.org/x/sync/semaphore" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -53,22 +55,81 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" ) -// Add creates a new controller for reconciling objects of the specified GVK, delegating actual resource reconciliation to the provided Model. -func Add(mgr manager.Manager, gvk schema.GroupVersionKind, model Model, opts Deps) error { +var ControllerBuilder directControllerBuilder + +func init() { + ControllerBuilder = directControllerBuilder{} +} + +type directControllerBuilder struct { + modelMapper map[schema.GroupVersionKind]func(*controller.Config) Model +} + +func (c *directControllerBuilder) RegisterModel(gvk schema.GroupVersionKind, modelFn func(*controller.Config) Model) { + if c.modelMapper == nil { + c.modelMapper = map[schema.GroupVersionKind]func(*controller.Config) Model{} + } + c.modelMapper[gvk] = modelFn +} + +func (c *directControllerBuilder) AddController(mgr manager.Manager, config *controller.Config, gvk schema.GroupVersionKind, deps Deps) error { immediateReconcileRequests := make(chan event.GenericEvent, k8s.ImmediateReconcileRequestsBufferSize) resourceWatcherRoutines := semaphore.NewWeighted(k8s.MaxNumResourceWatcherRoutines) - reconciler, err := NewReconciler(mgr, immediateReconcileRequests, resourceWatcherRoutines, gvk, model, opts.JitterGenerator) + + reconciler, err := c.NewReconciler(mgr, config, immediateReconcileRequests, resourceWatcherRoutines, gvk, deps.JitterGenerator) if err != nil { return err } return add(mgr, reconciler) } -// NewReconciler returns a new reconcile.Reconciler. -func NewReconciler(mgr manager.Manager, immediateReconcileRequests chan event.GenericEvent, resourceWatcherRoutines *semaphore.Weighted, - gvk schema.GroupVersionKind, model Model, jg jitter.Generator) (*DirectReconciler, error) { +func (c *directControllerBuilder) IsDirectByCRD(crd *apiextensions.CustomResourceDefinition) bool { + for gvk, _ := range c.modelMapper { + if gvk.Group == crd.Spec.Group && gvk.Kind == crd.Spec.Names.Kind { + for _, version := range crd.Spec.Versions { + if gvk.Version == version.Name { + return true + } + } + + } + } + return false +} + +func (c *directControllerBuilder) IsDirectByGK(gk schema.GroupKind) bool { + if c.modelMapper == nil { + return false + } + for gvk, _ := range c.modelMapper { + if gvk.Group == gk.Group && gvk.Kind == gk.Kind { + return true + } + } + return false +} +func (c *directControllerBuilder) IsDirectByGVK(gvk schema.GroupVersionKind) bool { + if c.modelMapper == nil { + return false + } + _, ok := c.modelMapper[gvk] + if ok { + return true + } + return false +} + +// NewReconciler returns a new reconcile.Reconciler. +func (c *directControllerBuilder) NewReconciler(mgr manager.Manager, config *controller.Config, immediateReconcileRequests chan event.GenericEvent, resourceWatcherRoutines *semaphore.Weighted, + gvk schema.GroupVersionKind, jg jitter.Generator) (*DirectReconciler, error) { controllerName := strings.ToLower(gvk.Kind) + "-controller" + modelFn, ok := c.modelMapper[gvk] + if !ok { + return nil, fmt.Errorf("no direct controller is registered for GroupVersionKind %s", gvk) + } + model := modelFn(config) + if jg == nil { return nil, fmt.Errorf("jitter generator is not initialized") } diff --git a/pkg/controller/direct/gkehub/featuremembership_controller.go b/pkg/controller/direct/gkehub/featuremembership_controller.go index 90232aa727..3aa54ed3bb 100644 --- a/pkg/controller/direct/gkehub/featuremembership_controller.go +++ b/pkg/controller/direct/gkehub/featuremembership_controller.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" krm "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/gkehub/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" @@ -34,21 +33,16 @@ import ( const ctrlName = "gkehubfeaturemembership-controller" -// AddGkeHubController creates a new controller and adds it to the Manager. -// The Manager will set fields on the Controller and start it when the Manager is started. -func AddGkeHubController(mgr manager.Manager, config *controller.Config, opts directbase.Deps) error { - gvk := krm.GKEHubFeatureMembershipGVK +func init() { + directbase.ControllerBuilder.RegisterModel(krm.GKEHubFeatureMembershipGVK, GetModel) +} - gcpClient, err := newGCPClient(config) - if err != nil { - return err - } - m := &gkeHubModel{gcpClient: gcpClient} - return directbase.Add(mgr, gvk, m, opts) +func GetModel(config *controller.Config) directbase.Model { + return &gkeHubModel{config: config} } type gkeHubModel struct { - gcpClient *gcpClient + config *controller.Config } // model implements the Model interface. @@ -70,7 +64,12 @@ var _ directbase.Adapter = &gkeHubAdapter{} // AdapterForObject implements the Model interface. func (m *gkeHubModel) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { - projectsLocationsFeaturesService, err := m.gcpClient.newProjectsLocationsFeaturesService(ctx) + gcpClient, err := newGCPClient(m.config) + if err != nil { + return nil, err + } + + projectsLocationsFeaturesService, err := gcpClient.newProjectsLocationsFeaturesService(ctx) if err != nil { return nil, err } diff --git a/pkg/controller/direct/logging/logmetric_controller.go b/pkg/controller/direct/logging/logmetric_controller.go index 65452e9ff5..dbbc45ee37 100644 --- a/pkg/controller/direct/logging/logmetric_controller.go +++ b/pkg/controller/direct/logging/logmetric_controller.go @@ -25,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/resources/logging/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1" @@ -36,31 +35,16 @@ import ( const ctrlName = "logmetric-controller" -// AddLogMetricController creates a new controller and adds it to the Manager. -// The Manager will set fields on the Controller and start it when the Manager is started. -func AddLogMetricController(mgr manager.Manager, config *controller.Config, opts directbase.Deps) error { - gvk := krm.LoggingLogMetricGVK - - // todo(acpana): plumb context throughout direct - ctx := context.TODO() - gcpClient, err := newGCPClient(ctx, config) - if err != nil { - return err - } - m := &logMetricModel{gcpClient: gcpClient} - return directbase.Add(mgr, gvk, m, opts) +func init() { + directbase.ControllerBuilder.RegisterModel(krm.LoggingLogMetricGVK, GetModel) } -func GetModel(ctx context.Context, config *controller.Config) (directbase.Model, error) { - gcpClient, err := newGCPClient(ctx, config) - if err != nil { - return nil, err - } - return &logMetricModel{gcpClient: gcpClient}, nil +func GetModel(config *controller.Config) directbase.Model { + return &logMetricModel{config: config} } type logMetricModel struct { - *gcpClient + config *controller.Config } // model implements the Model interface. @@ -79,7 +63,12 @@ var _ directbase.Adapter = &logMetricAdapter{} // AdapterForObject implements the Model interface. func (m *logMetricModel) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { - projectMetricsService, err := m.newProjectMetricsService(ctx) + gcpClient, err := newGCPClient(ctx, m.config) + if err != nil { + return nil, err + } + + projectMetricsService, err := gcpClient.newProjectMetricsService(ctx) if err != nil { return nil, err } diff --git a/pkg/controller/direct/register/register.go b/pkg/controller/direct/register/register.go new file mode 100644 index 0000000000..619d85e745 --- /dev/null +++ b/pkg/controller/direct/register/register.go @@ -0,0 +1,23 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package register + +import ( + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/alloydb" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/apikeys" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/gkehub" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/logging" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/resourcemanager" +) diff --git a/pkg/controller/direct/registry.go b/pkg/controller/direct/registry.go index 8739a361f5..47b0200a4f 100644 --- a/pkg/controller/direct/registry.go +++ b/pkg/controller/direct/registry.go @@ -52,10 +52,7 @@ func Export(ctx context.Context, url string, config *controller.Config) (*unstru if strings.HasPrefix(url, "//logging.googleapis.com/") { tokens := strings.Split(strings.TrimPrefix(url, "//logging.googleapis.com/"), "/") if len(tokens) == 4 && tokens[0] == "projects" && tokens[2] == "metrics" { - m, err := logging.GetModel(ctx, config) - if err != nil { - return nil, err - } + m := logging.GetModel(config) in := &unstructured.Unstructured{} in.SetName(tokens[3]) if err := unstructured.SetNestedField(in.Object, tokens[1], "spec", "projectRef", "external"); err != nil { diff --git a/pkg/controller/direct/resourcemanager/tagkey_controller.go b/pkg/controller/direct/resourcemanager/tagkey_controller.go index d144600067..b8aee1bf8e 100644 --- a/pkg/controller/direct/resourcemanager/tagkey_controller.go +++ b/pkg/controller/direct/resourcemanager/tagkey_controller.go @@ -28,30 +28,22 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager" krm "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/tags/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" ) -// AddTagKeyController creates a new controller and adds it to the Manager. -// The Manager will set fields on the Controller and start it when the Manager is started. -func AddTagKeyController(mgr manager.Manager, config *controller.Config, opts directbase.Deps) error { - gvk := krm.TagsTagKeyGVK +func init() { + directbase.ControllerBuilder.RegisterModel(krm.TagsTagKeyGVK, GetModel) +} - // TODO: Share gcp client (any value in doing so)? - ctx := context.TODO() - gcpClient, err := newGCPClient(ctx, config) - if err != nil { - return err - } - m := &tagKeyModel{gcpClient: gcpClient} - return directbase.Add(mgr, gvk, m, opts) +func GetModel(config *controller.Config) directbase.Model { + return &tagKeyModel{config: config} } type tagKeyModel struct { - *gcpClient + config *controller.Config } // model implements the Model interface. @@ -72,7 +64,12 @@ var _ directbase.Adapter = &tagKeyAdapter{} // AdapterForObject implements the Model interface. func (m *tagKeyModel) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { - tagKeysClient, err := m.newTagKeysClient(ctx) + gcpClient, err := newGCPClient(ctx, m.config) + if err != nil { + return nil, err + } + + tagKeysClient, err := gcpClient.newTagKeysClient(ctx) if err != nil { return nil, err } @@ -91,7 +88,7 @@ func (m *tagKeyModel) AdapterForObject(ctx context.Context, reader client.Reader return &tagKeyAdapter{ resourceID: resourceID, desired: obj, - gcpClient: m.gcpClient, + gcpClient: gcpClient, tagKeysClient: tagKeysClient, }, nil } diff --git a/pkg/controller/registration/registration_controller.go b/pkg/controller/registration/registration_controller.go index 0da95dd08c..3526915c79 100644 --- a/pkg/controller/registration/registration_controller.go +++ b/pkg/controller/registration/registration_controller.go @@ -23,11 +23,7 @@ import ( "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" dclcontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/dcl" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/deletiondefender" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/alloydb" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/apikeys" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/logging" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/resourcemanager" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/gsakeysecretgenerator" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/auditconfig" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/partialpolicy" @@ -196,44 +192,17 @@ func registerDefaultController(r *ReconcileRegistration, config *controller.Conf JitterGen: r.jitterGenerator, Defaulters: r.defaulters, } - var schemaUpdater k8s.SchemaReferenceUpdater if kccfeatureflags.UseDirectReconciler(gvk.GroupKind()) { - switch gvk.GroupKind() { - case schema.GroupKind{Group: "apikeys.cnrm.cloud.google.com", Kind: "APIKeysKey"}: - if err := apikeys.AddKeyReconciler(r.mgr, config, directbase.Deps{JitterGenerator: r.jitterGenerator}); err != nil { - return nil, err - } - return schemaUpdater, nil - - case schema.GroupKind{Group: "tags.cnrm.cloud.google.com", Kind: "TagsTagKey"}: - if err := resourcemanager.AddTagKeyController(r.mgr, config, directbase.Deps{JitterGenerator: r.jitterGenerator}); err != nil { - return nil, err - } - return schemaUpdater, nil - case schema.GroupKind{Group: "logging.cnrm.cloud.google.com", Kind: "LoggingLogMetric"}: - if err := logging.AddLogMetricController(r.mgr, config, directbase.Deps{JitterGenerator: r.jitterGenerator}); err != nil { - return nil, err - } - return schemaUpdater, nil - case schema.GroupKind{Group: "alloydb.cnrm.cloud.google.com", Kind: "AlloyDBCluster"}: - if err := alloydb.AddClusterController(r.mgr, config, directbase.Deps{JitterGenerator: r.jitterGenerator}); err != nil { - return nil, err - } - return schemaUpdater, nil - default: - return nil, fmt.Errorf("requested direct reconciler for %v, but it is not supported", gvk.GroupKind()) + err := directbase.ControllerBuilder.AddController(r.mgr, config, gvk, directbase.Deps{JitterGenerator: r.jitterGenerator}) + if err != nil { + return nil, fmt.Errorf("error adding direct controller for %v to a manager: %w", crd.Spec.Names.Kind, err) } + return schemaUpdater, nil } // Depending on which resource it is, we need to register a different controller. switch gvk.Kind { - // todo acpana: move direct controllers to the defaut case - case "LoggingLogMetric": - if err := logging.AddLogMetricController(r.mgr, config, directbase.Deps{JitterGenerator: r.jitterGenerator}); err != nil { - return nil, err - } - return schemaUpdater, nil case "IAMPolicy": if err := policy.Add(r.mgr, &cds); err != nil { return nil, err @@ -252,6 +221,14 @@ func registerDefaultController(r *ReconcileRegistration, config *controller.Conf } default: + // register the controller to automatically create secrets for GSA keys + if isServiceAccountKeyCRD(crd) { + logger.Info("registering the GSA-Key-to-Secret generation controller") + if err := gsakeysecretgenerator.Add(r.mgr, crd, &controller.Deps{JitterGen: r.jitterGenerator}); err != nil { + return nil, fmt.Errorf("error adding the gsa-to-secret generator for %v to a manager: %w", crd.Spec.Names.Kind, err) + } + } + // register controllers for dcl-based CRDs if val, ok := crd.Labels[k8s.DCL2CRDLabel]; ok && val == "true" { su, err := dclcontroller.Add(r.mgr, crd, r.dclConverter, r.dclConfig, r.smLoader, r.defaulters, r.jitterGenerator) @@ -261,22 +238,23 @@ func registerDefaultController(r *ReconcileRegistration, config *controller.Conf return su, nil } // register controllers for tf-based CRDs - if val, ok := crd.Labels[crdgeneration.TF2CRDLabel]; !ok || val != "true" { - logger.Error(fmt.Errorf("unrecognized CRD: %v", crd.Spec.Names.Kind), "skipping controller registration", "group", gvk.Group, "version", gvk.Version, "kind", gvk.Kind) - return nil, nil - } - su, err := tf.Add(r.mgr, crd, r.provider, r.smLoader, r.defaulters, r.jitterGenerator) - if err != nil { - return nil, fmt.Errorf("error adding terraform controller for %v to a manager: %w", crd.Spec.Names.Kind, err) + if val, ok := crd.Labels[crdgeneration.TF2CRDLabel]; ok && val == "true" { + su, err := tf.Add(r.mgr, crd, r.provider, r.smLoader, r.defaulters, r.jitterGenerator) + if err != nil { + return nil, fmt.Errorf("error adding terraform controller for %v to a manager: %w", crd.Spec.Names.Kind, err) + } + return su, nil } - schemaUpdater = su - // register the controller to automatically create secrets for GSA keys - if isServiceAccountKeyCRD(crd) { - logger.Info("registering the GSA-Key-to-Secret generation controller") - if err := gsakeysecretgenerator.Add(r.mgr, crd, &controller.Deps{JitterGen: r.jitterGenerator}); err != nil { - return nil, fmt.Errorf("error adding the gsa-to-secret generator for %v to a manager: %w", crd.Spec.Names.Kind, err) + // register controllers for direct CRDs + if directbase.ControllerBuilder.IsDirectByGVK(gvk) { + err := directbase.ControllerBuilder.AddController(r.mgr, config, gvk, directbase.Deps{JitterGenerator: r.jitterGenerator}) + if err != nil { + return nil, fmt.Errorf("error adding direct controller for %v to a manager: %w", crd.Spec.Names.Kind, err) } + return schemaUpdater, nil } + logger.Error(fmt.Errorf("unrecognized CRD: %v", crd.Spec.Names.Kind), "skipping controller registration", "group", gvk.Group, "version", gvk.Version, "kind", gvk.Kind) + return nil, nil } return schemaUpdater, nil } diff --git a/pkg/test/controller/reconciler/testreconciler.go b/pkg/test/controller/reconciler/testreconciler.go index e0e63605df..fd2f8fd5c7 100644 --- a/pkg/test/controller/reconciler/testreconciler.go +++ b/pkg/test/controller/reconciler/testreconciler.go @@ -23,11 +23,9 @@ import ( "testing" "time" - loggingapis "github.com/GoogleCloudPlatform/k8s-config-connector/apis/resources/logging/v1beta1" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" + kcccontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller" dclcontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/dcl" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" - "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/logging" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/auditconfig" partialpolicy "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/partialpolicy" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/policy" @@ -240,15 +238,8 @@ func (r *TestReconciler) newReconcilerForCRD(crd *apiextensions.CustomResourceDe if crd.GetLabels()[k8s.DCL2CRDLabel] == "true" { return dclcontroller.NewReconciler(r.mgr, crd, r.dclConverter, r.dclConfig, r.smLoader, immediateReconcileRequests, resourceWatcherRoutines, defaulters, jg) } - - switch crd.GetName() { - case "logginglogmetrics.logging.cnrm.cloud.google.com": - m, err := logging.GetModel(context.TODO(), &controller.Config{HTTPClient: r.httpClient}) - if err != nil { - return nil, fmt.Errorf("error getting logging model: %w", err) - } - - return directbase.NewReconciler(r.mgr, immediateReconcileRequests, resourceWatcherRoutines, loggingapis.LoggingLogMetricGVK, m, jg) + if directbase.ControllerBuilder.IsDirectByCRD(crd) { + return directbase.ControllerBuilder.NewReconciler(r.mgr, &kcccontroller.Config{HTTPClient: r.httpClient}, immediateReconcileRequests, resourceWatcherRoutines, crd.GroupVersionKind(), jg) } } return nil, fmt.Errorf("CRD format not recognized") diff --git a/pkg/test/resourcefixture/contexts/register.go b/pkg/test/resourcefixture/contexts/register.go index 9d8690399e..da2f79b39e 100644 --- a/pkg/test/resourcefixture/contexts/register.go +++ b/pkg/test/resourcefixture/contexts/register.go @@ -139,12 +139,9 @@ func (rc ResourceContext) Get(ctx context.Context, _ *testing.T, u *unstructured // direct controllers switch u.GroupVersionKind().GroupKind() { case schema.GroupKind{Group: "logging.cnrm.cloud.google.com", Kind: "LoggingLogMetric"}: - m, err := logging.GetModel(ctx, &controller.Config{ + m := logging.GetModel(&controller.Config{ HTTPClient: httpClient, }) - if err != nil { - return nil, err - } a, err := m.AdapterForObject(ctx, c, u) if err != nil { return nil, err @@ -175,12 +172,9 @@ func (rc ResourceContext) Delete(ctx context.Context, _ *testing.T, u *unstructu // direct controllers switch u.GroupVersionKind().GroupKind() { case schema.GroupKind{Group: "logging.cnrm.cloud.google.com", Kind: "LoggingLogMetric"}: - m, err := logging.GetModel(ctx, &controller.Config{ + m := logging.GetModel(&controller.Config{ HTTPClient: httpClient, }) - if err != nil { - return err - } a, err := m.AdapterForObject(ctx, c, u) if err != nil { return err diff --git a/tests/e2e/unified_test.go b/tests/e2e/unified_test.go index 0542de30d1..91d400a2e5 100644 --- a/tests/e2e/unified_test.go +++ b/tests/e2e/unified_test.go @@ -48,6 +48,8 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" + + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/register" ) func TestAllInSeries(t *testing.T) {