Skip to content

Commit

Permalink
Update ClusterSet and ClusterClaim webhooks (#4043)
Browse files Browse the repository at this point in the history
1. Add a ClusterSet webhook to make Leader's `clusterID` immutable, and
   allow only one ClusterSet in mc-controller's  Namespace.
2. Update ClusterClaim webhook to make the `value` field
   (ClusterID/ClusterSetID) immutable
3. Remove the unused mutate webhook of ClusterClaim

Signed-off-by: Lan Luo <[email protected]>
  • Loading branch information
luolanzone authored Jul 25, 2022
1 parent d9c4629 commit 13f470e
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 57 deletions.
16 changes: 9 additions & 7 deletions multicluster/apis/multicluster/v1alpha2/clusterclaim_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ func (r *ClusterClaim) SetupWebhookWithManager(mgr ctrl.Manager) error {
Complete()
}

//+kubebuilder:webhook:path=/mutate-multicluster-crd-antrea-io-v1alpha2-clusterclaim,mutating=true,failurePolicy=fail,sideEffects=None,groups=multicluster.crd.antrea.io,resources=clusterclaims,verbs=create;update,versions=v1alpha2,name=mclusterclaim.kb.io,admissionReviewVersions={v1,v1beta1}

var _ webhook.Defaulter = &ClusterClaim{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
Expand All @@ -49,9 +47,9 @@ var _ webhook.Validator = &ClusterClaim{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *ClusterClaim) ValidateCreate() error {
klog.InfoS("validate create", "name", r.Name)
klog.InfoS("Validate create", "name", r.Name)
if r.Name != WellKnownClusterClaimClusterSet && r.Name != WellKnownClusterClaimID {
err := fmt.Errorf("The name %s is not valid, only 'id.k8s.io' and 'clusterset.k8s.io' are valid names for ClusterClaim", r.Name)
err := fmt.Errorf("name %s is not valid, only 'id.k8s.io' and 'clusterset.k8s.io' are valid names for ClusterClaim", r.Name)
return err
}

Expand All @@ -60,15 +58,19 @@ func (r *ClusterClaim) ValidateCreate() error {

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *ClusterClaim) ValidateUpdate(old runtime.Object) error {
klog.InfoS("validate update", "name", r.Name)
klog.InfoS("Validate update", "name", r.Name)

// TODO(user): fill in your validation logic upon object update.
oldClusterClaim := old.(*ClusterClaim)
if r.Value != oldClusterClaim.Value {
err := fmt.Errorf("the field 'value' is immutable")
return err
}
return nil
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *ClusterClaim) ValidateDelete() error {
klog.InfoS("validate delete", "name", r.Name)
klog.InfoS("Validate delete", "name", r.Name)

// TODO(user): fill in your validation logic upon object deletion.
return nil
Expand Down
30 changes: 15 additions & 15 deletions multicluster/build/yamls/antrea-multicluster-leader-namespaced.yml
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,25 @@ webhooks:
resources:
- resourceexports
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
labels:
app: antrea
name: antrea-multicluster-antrea-mc-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: antrea-mc-webhook-service
namespace: antrea-multicluster
path: /mutate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
path: /validate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
failurePolicy: Fail
name: mclusterclaim.kb.io
name: vclusterclaim.kb.io
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: antrea-multicluster
Expand All @@ -465,38 +474,29 @@ webhooks:
resources:
- clusterclaims
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
labels:
app: antrea
name: antrea-multicluster-antrea-mc-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: antrea-mc-webhook-service
namespace: antrea-multicluster
path: /validate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
path: /validate-multicluster-crd-antrea-io-v1alpha1-clusterset
failurePolicy: Fail
name: vclusterclaim.kb.io
name: vclusterset.kb.io
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: antrea-multicluster
rules:
- apiGroups:
- multicluster.crd.antrea.io
apiVersions:
- v1alpha2
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clusterclaims
- clustersets
sideEffects: None
- admissionReviewVersions:
- v1
Expand Down
28 changes: 14 additions & 14 deletions multicluster/build/yamls/antrea-multicluster-member.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,14 @@ metadata:
labels:
app: antrea
name: antrea-mc-mutating-webhook-configuration
webhooks: []
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app: antrea
name: antrea-mc-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
Expand All @@ -1049,9 +1057,9 @@ webhooks:
service:
name: antrea-mc-webhook-service
namespace: kube-system
path: /mutate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
path: /validate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
failurePolicy: Fail
name: mclusterclaim.kb.io
name: vclusterclaim.kb.io
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
Expand All @@ -1066,35 +1074,27 @@ webhooks:
resources:
- clusterclaims
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app: antrea
name: antrea-mc-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: antrea-mc-webhook-service
namespace: kube-system
path: /validate-multicluster-crd-antrea-io-v1alpha2-clusterclaim
path: /validate-multicluster-crd-antrea-io-v1alpha1-clusterset
failurePolicy: Fail
name: vclusterclaim.kb.io
name: vclusterset.kb.io
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
rules:
- apiGroups:
- multicluster.crd.antrea.io
apiVersions:
- v1alpha2
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clusterclaims
- clustersets
sideEffects: None
81 changes: 81 additions & 0 deletions multicluster/cmd/multicluster-controller/clusterset_webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
Copyright 2022 Antrea 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 main

import (
"context"
"encoding/json"
"fmt"
"net/http"

"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

mcv1alpha1 "antrea.io/antrea/multicluster/apis/multicluster/v1alpha1"
)

//+kubebuilder:webhook:path=/validate-multicluster-crd-antrea-io-v1alpha1-clusterset,mutating=false,failurePolicy=fail,sideEffects=None,groups=multicluster.crd.antrea.io,resources=clustersets,verbs=create;update,versions=v1alpha1,name=vclusterset.kb.io,admissionReviewVersions={v1,v1beta1}

// ClusterSet validator
type clusterSetValidator struct {
Client client.Client
decoder *admission.Decoder
namespace string
}

// Handle handles admission requests.
func (v *clusterSetValidator) Handle(ctx context.Context, req admission.Request) admission.Response {
clusterSet := &mcv1alpha1.ClusterSet{}
err := v.decoder.Decode(req, clusterSet)
if err != nil {
klog.ErrorS(err, "Error while decoding ClusterSet", "ClusterSet", req.Namespace+"/"+req.Name)
return admission.Errored(http.StatusBadRequest, err)
}

oldClusterSet := &mcv1alpha1.ClusterSet{}
if req.OldObject.Raw != nil {
if err := json.Unmarshal(req.OldObject.Raw, &oldClusterSet); err != nil {
klog.ErrorS(err, "Error while decoding old ClusterSet", "ClusterSet", klog.KObj(clusterSet))
return admission.Errored(http.StatusBadRequest, err)
}
if oldClusterSet.Spec.Leaders[0].ClusterID != clusterSet.Spec.Leaders[0].ClusterID {
klog.ErrorS(err, "the field 'clusterID' is immutable", "ClusterSet", klog.KObj(clusterSet))
return admission.Denied("the field 'clusterID' is immutable")
}
return admission.Allowed("")
}

// Check if there is any existing ClusterSet.
clusterSetList := &mcv1alpha1.ClusterSetList{}
if err := v.Client.List(context.TODO(), clusterSetList, client.InNamespace(v.namespace)); err != nil {
klog.ErrorS(err, "Error reading ClusterSet", "Namespace", v.namespace)
return admission.Errored(http.StatusPreconditionFailed, err)
}

if len(clusterSetList.Items) > 0 {
err := fmt.Errorf("multiple ClusterSets in a Namespace are not allowed")
klog.ErrorS(err, "ClusterSet", klog.KObj(clusterSet), "Namespace", v.namespace)
return admission.Errored(http.StatusPreconditionFailed, err)
}
return admission.Allowed("")
}

func (v *clusterSetValidator) InjectDecoder(d *admission.Decoder) error {
v.decoder = d
return nil
}
Loading

0 comments on commit 13f470e

Please sign in to comment.