From 48b0ce2724f9e9076c23d545d3505a3decc7f70e Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Tue, 15 Nov 2022 15:24:46 +0100 Subject: [PATCH 1/6] reclaimspace: correct path in PROJECT the path for the existing CR's like reclaimspace,networkfence and csinode object is not correct, this commit adds the correct path to the project. Signed-off-by: Madhu Rajanna --- PROJECT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PROJECT b/PROJECT index 545a52e39..d82099435 100644 --- a/PROJECT +++ b/PROJECT @@ -12,7 +12,7 @@ resources: domain: openshift.io group: csiaddons kind: CSIAddonsNode - path: github.com/csi-addons/kubernetes-csi-addons/api/v1alpha1 + path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -21,7 +21,7 @@ resources: domain: openshift.io group: csiaddons kind: ReclaimSpaceJob - path: github.com/csi-addons/kubernetes-csi-addons/api/v1alpha1 + path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -29,7 +29,7 @@ resources: domain: openshift.io group: csiaddons kind: NetworkFence - path: github.com/csi-addons/kubernetes-csi-addons/api/v1alpha1 + path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 - controller: true domain: openshift.io From 751825299100652bad6988ea2ca5c4556aced5b9 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Tue, 15 Nov 2022 15:26:10 +0100 Subject: [PATCH 2/6] reclaimspaceCronJob: add path to project add the missing path for the ReclaimSpaceCronJob in the PROJECT. Signed-off-by: Madhu Rajanna --- PROJECT | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECT b/PROJECT index d82099435..51b071aa5 100644 --- a/PROJECT +++ b/PROJECT @@ -35,6 +35,7 @@ resources: domain: openshift.io group: csiaddons kind: ReclaimSpaceCronJob + path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 - controller: true group: core From d9326d7af31aef127f41b8eb7daf48cb333da817 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Fri, 18 Nov 2022 11:46:35 +0100 Subject: [PATCH 3/6] webhook: add webhooks for reclaimspacejobs Add webhook for reclaimspacejobs object to avoid users from changing the PVC once created. Below is the command to generate webhook for reclaimspacejobs object ```bash $ operator-sdk create webhook --group csiaddons --version v1alpha1 --kind ReclaimSpaceJob --programmatic-validation ``` Signed-off-by: Madhu Rajanna --- PROJECT | 3 + .../v1alpha1/reclaimspacejob_webhook.go | 76 ++++++++++ apis/csiaddons/v1alpha1/webhook_suite_test.go | 135 ++++++++++++++++++ .../v1alpha1/zz_generated.deepcopy.go | 2 +- cmd/manager/main.go | 6 + config/webhook/manifests.yaml | 19 +++ deploy/controller/install-all-in-one.yaml | 19 +++ 7 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 apis/csiaddons/v1alpha1/reclaimspacejob_webhook.go create mode 100644 apis/csiaddons/v1alpha1/webhook_suite_test.go diff --git a/PROJECT b/PROJECT index 51b071aa5..c5ac55f01 100644 --- a/PROJECT +++ b/PROJECT @@ -23,6 +23,9 @@ resources: kind: ReclaimSpaceJob path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 + webhooks: + validation: true + webhookVersion: v1 - api: crdVersion: v1 controller: true diff --git a/apis/csiaddons/v1alpha1/reclaimspacejob_webhook.go b/apis/csiaddons/v1alpha1/reclaimspacejob_webhook.go new file mode 100644 index 000000000..b9e229a31 --- /dev/null +++ b/apis/csiaddons/v1alpha1/reclaimspacejob_webhook.go @@ -0,0 +1,76 @@ +/* +Copyright 2022 The Kubernetes-CSI-Addons Authors. + +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 ( + "errors" + + 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 rsjLog = logf.Log.WithName("reclaimspacejob-webhook") + +func (r *ReclaimSpaceJob) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-csiaddons-openshift-io-v1alpha1-reclaimspacejob,mutating=false,failurePolicy=fail,sideEffects=None,groups=csiaddons.openshift.io,resources=reclaimspacejobs,verbs=update,versions=v1alpha1,name=vreclaimspacejob.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &ReclaimSpaceJob{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceJob) ValidateCreate() error { + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceJob) ValidateUpdate(old runtime.Object) error { + rsjLog.Info("validate update", "name", r.Name) + + oldReclaimSpaceJob, ok := old.(*ReclaimSpaceJob) + if !ok { + return errors.New("error casting ReclaimSpaceJob object") + } + + var allErrs field.ErrorList + + if r.Spec.Target.PersistentVolumeClaim != oldReclaimSpaceJob.Spec.Target.PersistentVolumeClaim { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "target", "persistentVolumeClaim"), r.Spec.Target.PersistentVolumeClaim, "persistentVolumeClaim cannot be changed")) + } + + if len(allErrs) != 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "csiaddons.openshift.io", Kind: "ReclaimSpaceJob"}, + r.Name, allErrs) + } + + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceJob) ValidateDelete() error { + return nil +} diff --git a/apis/csiaddons/v1alpha1/webhook_suite_test.go b/apis/csiaddons/v1alpha1/webhook_suite_test.go new file mode 100644 index 000000000..f677d0e9a --- /dev/null +++ b/apis/csiaddons/v1alpha1/webhook_suite_test.go @@ -0,0 +1,135 @@ +/* +Copyright 2022 The Kubernetes-CSI-Addons Authors. + +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")}, + }, + } + + 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 = (&ReclaimSpaceJob{}).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/apis/csiaddons/v1alpha1/zz_generated.deepcopy.go b/apis/csiaddons/v1alpha1/zz_generated.deepcopy.go index 9a4f011cf..ac43c006f 100644 --- a/apis/csiaddons/v1alpha1/zz_generated.deepcopy.go +++ b/apis/csiaddons/v1alpha1/zz_generated.deepcopy.go @@ -24,7 +24,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/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. diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 702fe40ac..88c2b2373 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -162,7 +162,13 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "VolumeReplication") os.Exit(1) } + + if err = (&csiaddonsv1alpha1.ReclaimSpaceJob{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "ReclaimSpaceJob") + os.Exit(1) + } } + //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 3d82d08e4..837c09c9c 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -5,6 +5,25 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-csiaddons-openshift-io-v1alpha1-reclaimspacejob + failurePolicy: Fail + name: vreclaimspacejob.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - reclaimspacejobs + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/deploy/controller/install-all-in-one.yaml b/deploy/controller/install-all-in-one.yaml index 49591bb31..660396bd6 100644 --- a/deploy/controller/install-all-in-one.yaml +++ b/deploy/controller/install-all-in-one.yaml @@ -1417,6 +1417,25 @@ metadata: cert-manager.io/inject-ca-from: csi-addons-system/csi-addons-serving-cert name: csi-addons-validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: csi-addons-webhook-service + namespace: csi-addons-system + path: /validate-csiaddons-openshift-io-v1alpha1-reclaimspacejob + failurePolicy: Fail + name: vreclaimspacejob.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - reclaimspacejobs + sideEffects: None - admissionReviewVersions: - v1 clientConfig: From e071455c0d6a1bf202908ae1f110dffbaa9a5fc3 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Fri, 18 Nov 2022 13:16:40 +0100 Subject: [PATCH 4/6] webhook: add webhooks for reclaimSpacecronJob Add webhook for reclaimspacecronjobs object to avoid users from changing the PVC once created. Below is the command to generate webhook for reclaimspacecronjobs object ```bash $ operator-sdk create webhook --group csiaddons --version v1alpha1 --kind ReclaimSpaceCronJob --programmatic-validation ``` Signed-off-by: Madhu Rajanna --- PROJECT | 3 + .../v1alpha1/reclaimspacecronjob_webhook.go | 75 +++++++++++++++++++ apis/csiaddons/v1alpha1/webhook_suite_test.go | 3 + cmd/manager/main.go | 5 ++ config/webhook/manifests.yaml | 19 +++++ deploy/controller/install-all-in-one.yaml | 19 +++++ 6 files changed, 124 insertions(+) create mode 100644 apis/csiaddons/v1alpha1/reclaimspacecronjob_webhook.go diff --git a/PROJECT b/PROJECT index c5ac55f01..fc552a412 100644 --- a/PROJECT +++ b/PROJECT @@ -40,6 +40,9 @@ resources: kind: ReclaimSpaceCronJob path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 + webhooks: + validation: true + webhookVersion: v1 - controller: true group: core kind: PersistentVolumeClaim diff --git a/apis/csiaddons/v1alpha1/reclaimspacecronjob_webhook.go b/apis/csiaddons/v1alpha1/reclaimspacecronjob_webhook.go new file mode 100644 index 000000000..9281f2596 --- /dev/null +++ b/apis/csiaddons/v1alpha1/reclaimspacecronjob_webhook.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes-CSI-Addons Authors. + +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 ( + "errors" + + 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 rscjLog = logf.Log.WithName("reclaimspacecronjob-webhook") + +func (r *ReclaimSpaceCronJob) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-csiaddons-openshift-io-v1alpha1-reclaimspacecronjob,mutating=false,failurePolicy=fail,sideEffects=None,groups=csiaddons.openshift.io,resources=reclaimspacecronjobs,verbs=update,versions=v1alpha1,name=vreclaimspacecronjob.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &ReclaimSpaceCronJob{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceCronJob) ValidateCreate() error { + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceCronJob) ValidateUpdate(old runtime.Object) error { + rsjLog.Info("validate update", "name", r.Name) + + oldReclaimSpaceCronJob, ok := old.(*ReclaimSpaceCronJob) + if !ok { + return errors.New("error casting ReclaimSpaceCronJob object") + } + + var allErrs field.ErrorList + + if r.Spec.JobSpec.Spec.Target.PersistentVolumeClaim != oldReclaimSpaceCronJob.Spec.JobSpec.Spec.Target.PersistentVolumeClaim { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "jobTemplate", "spec", "target", "persistentVolumeClaim"), r.Spec.JobSpec.Spec.Target.PersistentVolumeClaim, "persistentVolumeClaim cannot be changed")) + } + + if len(allErrs) != 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "csiaddons.openshift.io", Kind: "ReclaimSpaceCronJob"}, + r.Name, allErrs) + } + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *ReclaimSpaceCronJob) ValidateDelete() error { + return nil +} diff --git a/apis/csiaddons/v1alpha1/webhook_suite_test.go b/apis/csiaddons/v1alpha1/webhook_suite_test.go index f677d0e9a..e1ff9f28b 100644 --- a/apis/csiaddons/v1alpha1/webhook_suite_test.go +++ b/apis/csiaddons/v1alpha1/webhook_suite_test.go @@ -105,6 +105,9 @@ var _ = BeforeSuite(func() { err = (&ReclaimSpaceJob{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&ReclaimSpaceCronJob{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 88c2b2373..a6aadce50 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -167,6 +167,11 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "ReclaimSpaceJob") os.Exit(1) } + + if err = (&csiaddonsv1alpha1.ReclaimSpaceCronJob{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "ReclaimSpaceCronJob") + os.Exit(1) + } } //+kubebuilder:scaffold:builder diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 837c09c9c..606589263 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -5,6 +5,25 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-csiaddons-openshift-io-v1alpha1-reclaimspacecronjob + failurePolicy: Fail + name: vreclaimspacecronjob.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - reclaimspacecronjobs + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/deploy/controller/install-all-in-one.yaml b/deploy/controller/install-all-in-one.yaml index 660396bd6..2f3d1e5b6 100644 --- a/deploy/controller/install-all-in-one.yaml +++ b/deploy/controller/install-all-in-one.yaml @@ -1417,6 +1417,25 @@ metadata: cert-manager.io/inject-ca-from: csi-addons-system/csi-addons-serving-cert name: csi-addons-validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: csi-addons-webhook-service + namespace: csi-addons-system + path: /validate-csiaddons-openshift-io-v1alpha1-reclaimspacecronjob + failurePolicy: Fail + name: vreclaimspacecronjob.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - reclaimspacecronjobs + sideEffects: None - admissionReviewVersions: - v1 clientConfig: From 17fd578217c1ddc535b2f570628239f3d24b7321 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Fri, 18 Nov 2022 14:10:49 +0100 Subject: [PATCH 5/6] webhook: add webhooks for networkfence Add webhook for networkfence object to avoid users from changing the driver,secrets and parameters once created. Below is the command to generate webhook for networkfence object ```bash $ operator-sdk create webhook --group csiaddons --version v1alpha1 --kind NetworkFence --programmatic-validation ``` Signed-off-by: Madhu Rajanna --- PROJECT | 3 + .../v1alpha1/networkfence_webhook.go | 88 +++++++++++++++++++ apis/csiaddons/v1alpha1/webhook_suite_test.go | 3 + cmd/manager/main.go | 5 ++ config/webhook/manifests.yaml | 19 ++++ deploy/controller/install-all-in-one.yaml | 19 ++++ 6 files changed, 137 insertions(+) create mode 100644 apis/csiaddons/v1alpha1/networkfence_webhook.go diff --git a/PROJECT b/PROJECT index fc552a412..2fa805b32 100644 --- a/PROJECT +++ b/PROJECT @@ -34,6 +34,9 @@ resources: kind: NetworkFence path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 + webhooks: + validation: true + webhookVersion: v1 - controller: true domain: openshift.io group: csiaddons diff --git a/apis/csiaddons/v1alpha1/networkfence_webhook.go b/apis/csiaddons/v1alpha1/networkfence_webhook.go new file mode 100644 index 000000000..0f4d69758 --- /dev/null +++ b/apis/csiaddons/v1alpha1/networkfence_webhook.go @@ -0,0 +1,88 @@ +/* +Copyright 2022 The Kubernetes-CSI-Addons Authors. + +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 ( + "errors" + "reflect" + + 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 nfLog = logf.Log.WithName("networkfence-webhook") + +func (n *NetworkFence) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(n). + Complete() +} + +//+kubebuilder:webhook:path=/validate-csiaddons-openshift-io-v1alpha1-networkfence,mutating=false,failurePolicy=fail,sideEffects=None,groups=csiaddons.openshift.io,resources=networkfences,verbs=update,versions=v1alpha1,name=vnetworkfence.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &NetworkFence{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (n *NetworkFence) ValidateCreate() error { + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (n *NetworkFence) ValidateUpdate(old runtime.Object) error { + nfLog.Info("validate update", "name", n.Name) + + oldNetworkFence, ok := old.(*NetworkFence) + if !ok { + return errors.New("error casting NetworkFence object") + } + + var allErrs field.ErrorList + if n.Spec.Driver != oldNetworkFence.Spec.Driver { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("driver"), n.Spec.Driver, "driver cannot be changed")) + } + + if reflect.DeepEqual(n.Spec.Parameters, oldNetworkFence.Spec.Parameters) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("parameters"), n.Spec.Parameters, "parameters cannot be changed")) + } + + if n.Spec.Secret.Name != oldNetworkFence.Spec.Secret.Name { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "secret", "name"), n.Spec.Secret, "secret name cannot be changed")) + } + + if n.Spec.Secret.Namespace != oldNetworkFence.Spec.Secret.Namespace { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "secret", "namespace"), n.Spec.Secret, "secret namespace cannot be changed")) + } + + if len(allErrs) != 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "csiaddons.openshift.io", Kind: "NetworkFence"}, + n.Name, allErrs) + } + + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (n *NetworkFence) ValidateDelete() error { + return nil +} diff --git a/apis/csiaddons/v1alpha1/webhook_suite_test.go b/apis/csiaddons/v1alpha1/webhook_suite_test.go index e1ff9f28b..ba95e8752 100644 --- a/apis/csiaddons/v1alpha1/webhook_suite_test.go +++ b/apis/csiaddons/v1alpha1/webhook_suite_test.go @@ -108,6 +108,9 @@ var _ = BeforeSuite(func() { err = (&ReclaimSpaceCronJob{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&NetworkFence{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/cmd/manager/main.go b/cmd/manager/main.go index a6aadce50..41c0698e8 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -172,6 +172,11 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "ReclaimSpaceCronJob") os.Exit(1) } + + if err = (&csiaddonsv1alpha1.NetworkFence{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "NetworkFence") + os.Exit(1) + } } //+kubebuilder:scaffold:builder diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 606589263..23fab52c2 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -5,6 +5,25 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-csiaddons-openshift-io-v1alpha1-networkfence + failurePolicy: Fail + name: vnetworkfence.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - networkfences + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/deploy/controller/install-all-in-one.yaml b/deploy/controller/install-all-in-one.yaml index 2f3d1e5b6..f5bcba738 100644 --- a/deploy/controller/install-all-in-one.yaml +++ b/deploy/controller/install-all-in-one.yaml @@ -1417,6 +1417,25 @@ metadata: cert-manager.io/inject-ca-from: csi-addons-system/csi-addons-serving-cert name: csi-addons-validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: csi-addons-webhook-service + namespace: csi-addons-system + path: /validate-csiaddons-openshift-io-v1alpha1-networkfence + failurePolicy: Fail + name: vnetworkfence.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - networkfences + sideEffects: None - admissionReviewVersions: - v1 clientConfig: From e2a80f8a63adba1d7ea01fa6a52f9c0d70a56982 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Fri, 18 Nov 2022 14:53:53 +0100 Subject: [PATCH 6/6] webhook: add webhooks for csiaddonsnode Add webhook for csiaddonsnode object to avoid users from changing the driver name, and NodeID once created. Below is the command to generate webhook for csiaddonsnode object ```bash $ operator-sdk create webhook --group csiaddons --version v1alpha1 --kind csiAddonsNode --programmatic-validation ``` Signed-off-by: Madhu Rajanna --- PROJECT | 3 + .../v1alpha1/csiaddonsnode_webhook.go | 80 +++++++++++++++++++ apis/csiaddons/v1alpha1/webhook_suite_test.go | 3 + cmd/manager/main.go | 5 ++ config/webhook/manifests.yaml | 19 +++++ deploy/controller/install-all-in-one.yaml | 19 +++++ 6 files changed, 129 insertions(+) create mode 100644 apis/csiaddons/v1alpha1/csiaddonsnode_webhook.go diff --git a/PROJECT b/PROJECT index 2fa805b32..ec3f8845b 100644 --- a/PROJECT +++ b/PROJECT @@ -14,6 +14,9 @@ resources: kind: CSIAddonsNode path: github.com/csi-addons/kubernetes-csi-addons/apis/csiaddons/v1alpha1 version: v1alpha1 + webhooks: + validation: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true diff --git a/apis/csiaddons/v1alpha1/csiaddonsnode_webhook.go b/apis/csiaddons/v1alpha1/csiaddonsnode_webhook.go new file mode 100644 index 000000000..34da55555 --- /dev/null +++ b/apis/csiaddons/v1alpha1/csiaddonsnode_webhook.go @@ -0,0 +1,80 @@ +/* +Copyright 2022 The Kubernetes-CSI-Addons Authors. + +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 ( + "errors" + + 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 csnLog = logf.Log.WithName("csiaddonsnode-webhook") + +func (c *CSIAddonsNode) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(c). + Complete() +} + +//+kubebuilder:webhook:path=/validate-csiaddons-openshift-io-v1alpha1-csiaddonsnode,mutating=false,failurePolicy=fail,sideEffects=None,groups=csiaddons.openshift.io,resources=csiaddonsnodes,verbs=update,versions=v1alpha1,name=vcsiaddonsnode.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &CSIAddonsNode{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (c *CSIAddonsNode) ValidateCreate() error { + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (c *CSIAddonsNode) ValidateUpdate(old runtime.Object) error { + csnLog.Info("validate update", "name", c.Name) + + oldCSIAddonsNode, ok := old.(*CSIAddonsNode) + if !ok { + return errors.New("error casting CSIAddonsNode object") + } + + var allErrs field.ErrorList + + if c.Spec.Driver.NodeID != oldCSIAddonsNode.Spec.Driver.NodeID { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "driver", "nodeID"), c.Spec.Driver.NodeID, "nodeID cannot be updated")) + } + + if c.Spec.Driver.Name != oldCSIAddonsNode.Spec.Driver.Name { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "driver", "name"), c.Spec.Driver.Name, "name cannot be updated")) + } + + if len(allErrs) != 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "csiaddons.openshift.io", Kind: "CSIAddonsNode"}, + c.Name, allErrs) + } + + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *CSIAddonsNode) ValidateDelete() error { + return nil +} diff --git a/apis/csiaddons/v1alpha1/webhook_suite_test.go b/apis/csiaddons/v1alpha1/webhook_suite_test.go index ba95e8752..1a31a90ed 100644 --- a/apis/csiaddons/v1alpha1/webhook_suite_test.go +++ b/apis/csiaddons/v1alpha1/webhook_suite_test.go @@ -111,6 +111,9 @@ var _ = BeforeSuite(func() { err = (&NetworkFence{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&CSIAddonsNode{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 41c0698e8..e58f2674e 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -177,6 +177,11 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "NetworkFence") os.Exit(1) } + + if err = (&csiaddonsv1alpha1.CSIAddonsNode{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "CSIAddonsNode") + os.Exit(1) + } } //+kubebuilder:scaffold:builder diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 23fab52c2..53462ffc9 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -5,6 +5,25 @@ metadata: creationTimestamp: null name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-csiaddons-openshift-io-v1alpha1-csiaddonsnode + failurePolicy: Fail + name: vcsiaddonsnode.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - csiaddonsnodes + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/deploy/controller/install-all-in-one.yaml b/deploy/controller/install-all-in-one.yaml index f5bcba738..1836b72cd 100644 --- a/deploy/controller/install-all-in-one.yaml +++ b/deploy/controller/install-all-in-one.yaml @@ -1417,6 +1417,25 @@ metadata: cert-manager.io/inject-ca-from: csi-addons-system/csi-addons-serving-cert name: csi-addons-validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: csi-addons-webhook-service + namespace: csi-addons-system + path: /validate-csiaddons-openshift-io-v1alpha1-csiaddonsnode + failurePolicy: Fail + name: vcsiaddonsnode.kb.io + rules: + - apiGroups: + - csiaddons.openshift.io + apiVersions: + - v1alpha1 + operations: + - UPDATE + resources: + - csiaddonsnodes + sideEffects: None - admissionReviewVersions: - v1 clientConfig: