You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by ch...@apache.org on 2022/09/20 03:44:00 UTC
[dolphinscheduler-operator] 23/44: feat(master && worker): add feature webhook
This is an automated email from the ASF dual-hosted git repository.
chufenggao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler-operator.git
commit 06aaf5e93b210455652bf56352df3b437766d4a8
Author: nobolity <no...@gmail.com>
AuthorDate: Sun Jun 12 13:01:58 2022 +0800
feat(master && worker): add feature webhook
---
api/v1alpha1/dsmaster_webhook.go | 97 +++++++++++++++++++
api/v1alpha1/webhook_suite_test.go | 133 +++++++++++++++++++++++++++
config/certmanager/certificate.yaml | 25 +++++
config/certmanager/kustomization.yaml | 5 +
config/certmanager/kustomizeconfig.yaml | 16 ++++
config/default/manager_webhook_patch.yaml | 23 +++++
config/default/webhookcainjection_patch.yaml | 15 +++
config/webhook/kustomization.yaml | 6 ++
config/webhook/kustomizeconfig.yaml | 25 +++++
config/webhook/manifests.yaml | 54 +++++++++++
config/webhook/service.yaml | 13 +++
11 files changed, 412 insertions(+)
diff --git a/api/v1alpha1/dsmaster_webhook.go b/api/v1alpha1/dsmaster_webhook.go
new file mode 100644
index 0000000..60cc9cb
--- /dev/null
+++ b/api/v1alpha1/dsmaster_webhook.go
@@ -0,0 +1,97 @@
+/*
+Copyright 2022.
+
+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 v1alpha1
+
+import (
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/util/validation/field"
+ 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 dsmasterlog = logf.Log.WithName("dsmaster-resource")
+
+func (r *DSMaster) 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-ds-apache-dolphinscheduler-dev-v1alpha1-dsmaster,mutating=true,failurePolicy=fail,sideEffects=None,groups=ds.apache.dolphinscheduler.dev,resources=dsmasters,verbs=create;update,versions=v1alpha1,name=mdsmaster.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Defaulter = &DSMaster{}
+
+// Default implements webhook.Defaulter so a webhook will be registered for the type
+func (r *DSMaster) Default() {
+
+ if r.Spec.HpaPolicy != nil {
+ if &r.Spec.HpaPolicy.MinReplicas == nil {
+ r.Spec.HpaPolicy.MinReplicas = int32(1)
+ }
+
+ if &r.Spec.HpaPolicy.MaxReplicas == nil {
+ r.Spec.HpaPolicy.MinReplicas = int32(5)
+ }
+ }
+
+}
+
+// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
+//+kubebuilder:webhook:path=/validate-ds-apache-dolphinscheduler-dev-v1alpha1-dsmaster,mutating=false,failurePolicy=fail,sideEffects=None,groups=ds.apache.dolphinscheduler.dev,resources=dsmasters,verbs=create;update,versions=v1alpha1,name=vdsmaster.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Validator = &DSMaster{}
+
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
+func (r *DSMaster) ValidateCreate() error {
+ var allErrs field.ErrorList
+
+ if r.Spec.HpaPolicy != nil {
+ if &r.Spec.HpaPolicy.MinReplicas != nil && &r.Spec.HpaPolicy.MaxReplicas != nil && r.Spec.HpaPolicy.MinReplicas > r.Spec.HpaPolicy.MaxReplicas {
+ return apierrors.NewInvalid(
+ schema.GroupKind{Group: "ds", Kind: "DSMaster"},
+ r.Name,
+ allErrs)
+ }
+
+ } else {
+ dsmasterlog.Info("Hpa `s replicas is valid")
+ return nil
+ }
+ return nil
+}
+
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
+func (r *DSMaster) ValidateUpdate(old runtime.Object) error {
+ dsmasterlog.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 *DSMaster) ValidateDelete() error {
+ dsmasterlog.Info("validate delete", "name", r.Name)
+
+ // TODO(user): fill in your validation logic upon object deletion.
+ return nil
+}
diff --git a/api/v1alpha1/webhook_suite_test.go b/api/v1alpha1/webhook_suite_test.go
new file mode 100644
index 0000000..16f9fc7
--- /dev/null
+++ b/api/v1alpha1/webhook_suite_test.go
@@ -0,0 +1,133 @@
+/*
+Copyright 2022.
+
+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 v1alpha1
+
+import (
+ "context"
+ "crypto/tls"
+ "fmt"
+ "net"
+ "path/filepath"
+ "testing"
+ "time"
+
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+
+ admissionv1beta1 "k8s.io/api/admission/v1beta1"
+ //+kubebuilder:scaffold:imports
+ "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"
+ "sigs.k8s.io/controller-runtime/pkg/envtest/printer"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+ "sigs.k8s.io/controller-runtime/pkg/log/zap"
+)
+
+// 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
+var k8sClient client.Client
+var testEnv *envtest.Environment
+var ctx context.Context
+var cancel context.CancelFunc
+
+func TestAPIs(t *testing.T) {
+ RegisterFailHandler(Fail)
+
+ RunSpecsWithDefaultAndCustomReporters(t,
+ "Webhook Suite",
+ []Reporter{printer.NewlineReporter{}})
+}
+
+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")},
+ },
+ }
+
+ 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 = (&DSMaster{}).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())
+
+}, 60)
+
+var _ = AfterSuite(func() {
+ cancel()
+ By("tearing down the test environment")
+ err := testEnv.Stop()
+ Expect(err).NotTo(HaveOccurred())
+})
diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml
new file mode 100644
index 0000000..52d8661
--- /dev/null
+++ b/config/certmanager/certificate.yaml
@@ -0,0 +1,25 @@
+# The following manifests contain a self-signed issuer CR and a certificate CR.
+# More document can be found at https://docs.cert-manager.io
+# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned-issuer
+ namespace: system
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
+ namespace: system
+spec:
+ # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
+ dnsNames:
+ - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
+ - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
+ issuerRef:
+ kind: Issuer
+ name: selfsigned-issuer
+ secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml
new file mode 100644
index 0000000..bebea5a
--- /dev/null
+++ b/config/certmanager/kustomization.yaml
@@ -0,0 +1,5 @@
+resources:
+- certificate.yaml
+
+configurations:
+- kustomizeconfig.yaml
diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml
new file mode 100644
index 0000000..90d7c31
--- /dev/null
+++ b/config/certmanager/kustomizeconfig.yaml
@@ -0,0 +1,16 @@
+# This configuration is for teaching kustomize how to update name ref and var substitution
+nameReference:
+- kind: Issuer
+ group: cert-manager.io
+ fieldSpecs:
+ - kind: Certificate
+ group: cert-manager.io
+ path: spec/issuerRef/name
+
+varReference:
+- kind: Certificate
+ group: cert-manager.io
+ path: spec/commonName
+- kind: Certificate
+ group: cert-manager.io
+ path: spec/dnsNames
diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml
new file mode 100644
index 0000000..738de35
--- /dev/null
+++ b/config/default/manager_webhook_patch.yaml
@@ -0,0 +1,23 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: controller-manager
+ namespace: system
+spec:
+ template:
+ spec:
+ containers:
+ - name: manager
+ ports:
+ - containerPort: 9443
+ name: webhook-server
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /tmp/k8s-webhook-server/serving-certs
+ name: cert
+ readOnly: true
+ volumes:
+ - name: cert
+ secret:
+ defaultMode: 420
+ secretName: webhook-server-cert
diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml
new file mode 100644
index 0000000..02ab515
--- /dev/null
+++ b/config/default/webhookcainjection_patch.yaml
@@ -0,0 +1,15 @@
+# This patch add annotation to admission webhook config and
+# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
+apiVersion: admissionregistration.k8s.io/v1
+kind: MutatingWebhookConfiguration
+metadata:
+ name: mutating-webhook-configuration
+ annotations:
+ cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: validating-webhook-configuration
+ annotations:
+ cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml
new file mode 100644
index 0000000..9cf2613
--- /dev/null
+++ b/config/webhook/kustomization.yaml
@@ -0,0 +1,6 @@
+resources:
+- manifests.yaml
+- service.yaml
+
+configurations:
+- kustomizeconfig.yaml
diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml
new file mode 100644
index 0000000..25e21e3
--- /dev/null
+++ b/config/webhook/kustomizeconfig.yaml
@@ -0,0 +1,25 @@
+# the following config is for teaching kustomize where to look at when substituting vars.
+# It requires kustomize v2.1.0 or newer to work properly.
+nameReference:
+- kind: Service
+ version: v1
+ fieldSpecs:
+ - kind: MutatingWebhookConfiguration
+ group: admissionregistration.k8s.io
+ path: webhooks/clientConfig/service/name
+ - kind: ValidatingWebhookConfiguration
+ group: admissionregistration.k8s.io
+ path: webhooks/clientConfig/service/name
+
+namespace:
+- kind: MutatingWebhookConfiguration
+ group: admissionregistration.k8s.io
+ path: webhooks/clientConfig/service/namespace
+ create: true
+- kind: ValidatingWebhookConfiguration
+ group: admissionregistration.k8s.io
+ path: webhooks/clientConfig/service/namespace
+ create: true
+
+varReference:
+- path: metadata/annotations
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
new file mode 100644
index 0000000..77bb19e
--- /dev/null
+++ b/config/webhook/manifests.yaml
@@ -0,0 +1,54 @@
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: MutatingWebhookConfiguration
+metadata:
+ creationTimestamp: null
+ name: mutating-webhook-configuration
+webhooks:
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook-service
+ namespace: system
+ path: /mutate-ds-apache-dolphinscheduler-dev-v1alpha1-dsmaster
+ failurePolicy: Fail
+ name: mdsmaster.kb.io
+ rules:
+ - apiGroups:
+ - ds.apache.dolphinscheduler.dev
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - dsmasters
+ sideEffects: None
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ creationTimestamp: null
+ name: validating-webhook-configuration
+webhooks:
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook-service
+ namespace: system
+ path: /validate-ds-apache-dolphinscheduler-dev-v1alpha1-dsmaster
+ failurePolicy: Fail
+ name: vdsmaster.kb.io
+ rules:
+ - apiGroups:
+ - ds.apache.dolphinscheduler.dev
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - dsmasters
+ sideEffects: None
diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml
new file mode 100644
index 0000000..3f638bd
--- /dev/null
+++ b/config/webhook/service.yaml
@@ -0,0 +1,13 @@
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: webhook-service
+ namespace: system
+spec:
+ ports:
+ - port: 443
+ protocol: TCP
+ targetPort: 9443
+ selector:
+ control-plane: controller-manager