mirror of
https://github.com/outbackdingo/kamaji.git
synced 2026-01-27 10:19:29 +00:00
feat!: support for cert-manager and webhooks
This commit is contained in:
62
api/v1alpha1/datastore_webhook.go
Normal file
62
api/v1alpha1/datastore_webhook.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
)
|
||||
|
||||
// log is for logging in this package.
|
||||
var datastorelog = logf.Log.WithName("datastore-resource")
|
||||
|
||||
func (r *DataStore) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
|
||||
//+kubebuilder:webhook:path=/mutate-kamaji-clastix-io-v1alpha1-datastore,mutating=true,failurePolicy=fail,sideEffects=None,groups=kamaji.clastix.io,resources=datastores,verbs=create;update,versions=v1alpha1,name=mdatastore.kb.io,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &DataStore{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *DataStore) Default() {
|
||||
datastorelog.Info("default", "name", r.Name)
|
||||
|
||||
// TODO(user): fill in your defaulting logic.
|
||||
}
|
||||
|
||||
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
|
||||
//+kubebuilder:webhook:path=/validate-kamaji-clastix-io-v1alpha1-datastore,mutating=false,failurePolicy=fail,sideEffects=None,groups=kamaji.clastix.io,resources=datastores,verbs=create;update,versions=v1alpha1,name=vdatastore.kb.io,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &DataStore{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DataStore) ValidateCreate() error {
|
||||
datastorelog.Info("validate create", "name", r.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object creation.
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DataStore) ValidateUpdate(old runtime.Object) error {
|
||||
datastorelog.Info("validate update", "name", r.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object update.
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DataStore) ValidateDelete() error {
|
||||
datastorelog.Info("validate delete", "name", r.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object deletion.
|
||||
return nil
|
||||
}
|
||||
62
api/v1alpha1/tenantcontrolplane_webhook.go
Normal file
62
api/v1alpha1/tenantcontrolplane_webhook.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
)
|
||||
|
||||
// log is for logging in this package.
|
||||
var tenantcontrolplanelog = logf.Log.WithName("tenantcontrolplane-resource")
|
||||
|
||||
func (in *TenantControlPlane) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(in).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
|
||||
//+kubebuilder:webhook:path=/mutate-kamaji-clastix-io-v1alpha1-tenantcontrolplane,mutating=true,failurePolicy=fail,sideEffects=None,groups=kamaji.clastix.io,resources=tenantcontrolplanes,verbs=create;update,versions=v1alpha1,name=mtenantcontrolplane.kb.io,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &TenantControlPlane{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (in *TenantControlPlane) Default() {
|
||||
tenantcontrolplanelog.Info("default", "name", in.Name)
|
||||
|
||||
// TODO(user): fill in your defaulting logic.
|
||||
}
|
||||
|
||||
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
|
||||
//+kubebuilder:webhook:path=/validate-kamaji-clastix-io-v1alpha1-tenantcontrolplane,mutating=false,failurePolicy=fail,sideEffects=None,groups=kamaji.clastix.io,resources=tenantcontrolplanes,verbs=create;update,versions=v1alpha1,name=vtenantcontrolplane.kb.io,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &TenantControlPlane{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (in *TenantControlPlane) ValidateCreate() error {
|
||||
tenantcontrolplanelog.Info("validate create", "name", in.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object creation.
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (in *TenantControlPlane) ValidateUpdate(old runtime.Object) error {
|
||||
tenantcontrolplanelog.Info("validate update", "name", in.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object update.
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (in *TenantControlPlane) ValidateDelete() error {
|
||||
tenantcontrolplanelog.Info("validate delete", "name", in.Name)
|
||||
|
||||
// TODO(user): fill in your validation logic upon object deletion.
|
||||
return nil
|
||||
}
|
||||
123
api/v1alpha1/webhook_suite_test.go
Normal file
123
api/v1alpha1/webhook_suite_test.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/rest"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
//+kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
|
||||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
|
||||
|
||||
var (
|
||||
cfg *rest.Config
|
||||
k8sClient client.Client
|
||||
testEnv *envtest.Environment
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
)
|
||||
|
||||
func TestAPIs(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
|
||||
RunSpecs(t, "Webhook Suite")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
|
||||
|
||||
ctx, cancel = context.WithCancel(context.TODO())
|
||||
|
||||
By("bootstrapping test environment")
|
||||
testEnv = &envtest.Environment{
|
||||
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
|
||||
ErrorIfCRDPathMissing: false,
|
||||
WebhookInstallOptions: envtest.WebhookInstallOptions{
|
||||
Paths: []string{filepath.Join("..", "..", "config", "webhook")},
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
// cfg is defined in this file globally.
|
||||
cfg, err = testEnv.Start()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(cfg).NotTo(BeNil())
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err = AddToScheme(scheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = admissionv1beta1.AddToScheme(scheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
//+kubebuilder:scaffold:scheme
|
||||
|
||||
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(k8sClient).NotTo(BeNil())
|
||||
|
||||
// start webhook server using Manager
|
||||
webhookInstallOptions := &testEnv.WebhookInstallOptions
|
||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
||||
Scheme: scheme,
|
||||
Host: webhookInstallOptions.LocalServingHost,
|
||||
Port: webhookInstallOptions.LocalServingPort,
|
||||
CertDir: webhookInstallOptions.LocalServingCertDir,
|
||||
LeaderElection: false,
|
||||
MetricsBindAddress: "0",
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = (&TenantControlPlane{}).SetupWebhookWithManager(mgr)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = (&DataStore{}).SetupWebhookWithManager(mgr)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
//+kubebuilder:scaffold:webhook
|
||||
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
err = mgr.Start(ctx)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}()
|
||||
|
||||
// wait for the webhook server to get ready
|
||||
dialer := &net.Dialer{Timeout: time.Second}
|
||||
addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)
|
||||
Eventually(func() error {
|
||||
conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
return nil
|
||||
}).Should(Succeed())
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
cancel()
|
||||
By("tearing down the test environment")
|
||||
err := testEnv.Stop()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
@@ -10,7 +10,7 @@ package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
||||
3
go.mod
3
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.1.4
|
||||
github.com/onsi/gomega v1.19.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
@@ -21,6 +22,7 @@ require (
|
||||
k8s.io/apiserver v0.25.0
|
||||
k8s.io/client-go v0.25.0
|
||||
k8s.io/cluster-bootstrap v0.0.0
|
||||
k8s.io/klog/v2 v2.70.1
|
||||
k8s.io/kubelet v0.0.0
|
||||
k8s.io/kubernetes v1.25.0
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
|
||||
@@ -153,7 +155,6 @@ require (
|
||||
k8s.io/apiextensions-apiserver v0.25.0 // indirect
|
||||
k8s.io/cli-runtime v0.25.0 // indirect
|
||||
k8s.io/component-base v0.25.0 // indirect
|
||||
k8s.io/klog/v2 v2.70.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
|
||||
k8s.io/kube-proxy v0.0.0 // indirect
|
||||
k8s.io/system-validators v1.7.0 // indirect
|
||||
|
||||
8
main.go
8
main.go
@@ -100,6 +100,14 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err = (&kamajiv1alpha1.TenantControlPlane{}).SetupWebhookWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create webhook", "webhook", "TenantControlPlane")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = (&kamajiv1alpha1.DataStore{}).SetupWebhookWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create webhook", "webhook", "DataStore")
|
||||
os.Exit(1)
|
||||
}
|
||||
//+kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user