diff --git a/apis/vault/v1alpha1/secretsinjector_webhook.go b/apis/vault/v1alpha1/secretsinjector_webhook.go index a961d12a..dd964bdd 100644 --- a/apis/vault/v1alpha1/secretsinjector_webhook.go +++ b/apis/vault/v1alpha1/secretsinjector_webhook.go @@ -14,6 +14,7 @@ import ( "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/metrics" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -31,11 +32,12 @@ type SecretsInjector struct { opts SecretsInjectorOptions } -func NewSecretsInjector(c client.Client, logger logr.Logger, opts SecretsInjectorOptions) *SecretsInjector { +func NewSecretsInjector(c client.Client, logger logr.Logger, opts SecretsInjectorOptions, scheme *runtime.Scheme) *SecretsInjector { return &SecretsInjector{ - client: c, - logger: logger, - opts: opts, + client: c, + logger: logger, + opts: opts, + decoder: admission.NewDecoder(scheme), } } diff --git a/apis/workloads/v1alpha1/console_attach_webhook.go b/apis/workloads/v1alpha1/console_attach_webhook.go index 29c4b9c1..538117be 100644 --- a/apis/workloads/v1alpha1/console_attach_webhook.go +++ b/apis/workloads/v1alpha1/console_attach_webhook.go @@ -8,6 +8,7 @@ import ( "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -25,21 +26,17 @@ type ConsoleAttachObserverWebhook struct { requestTimeout time.Duration } -func NewConsoleAttachObserverWebhook(c client.Client, recorder record.EventRecorder, lifecycleRecorder LifecycleEventRecorder, logger logr.Logger, requestTimeout time.Duration) *ConsoleAttachObserverWebhook { +func NewConsoleAttachObserverWebhook(c client.Client, recorder record.EventRecorder, lifecycleRecorder LifecycleEventRecorder, logger logr.Logger, requestTimeout time.Duration, scheme *runtime.Scheme) *ConsoleAttachObserverWebhook { return &ConsoleAttachObserverWebhook{ client: c, recorder: recorder, lifecycleRecorder: lifecycleRecorder, logger: logger, requestTimeout: requestTimeout, + decoder: admission.NewDecoder(scheme), } } -func (c *ConsoleAttachObserverWebhook) InjectDecoder(d *admission.Decoder) error { - c.decoder = d - return nil -} - func (c *ConsoleAttachObserverWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { logger := c.logger.WithValues( "uuid", string(req.UID), diff --git a/apis/workloads/v1alpha1/console_authenticator_webhook.go b/apis/workloads/v1alpha1/console_authenticator_webhook.go index e02154d7..968e9df0 100644 --- a/apis/workloads/v1alpha1/console_authenticator_webhook.go +++ b/apis/workloads/v1alpha1/console_authenticator_webhook.go @@ -8,6 +8,7 @@ import ( "time" "github.com/go-logr/logr" + runtime "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) @@ -18,18 +19,14 @@ type ConsoleAuthenticatorWebhook struct { decoder *admission.Decoder } -func NewConsoleAuthenticatorWebhook(lifecycleRecorder LifecycleEventRecorder, logger logr.Logger) *ConsoleAuthenticatorWebhook { +func NewConsoleAuthenticatorWebhook(lifecycleRecorder LifecycleEventRecorder, logger logr.Logger, scheme *runtime.Scheme) *ConsoleAuthenticatorWebhook { return &ConsoleAuthenticatorWebhook{ lifecycleRecorder: lifecycleRecorder, logger: logger, + decoder: admission.NewDecoder(scheme), } } -func (c *ConsoleAuthenticatorWebhook) InjectDecoder(d *admission.Decoder) error { - c.decoder = d - return nil -} - func (c *ConsoleAuthenticatorWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { logger := c.logger.WithValues("uuid", string(req.UID)) logger.Info("starting request", "event", "request.start") diff --git a/apis/workloads/v1alpha1/console_authorisation_webhook.go b/apis/workloads/v1alpha1/console_authorisation_webhook.go index 27416861..8f827001 100644 --- a/apis/workloads/v1alpha1/console_authorisation_webhook.go +++ b/apis/workloads/v1alpha1/console_authorisation_webhook.go @@ -10,6 +10,7 @@ import ( "github.com/go-logr/logr" "github.com/hashicorp/go-multierror" "github.com/pkg/errors" + runtime "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -25,19 +26,15 @@ type ConsoleAuthorisationWebhook struct { decoder *admission.Decoder } -func NewConsoleAuthorisationWebhook(c client.Client, lifecycleRecorder LifecycleEventRecorder, logger logr.Logger) *ConsoleAuthorisationWebhook { +func NewConsoleAuthorisationWebhook(c client.Client, lifecycleRecorder LifecycleEventRecorder, logger logr.Logger, scheme *runtime.Scheme) *ConsoleAuthorisationWebhook { return &ConsoleAuthorisationWebhook{ client: c, lifecycleRecorder: lifecycleRecorder, logger: logger, + decoder: admission.NewDecoder(scheme), } } -func (c *ConsoleAuthorisationWebhook) InjectDecoder(d *admission.Decoder) error { - c.decoder = d - return nil -} - func (c *ConsoleAuthorisationWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { logger := c.logger.WithValues("uuid", string(req.UID)) logger.Info("starting request", "event", "request.start") diff --git a/apis/workloads/v1alpha1/console_template_validation_webhook.go b/apis/workloads/v1alpha1/console_template_validation_webhook.go index 3019265d..a7fa606b 100644 --- a/apis/workloads/v1alpha1/console_template_validation_webhook.go +++ b/apis/workloads/v1alpha1/console_template_validation_webhook.go @@ -7,6 +7,7 @@ import ( "time" "github.com/go-logr/logr" + runtime "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) @@ -17,17 +18,13 @@ type ConsoleTemplateValidationWebhook struct { decoder *admission.Decoder } -func NewConsoleTemplateValidationWebhook(logger logr.Logger) *ConsoleTemplateValidationWebhook { +func NewConsoleTemplateValidationWebhook(logger logr.Logger, scheme *runtime.Scheme) *ConsoleTemplateValidationWebhook { return &ConsoleTemplateValidationWebhook{ - logger: logger, + logger: logger, + decoder: admission.NewDecoder(scheme), } } -func (c *ConsoleTemplateValidationWebhook) InjectDecoder(d *admission.Decoder) error { - c.decoder = d - return nil -} - func (c *ConsoleTemplateValidationWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { logger := c.logger.WithValues("uuid", string(req.UID)) logger.Info("starting request", "event", "request.start") diff --git a/cmd/rbac-manager/main.go b/cmd/rbac-manager/main.go index 8879d9ec..4b37b9b5 100644 --- a/cmd/rbac-manager/main.go +++ b/cmd/rbac-manager/main.go @@ -15,6 +15,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // this is required to auth against GCP ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/metrics" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" rbacv1alpha1 "github.com/gocardless/theatre/v4/apis/rbac/v1alpha1" "github.com/gocardless/theatre/v4/cmd" @@ -72,11 +73,10 @@ func main() { } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort), - Port: 9443, - LeaderElection: commonOpts.ManagerLeaderElection, - LeaderElectionID: "rbac.crds.gocardless.com", + Scheme: scheme, + Metrics: metricsserver.Options{BindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort)}, + LeaderElection: commonOpts.ManagerLeaderElection, + LeaderElectionID: "rbac.crds.gocardless.com", }) if err != nil { app.Fatalf("failed to create manager: %v", err) diff --git a/cmd/vault-manager/main.go b/cmd/vault-manager/main.go index bddf5463..51d332af 100644 --- a/cmd/vault-manager/main.go +++ b/cmd/vault-manager/main.go @@ -9,6 +9,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/metrics" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" vaultv1alpha1 "github.com/gocardless/theatre/v4/apis/vault/v1alpha1" @@ -57,10 +59,12 @@ func main() { defer cancel() mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - MetricsBindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort), - Port: 443, - LeaderElection: commonOpts.ManagerLeaderElection, - LeaderElectionID: "vault.crds.gocardless.com", + Metrics: metricsserver.Options{BindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort)}, + LeaderElection: commonOpts.ManagerLeaderElection, + LeaderElectionID: "vault.crds.gocardless.com", + WebhookServer: webhook.NewServer(webhook.Options{ + Port: 443, + }), }) if err != nil { app.Fatalf("failed to create manager: %v", err) @@ -86,6 +90,7 @@ func main() { mgr.GetClient(), logger.WithName("webhooks").WithName("secrets-injector"), injectorOpts, + mgr.GetScheme(), ), }) diff --git a/cmd/workloads-manager/main.go b/cmd/workloads-manager/main.go index 25ad0492..28bb8d2e 100644 --- a/cmd/workloads-manager/main.go +++ b/cmd/workloads-manager/main.go @@ -11,6 +11,8 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // this is required to auth against GCP ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/metrics" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" rbacv1alpha1 "github.com/gocardless/theatre/v4/apis/rbac/v1alpha1" @@ -82,11 +84,13 @@ func main() { lifecycleRecorder := workloadsv1alpha1.NewLifecycleEventRecorder(*contextName, logger, publisher, idBuilder) mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - MetricsBindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort), - Port: 443, - LeaderElection: commonOpts.ManagerLeaderElection, - LeaderElectionID: "workloads.crds.gocardless.com", - Scheme: scheme, + Metrics: metricsserver.Options{BindAddress: fmt.Sprintf("%s:%d", commonOpts.MetricAddress, commonOpts.MetricPort)}, + LeaderElection: commonOpts.ManagerLeaderElection, + LeaderElectionID: "workloads.crds.gocardless.com", + Scheme: scheme, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: 443, + }), }) if err != nil { app.Fatalf("failed to create manager: %v", err) @@ -108,11 +112,16 @@ func main() { app.Fatalf("failed to create controller: %v", err) } + // NOTE: We may want to simplify the implementation of webhooks, like this: + // https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation + // Currently there's a lot of boilerplate/wiring up, which isn't really necessary. + // console authenticator webhook mgr.GetWebhookServer().Register("/mutate-consoles", &admission.Webhook{ Handler: workloadsv1alpha1.NewConsoleAuthenticatorWebhook( lifecycleRecorder, logger.WithName("webhooks").WithName("console-authenticator"), + mgr.GetScheme(), ), }) @@ -122,6 +131,7 @@ func main() { mgr.GetClient(), lifecycleRecorder, logger.WithName("webhooks").WithName("console-authorisation"), + mgr.GetScheme(), ), }) @@ -129,6 +139,7 @@ func main() { mgr.GetWebhookServer().Register("/validate-consoletemplates", &admission.Webhook{ Handler: workloadsv1alpha1.NewConsoleTemplateValidationWebhook( logger.WithName("webhooks").WithName("console-template"), + mgr.GetScheme(), ), }) @@ -140,6 +151,7 @@ func main() { lifecycleRecorder, logger.WithName("webhooks").WithName("console-attach-observer"), 10*time.Second, + mgr.GetScheme(), ), }) diff --git a/controllers/rbac/directoryrolebinding/controller.go b/controllers/rbac/directoryrolebinding/controller.go index e36cbf01..c468f033 100644 --- a/controllers/rbac/directoryrolebinding/controller.go +++ b/controllers/rbac/directoryrolebinding/controller.go @@ -17,7 +17,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" rbacv1alpha1 "github.com/gocardless/theatre/v4/apis/rbac/v1alpha1" rbacutils "github.com/gocardless/theatre/v4/pkg/rbac" @@ -112,11 +111,8 @@ func (r *DirectoryRoleBindingReconciler) SetupWithManager(mgr manager.Manager) e return ctrl.NewControllerManagedBy(mgr). For(&rbacv1alpha1.DirectoryRoleBinding{}). Watches( - &source.Kind{Type: &rbacv1.RoleBinding{}}, - &handler.EnqueueRequestForOwner{ - IsController: true, - OwnerType: &rbacv1alpha1.DirectoryRoleBinding{}, - }, + &rbacv1.RoleBinding{}, + handler.EnqueueRequestForOwner(r.Scheme, mgr.GetRESTMapper(), &rbacv1alpha1.DirectoryRoleBinding{}, handler.OnlyControllerOwner()), ). Complete( recutil.ResolveAndReconcile( diff --git a/controllers/workloads/console/controller.go b/controllers/workloads/console/controller.go index b7c9adc1..4890c637 100644 --- a/controllers/workloads/console/controller.go +++ b/controllers/workloads/console/controller.go @@ -27,7 +27,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" rbacv1alpha1 "github.com/gocardless/theatre/v4/apis/rbac/v1alpha1" workloadsv1alpha1 "github.com/gocardless/theatre/v4/apis/workloads/v1alpha1" @@ -109,25 +108,19 @@ func (r *ConsoleReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag return ctrl.NewControllerManagedBy(mgr). For(&workloadsv1alpha1.Console{}). Watches( - &source.Kind{Type: &workloadsv1alpha1.Console{}}, + &workloadsv1alpha1.Console{}, &handler.EnqueueRequestForObject{}, ). Watches( - &source.Kind{Type: &workloadsv1alpha1.ConsoleAuthorisation{}}, - &handler.EnqueueRequestForOwner{ - IsController: true, - OwnerType: &workloadsv1alpha1.Console{}, - }, + &workloadsv1alpha1.ConsoleAuthorisation{}, + handler.EnqueueRequestForOwner(r.Scheme, mgr.GetRESTMapper(), &workloadsv1alpha1.Console{}, handler.OnlyControllerOwner()), // Don't unnecessarily reconcile when the controller initially creates the // authorisation object. builder.WithPredicates(IgnoreCreatePredicate{}), ). Watches( - &source.Kind{Type: &batchv1.Job{}}, - &handler.EnqueueRequestForOwner{ - IsController: true, - OwnerType: &workloadsv1alpha1.Console{}, - }, + &batchv1.Job{}, + handler.EnqueueRequestForOwner(r.Scheme, mgr.GetRESTMapper(), &workloadsv1alpha1.Console{}, handler.OnlyControllerOwner()), ). Complete( recutil.ResolveAndReconcile( diff --git a/controllers/workloads/console/integration/suite_test.go b/controllers/workloads/console/integration/suite_test.go index f7e151dd..67a0d069 100644 --- a/controllers/workloads/console/integration/suite_test.go +++ b/controllers/workloads/console/integration/suite_test.go @@ -16,6 +16,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" rbacv1alpha1 "github.com/gocardless/theatre/v4/apis/rbac/v1alpha1" @@ -65,12 +66,15 @@ var _ = BeforeSuite(func() { idBuilder := workloadsv1alpha1.NewConsoleIdBuilder("test") lifecycleRecorder := workloadsv1alpha1.NewLifecycleEventRecorder("test", ctrl.Log, events.NewNopPublisher(), idBuilder) - mgr, err = ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - - Port: testEnv.WebhookInstallOptions.LocalServingPort, + server := webhook.NewServer(webhook.Options{ Host: testEnv.WebhookInstallOptions.LocalServingHost, CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir, + Port: testEnv.WebhookInstallOptions.LocalServingPort, + }) + + mgr, err = ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme, + WebhookServer: server, }) Expect(err).ToNot(HaveOccurred()) @@ -79,6 +83,7 @@ var _ = BeforeSuite(func() { Handler: workloadsv1alpha1.NewConsoleAuthenticatorWebhook( lifecycleRecorder, ctrl.Log.WithName("webhooks").WithName("console-authenticator"), + mgr.GetScheme(), ), }) @@ -88,6 +93,7 @@ var _ = BeforeSuite(func() { mgr.GetClient(), lifecycleRecorder, ctrl.Log.WithName("webhooks").WithName("console-authorisation"), + mgr.GetScheme(), ), }) @@ -95,6 +101,7 @@ var _ = BeforeSuite(func() { mgr.GetWebhookServer().Register("/validate-consoletemplates", &admission.Webhook{ Handler: workloadsv1alpha1.NewConsoleTemplateValidationWebhook( ctrl.Log.WithName("webhooks").WithName("console-template"), + mgr.GetScheme(), ), })