Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register direct controller in init() #1910

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
25 changes: 9 additions & 16 deletions pkg/controller/direct/alloydb/cluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
return &clusterModel{config: config}
}

type clusterModel struct {
*gcpClient
// *gcpClient
config *controller.Config
}

// model implements the Model interface.
Expand All @@ -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)
Expand Down
11 changes: 5 additions & 6 deletions pkg/controller/direct/apikeys/apikeyskey_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this!

}

return directbase.Add(mgr, gvk, &model{config: *config}, opts)
func NewModel(config *controller.Config) directbase.Model {
return &model{config: *config}
}

type model struct {
Expand Down
73 changes: 67 additions & 6 deletions pkg/controller/direct/directbase/directbase_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
}

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 {
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
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 {
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
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")
}
Expand Down
25 changes: 12 additions & 13 deletions pkg/controller/direct/gkehub/featuremembership_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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
}
Expand Down
33 changes: 11 additions & 22 deletions pkg/controller/direct/logging/logmetric_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/controller/direct/register/register.go
Original file line number Diff line number Diff line change
@@ -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"
)
5 changes: 1 addition & 4 deletions pkg/controller/direct/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
29 changes: 13 additions & 16 deletions pkg/controller/direct/resourcemanager/tagkey_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
}
Expand All @@ -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
}
Expand Down
Loading
Loading