From 1e6c21cc2886c443bb5b645f9ee1e23c5f6b133e Mon Sep 17 00:00:00 2001 From: changzhen Date: Thu, 8 Jul 2021 21:26:39 +0800 Subject: [PATCH] mutate policy's ResourceSelectors in webhook Signed-off-by: changzhen --- .../mcs/service_import_controller.go | 31 ++++++++++-- pkg/util/constants.go | 7 ++- pkg/util/helper/policy.go | 47 +++++++++++++++++++ .../clusterpropagationpolicy/mutating.go | 5 ++ pkg/webhook/propagationpolicy/mutating.go | 7 ++- 5 files changed, 89 insertions(+), 8 deletions(-) diff --git a/pkg/controllers/mcs/service_import_controller.go b/pkg/controllers/mcs/service_import_controller.go index 3ea865059..87a8de660 100644 --- a/pkg/controllers/mcs/service_import_controller.go +++ b/pkg/controllers/mcs/service_import_controller.go @@ -32,7 +32,7 @@ func (c *ServiceImportController) Reconcile(ctx context.Context, req controllerr svcImport := &mcsv1alpha1.ServiceImport{} if err := c.Client.Get(context.TODO(), req.NamespacedName, svcImport); err != nil { if errors.IsNotFound(err) { - return controllerruntime.Result{}, nil + return c.deleteDerivedService(req.NamespacedName) } return controllerruntime.Result{Requeue: true}, err @@ -50,14 +50,35 @@ func (c *ServiceImportController) SetupWithManager(mgr controllerruntime.Manager return controllerruntime.NewControllerManagedBy(mgr).For(&mcsv1alpha1.ServiceImport{}).Complete(c) } +func (c *ServiceImportController) deleteDerivedService(svcImport types.NamespacedName) (controllerruntime.Result, error) { + derivedSvc := &corev1.Service{} + derivedSvcNamespacedName := types.NamespacedName{ + Namespace: svcImport.Namespace, + Name: names.GenerateDerivedServiceName(svcImport.Name), + } + err := c.Client.Get(context.TODO(), derivedSvcNamespacedName, derivedSvc) + if err != nil { + if errors.IsNotFound(err) { + return controllerruntime.Result{}, nil + } + + return controllerruntime.Result{Requeue: true}, err + } + + err = c.Client.Delete(context.TODO(), derivedSvc) + if err != nil { + klog.Errorf("Delete derived service(%s) failed, Error: %v", derivedSvcNamespacedName, err) + return controllerruntime.Result{Requeue: true}, err + } + + return controllerruntime.Result{}, nil +} + func (c *ServiceImportController) deriveServiceFromServiceImport(svcImport *mcsv1alpha1.ServiceImport) (controllerruntime.Result, error) { newDerivedService := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Namespace: svcImport.Namespace, Name: names.GenerateDerivedServiceName(svcImport.Name), - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(svcImport, svcImport.GroupVersionKind()), - }, }, Spec: corev1.ServiceSpec{ Type: corev1.ServiceTypeClusterIP, @@ -77,7 +98,7 @@ func (c *ServiceImportController) deriveServiceFromServiceImport(svcImport *mcsv return controllerruntime.Result{Requeue: true}, err } - return controllerruntime.Result{}, nil + return c.updateServiceStatus(svcImport, newDerivedService) } return controllerruntime.Result{Requeue: true}, err diff --git a/pkg/util/constants.go b/pkg/util/constants.go index bce22b49f..8e19c9e11 100644 --- a/pkg/util/constants.go +++ b/pkg/util/constants.go @@ -84,10 +84,13 @@ const ( ReplicaSetKind = "ReplicaSet" // StatefulSetKind indicates the target resource is a statefulset StatefulSetKind = "StatefulSet" - // ServiceExportKind indicates the target resource is a serviceexport - ServiceExportKind = "ServiceExport" // EndpointSliceKind indicates the target resource is a endpointslice EndpointSliceKind = "EndpointSlice" + + // ServiceExportKind indicates the target resource is a serviceexport crd + ServiceExportKind = "ServiceExport" + // ServiceImportKind indicates the target resource is a serviceimport crd + ServiceImportKind = "ServiceImport" ) // Define resource filed diff --git a/pkg/util/helper/policy.go b/pkg/util/helper/policy.go index 30c1e1012..6485437f0 100644 --- a/pkg/util/helper/policy.go +++ b/pkg/util/helper/policy.go @@ -3,10 +3,14 @@ package helper import ( "fmt" + discoveryv1beta1 "k8s.io/api/discovery/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" + "github.com/karmada-io/karmada/pkg/util" + "github.com/karmada-io/karmada/pkg/util/names" ) // DenyReasonResourceSelectorsModify constructs a reason indicating that modify ResourceSelectors is not allowed. @@ -73,3 +77,46 @@ func IsDependentClusterOverridesPresent(c client.Client, policy *policyv1alpha1. return true, nil } + +// GetFollowedResourceSelectorsWhenMatchServiceImport get followed derived-service and endpointSlices resource selectors +// when policy's ResourceSelectors contains ResourceSelector, whose kind is ServiceImport. +func GetFollowedResourceSelectorsWhenMatchServiceImport(resourceSelectors []policyv1alpha1.ResourceSelector) []policyv1alpha1.ResourceSelector { + var addedResourceSelectors []policyv1alpha1.ResourceSelector + + for _, resourceSelector := range resourceSelectors { + if resourceSelector.Kind != util.ServiceImportKind { + continue + } + + if resourceSelector.Namespace == "" || resourceSelector.Name == "" { + continue + } + + addedResourceSelectors = append(addedResourceSelectors, GenerateResourceSelectorForServiceImport(resourceSelector)...) + } + + return addedResourceSelectors +} + +// GenerateResourceSelectorForServiceImport generates resource selectors for ServiceImport. +func GenerateResourceSelectorForServiceImport(svcImport policyv1alpha1.ResourceSelector) []policyv1alpha1.ResourceSelector { + derivedServiceName := names.GenerateDerivedServiceName(svcImport.Name) + return []policyv1alpha1.ResourceSelector{ + { + APIVersion: "v1", + Kind: util.ServiceKind, + Namespace: svcImport.Namespace, + Name: derivedServiceName, + }, + { + APIVersion: "discovery.k8s.io/v1beta1", + Kind: util.EndpointSliceKind, + Namespace: svcImport.Namespace, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + discoveryv1beta1.LabelServiceName: derivedServiceName, + }, + }, + }, + } +} diff --git a/pkg/webhook/clusterpropagationpolicy/mutating.go b/pkg/webhook/clusterpropagationpolicy/mutating.go index bb2653971..bb5ad545b 100644 --- a/pkg/webhook/clusterpropagationpolicy/mutating.go +++ b/pkg/webhook/clusterpropagationpolicy/mutating.go @@ -38,6 +38,11 @@ func (a *MutatingAdmission) Handle(ctx context.Context, req admission.Request) a return admission.Errored(http.StatusBadRequest, fmt.Errorf("ClusterPropagationPolicy's name should be no more than %d characters", validation.LabelValueMaxLength)) } + addedResourceSelectors := helper.GetFollowedResourceSelectorsWhenMatchServiceImport(policy.Spec.ResourceSelectors) + if addedResourceSelectors != nil { + policy.Spec.ResourceSelectors = append(policy.Spec.ResourceSelectors, addedResourceSelectors...) + } + marshaledBytes, err := json.Marshal(policy) if err != nil { return admission.Errored(http.StatusInternalServerError, err) diff --git a/pkg/webhook/propagationpolicy/mutating.go b/pkg/webhook/propagationpolicy/mutating.go index 01456587f..0c28db571 100644 --- a/pkg/webhook/propagationpolicy/mutating.go +++ b/pkg/webhook/propagationpolicy/mutating.go @@ -41,11 +41,16 @@ func (a *MutatingAdmission) Handle(ctx context.Context, req admission.Request) a } if len(policy.Name) > validation.LabelValueMaxLength { - return admission.Errored(http.StatusBadRequest, fmt.Errorf("PropagationPolicy's name and should be no more than %d characters", validation.LabelValueMaxLength)) + return admission.Errored(http.StatusBadRequest, fmt.Errorf("PropagationPolicy's name should be no more than %d characters", validation.LabelValueMaxLength)) } // Set default spread constraints if both 'SpreadByField' and 'SpreadByLabel' not set. helper.SetDefaultSpreadConstraints(policy.Spec.Placement.SpreadConstraints) + addedResourceSelectors := helper.GetFollowedResourceSelectorsWhenMatchServiceImport(policy.Spec.ResourceSelectors) + if addedResourceSelectors != nil { + policy.Spec.ResourceSelectors = append(policy.Spec.ResourceSelectors, addedResourceSelectors...) + } + marshaledBytes, err := json.Marshal(policy) if err != nil { return admission.Errored(http.StatusInternalServerError, err)