From 29250da4873364df63782b4d53d189e9d2e7aa32 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Wed, 17 Jan 2024 12:01:36 +0800 Subject: [PATCH] bump: webhook to 0.1.3 Signed-off-by: Jack Yu --- cmd/webhook/main.go | 41 ++- go.mod | 4 +- go.sum | 8 +- pkg/webhook/clusternetwork/validator.go | 13 +- pkg/webhook/nad/mutator.go | 39 ++- pkg/webhook/nad/validator.go | 19 +- pkg/webhook/vlanconfig/mutator.go | 35 +- pkg/webhook/vlanconfig/validator.go | 21 +- .../harvester/webhook/pkg/clients/clients.go | 8 +- .../harvester/webhook/pkg/config/config.go | 2 +- .../{types => server/admission}/admission.go | 25 +- .../{types => server/admission}/mutator.go | 2 +- .../{types => server/admission}/request.go | 2 +- .../{types => server/admission}/resource.go | 2 +- .../{types => server/admission}/validator.go | 2 +- .../pkg/server/conversion/conversion.go | 122 +++++++ .../harvester/webhook/pkg/server/mutation.go | 30 -- .../harvester/webhook/pkg/server/server.go | 326 ++++++++++++------ .../webhook/pkg/server/validation.go | 21 -- .../rancher/wrangler/pkg/apply/desiredset.go | 1 - .../wrangler/pkg/apply/desiredset_apply.go | 2 +- .../wrangler/pkg/condition/condition.go | 1 - .../wrangler/pkg/controller-gen/main.go | 7 +- .../wrangler/pkg/data/convert/convert.go | 5 +- .../rancher/wrangler/pkg/generic/factory.go | 2 +- .../rancher/wrangler/pkg/kubeconfig/loader.go | 3 +- .../wrangler/pkg/schemas/mappers/move.go | 2 +- .../wrangler/pkg/schemas/reflection.go | 4 +- .../wrangler/pkg/summary/summarized.go | 2 - .../rancher/wrangler/pkg/webhook/router.go | 5 +- vendor/modules.txt | 9 +- 31 files changed, 491 insertions(+), 274 deletions(-) rename vendor/github.com/harvester/webhook/pkg/{types => server/admission}/admission.go (85%) rename vendor/github.com/harvester/webhook/pkg/{types => server/admission}/mutator.go (97%) rename vendor/github.com/harvester/webhook/pkg/{types => server/admission}/request.go (98%) rename vendor/github.com/harvester/webhook/pkg/{types => server/admission}/resource.go (98%) rename vendor/github.com/harvester/webhook/pkg/{types => server/admission}/validator.go (99%) create mode 100644 vendor/github.com/harvester/webhook/pkg/server/conversion/conversion.go delete mode 100644 vendor/github.com/harvester/webhook/pkg/server/mutation.go delete mode 100644 vendor/github.com/harvester/webhook/pkg/server/validation.go diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index 44592de6..9795656c 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -2,16 +2,9 @@ package main import ( "context" + "fmt" "os" - ctlcni "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io" - ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1" - ctlkubevirt "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io" - ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" - "github.com/harvester/harvester/pkg/indexeres" - "github.com/harvester/webhook/pkg/config" - "github.com/harvester/webhook/pkg/server" - "github.com/harvester/webhook/pkg/types" ctlcore "github.com/rancher/wrangler/pkg/generated/controllers/core" ctlcorev1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1" "github.com/rancher/wrangler/pkg/kubeconfig" @@ -22,11 +15,19 @@ import ( "k8s.io/client-go/rest" kubevirtv1 "kubevirt.io/api/core/v1" - ctlnetwork "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io" - ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1" "github.com/harvester/harvester-network-controller/pkg/webhook/clusternetwork" "github.com/harvester/harvester-network-controller/pkg/webhook/nad" "github.com/harvester/harvester-network-controller/pkg/webhook/vlanconfig" + ctlcni "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io" + ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1" + ctlkubevirt "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io" + ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" + "github.com/harvester/harvester/pkg/indexeres" + "github.com/harvester/webhook/pkg/config" + "github.com/harvester/webhook/pkg/server" + + ctlnetwork "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io" + ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1" ) const name = "harvester-network-webhook" @@ -107,15 +108,23 @@ func run(ctx context.Context, cfg *rest.Config, options *config.Options) error { return err } - webhookServer := server.New(ctx, cfg, name, options) - admitters := []types.Admitter{ - types.Validator2Admitter(clusternetwork.NewCnValidator(c.vcCache)), - types.Validator2Admitter(nad.NewNadValidator(c.vmiCache)), - types.Validator2Admitter(vlanconfig.NewVlanConfigValidator(c.nadCache, c.vcCache, c.vsCache, c.vmiCache)), + webhookServer := server.NewWebhookServer(ctx, cfg, name, options) + + if err := webhookServer.RegisterMutators( nad.NewNadMutator(c.cnCache, c.vcCache), vlanconfig.NewVlanConfigMutator(c.nodeCache), + ); err != nil { + return fmt.Errorf("failed to register mutators: %v", err) } - webhookServer.Register(admitters) + + if err := webhookServer.RegisterValidators( + clusternetwork.NewCnValidator(c.vcCache), + nad.NewNadValidator(c.vmiCache), + vlanconfig.NewVlanConfigValidator(c.nadCache, c.vcCache, c.vsCache, c.vmiCache), + ); err != nil { + return fmt.Errorf("failed to register validators: %v", err) + } + if err := webhookServer.Start(); err != nil { return err } diff --git a/go.mod b/go.mod index 790b6b13..f122b617 100644 --- a/go.mod +++ b/go.mod @@ -67,11 +67,11 @@ require ( github.com/deckarep/golang-set/v2 v2.1.0 github.com/go-ping/ping v0.0.0-20211014180314-6e2b003bffdd github.com/harvester/harvester v1.1.2-rc8 - github.com/harvester/webhook v0.1.2 + github.com/harvester/webhook v0.1.3 github.com/insomniacslk/dhcp v0.0.0-20201112113307-4de412bc85d8 github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20200331171230-d50e42f2b669 github.com/rancher/lasso v0.0.0-20221227210133-6ea88ca2fbcc - github.com/rancher/wrangler v1.1.0 + github.com/rancher/wrangler v1.1.1 github.com/sirupsen/logrus v1.9.0 github.com/tidwall/sjson v1.2.5 github.com/urfave/cli v1.22.9 diff --git a/go.sum b/go.sum index 4257341d..8fef40bb 100644 --- a/go.sum +++ b/go.sum @@ -1119,8 +1119,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/harvester/harvester v1.1.2-rc8 h1:kw4OuCdHn2O/vVX5m0ZjUsOFfYZtfXhiOCd8/Ex6VNE= github.com/harvester/harvester v1.1.2-rc8/go.mod h1:0u5p38ODTd4L/ZQtgyjoB851Jg8YcGTK29rmqGtA6To= -github.com/harvester/webhook v0.1.2 h1:fo3PXiDBAEl0Fq2AfOkblMIRihp5Y91wOatP1AERX74= -github.com/harvester/webhook v0.1.2/go.mod h1:vveGwEGuHUN2lEHbNrZKisiMYBTMakrNd0cLSnRkEGI= +github.com/harvester/webhook v0.1.3 h1:rPdpOikIFWTRQGidgWaAUoUc/zgv0E5EzjX8MF3Fi8A= +github.com/harvester/webhook v0.1.3/go.mod h1:vfRPB26WHSPxMF/ONpUVzaEaewTUxpP9qAqu1ZyonR0= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1496,8 +1496,8 @@ github.com/rancher/wrangler v0.6.2-0.20200820173016-2068de651106/go.mod h1:iKqQc github.com/rancher/wrangler v0.8.3/go.mod h1:dKEaHNB4izxmPUtpq1Hvr3z3Oh+9k5pCZyFO9sUhlaY= github.com/rancher/wrangler v0.8.10/go.mod h1:Lte9WjPtGYxYacIWeiS9qawvu2R4NujFU9xuXWJvc/0= github.com/rancher/wrangler v0.8.11-0.20211214201934-f5aa5d9f2e81/go.mod h1:Lte9WjPtGYxYacIWeiS9qawvu2R4NujFU9xuXWJvc/0= -github.com/rancher/wrangler v1.1.0 h1:1VWistON261oKmCPF5fOPMWb/YwjgEciO9pCw5Z0mzQ= -github.com/rancher/wrangler v1.1.0/go.mod h1:lQorqAAIMkNWteece1GiuwZTmMqkaVTXL5qjiiPVDxQ= +github.com/rancher/wrangler v1.1.1 h1:wmqUwqc2M7ADfXnBCJTFkTB5ZREWpD78rnZMzmxwMvM= +github.com/rancher/wrangler v1.1.1/go.mod h1:ioVbKupzcBOdzsl55MvEDN0R1wdGggj8iNCYGFI5JvM= github.com/rancher/wrangler-api v0.6.1-0.20200427172631-a7c2f09b783e/go.mod h1:2lcWR98q8HU3U4mVETnXc8quNG0uXxrt8vKd6cAa/30= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= diff --git a/pkg/webhook/clusternetwork/validator.go b/pkg/webhook/clusternetwork/validator.go index 3f67699b..d808c0c5 100644 --- a/pkg/webhook/clusternetwork/validator.go +++ b/pkg/webhook/clusternetwork/validator.go @@ -3,11 +3,12 @@ package clusternetwork import ( "fmt" - "github.com/harvester/webhook/pkg/types" admissionregv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "github.com/harvester/webhook/pkg/server/admission" + networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1" ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1" "github.com/harvester/harvester-network-controller/pkg/utils" @@ -18,11 +19,11 @@ const ( ) type CnValidator struct { - types.DefaultValidator + admission.DefaultValidator vcCache ctlnetworkv1.VlanConfigCache } -var _ types.Validator = &CnValidator{} +var _ admission.Validator = &CnValidator{} func NewCnValidator(vcCache ctlnetworkv1.VlanConfigCache) *CnValidator { validator := &CnValidator{ @@ -31,7 +32,7 @@ func NewCnValidator(vcCache ctlnetworkv1.VlanConfigCache) *CnValidator { return validator } -func (c *CnValidator) Delete(_ *types.Request, oldObj runtime.Object) error { +func (c *CnValidator) Delete(_ *admission.Request, oldObj runtime.Object) error { cn := oldObj.(*networkv1.ClusterNetwork) if cn.Name == utils.ManagementClusterNetworkName { @@ -57,8 +58,8 @@ func (c *CnValidator) Delete(_ *types.Request, oldObj runtime.Object) error { return nil } -func (c *CnValidator) Resource() types.Resource { - return types.Resource{ +func (c *CnValidator) Resource() admission.Resource { + return admission.Resource{ Names: []string{"clusternetworks"}, Scope: admissionregv1.ClusterScope, APIGroup: networkv1.SchemeGroupVersion.Group, diff --git a/pkg/webhook/nad/mutator.go b/pkg/webhook/nad/mutator.go index 9e2053c4..cebba9e3 100644 --- a/pkg/webhook/nad/mutator.go +++ b/pkg/webhook/nad/mutator.go @@ -6,7 +6,6 @@ import ( "reflect" "strconv" - "github.com/harvester/webhook/pkg/types" cniv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" "github.com/tidwall/sjson" admissionregv1 "k8s.io/api/admissionregistration/v1" @@ -14,16 +13,18 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog" + "github.com/harvester/webhook/pkg/server/admission" + networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1" ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1" "github.com/harvester/harvester-network-controller/pkg/network/iface" "github.com/harvester/harvester-network-controller/pkg/utils" ) -var _ types.Mutator = &Mutator{} +var _ admission.Mutator = &Mutator{} type Mutator struct { - types.DefaultMutator + admission.DefaultMutator cnCache ctlnetworkv1.ClusterNetworkCache vcCache ctlnetworkv1.VlanConfigCache } @@ -36,7 +37,7 @@ func NewNadMutator(cnCache ctlnetworkv1.ClusterNetworkCache, } } -func (m *Mutator) Create(_ *types.Request, newObj runtime.Object) (types.Patch, error) { +func (m *Mutator) Create(_ *admission.Request, newObj runtime.Object) (admission.Patch, error) { nad := newObj.(*cniv1.NetworkAttachmentDefinition) patch, err := m.patchMTU(nad.Spec.Config) @@ -47,7 +48,7 @@ func (m *Mutator) Create(_ *types.Request, newObj runtime.Object) (types.Patch, return patch, nil } -func (m *Mutator) Update(_ *types.Request, oldObj, newObj runtime.Object) (types.Patch, error) { +func (m *Mutator) Update(_ *admission.Request, oldObj, newObj runtime.Object) (admission.Patch, error) { oldNad := oldObj.(*cniv1.NetworkAttachmentDefinition) newNad := newObj.(*cniv1.NetworkAttachmentDefinition) @@ -80,8 +81,8 @@ func (m *Mutator) Update(_ *types.Request, oldObj, newObj runtime.Object) (types return append(patch, annotationPatch...), nil } -func (m *Mutator) Resource() types.Resource { - return types.Resource{ +func (m *Mutator) Resource() admission.Resource { + return admission.Resource{ Names: []string{"network-attachment-definitions"}, Scope: admissionregv1.NamespacedScope, APIGroup: cniv1.SchemeGroupVersion.Group, @@ -94,7 +95,7 @@ func (m *Mutator) Resource() types.Resource { } } -func (m *Mutator) ensureLabels(nad *cniv1.NetworkAttachmentDefinition, oldConf, newConf *utils.NetConf) (types.Patch, error) { +func (m *Mutator) ensureLabels(nad *cniv1.NetworkAttachmentDefinition, oldConf, newConf *utils.NetConf) (admission.Patch, error) { labels := nad.Labels if labels == nil { labels = make(map[string]string) @@ -130,16 +131,16 @@ func (m *Mutator) ensureLabels(nad *cniv1.NetworkAttachmentDefinition, oldConf, labels[utils.KeyNetworkReady] = utils.ValueFalse } - return types.Patch{ - types.PatchOp{ - Op: types.PatchOpReplace, + return admission.Patch{ + admission.PatchOp{ + Op: admission.PatchOpReplace, Path: "/metadata/labels", Value: labels, }}, nil } // If the vlan or bridge name is changed, we need to tag the route annotation outdated -func tagRouteOutdated(nad *cniv1.NetworkAttachmentDefinition, oldConf, newConf *utils.NetConf) (types.Patch, error) { +func tagRouteOutdated(nad *cniv1.NetworkAttachmentDefinition, oldConf, newConf *utils.NetConf) (admission.Patch, error) { if oldConf.BrName == newConf.BrName && oldConf.Vlan == newConf.Vlan { return nil, nil } @@ -173,16 +174,16 @@ func tagRouteOutdated(nad *cniv1.NetworkAttachmentDefinition, oldConf, newConf * annotations[utils.KeyNetworkRoute] = string(outdatedRoute) } - return types.Patch{ - types.PatchOp{ - Op: types.PatchOpReplace, + return admission.Patch{ + admission.PatchOp{ + Op: admission.PatchOpReplace, Path: "/metadata/annotations", Value: annotations, }, }, nil } -func (m *Mutator) patchMTU(config string) (types.Patch, error) { +func (m *Mutator) patchMTU(config string) (admission.Patch, error) { netConf := &utils.NetConf{} if err := json.Unmarshal([]byte(config), netConf); err != nil { return nil, err @@ -204,9 +205,9 @@ func (m *Mutator) patchMTU(config string) (types.Patch, error) { return nil, fmt.Errorf("set mtu failed, error: %w", err) } - return types.Patch{ - types.PatchOp{ - Op: types.PatchOpReplace, + return admission.Patch{ + admission.PatchOp{ + Op: admission.PatchOpReplace, Path: "/spec/config", Value: newConfig, }, diff --git a/pkg/webhook/nad/validator.go b/pkg/webhook/nad/validator.go index cfec3e66..3993b7c2 100644 --- a/pkg/webhook/nad/validator.go +++ b/pkg/webhook/nad/validator.go @@ -6,12 +6,13 @@ import ( "reflect" "strings" - ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" - "github.com/harvester/webhook/pkg/types" cniv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" admissionregv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/runtime" + ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" + "github.com/harvester/webhook/pkg/server/admission" + "github.com/harvester/harvester-network-controller/pkg/network/iface" "github.com/harvester/harvester-network-controller/pkg/utils" ) @@ -23,11 +24,11 @@ const ( ) type Validator struct { - types.DefaultValidator + admission.DefaultValidator vmiCache ctlkubevirtv1.VirtualMachineInstanceCache } -var _ types.Validator = &Validator{} +var _ admission.Validator = &Validator{} func NewNadValidator(vmiCache ctlkubevirtv1.VirtualMachineInstanceCache) *Validator { return &Validator{ @@ -35,7 +36,7 @@ func NewNadValidator(vmiCache ctlkubevirtv1.VirtualMachineInstanceCache) *Valida } } -func (v *Validator) Create(_ *types.Request, newObj runtime.Object) error { +func (v *Validator) Create(_ *admission.Request, newObj runtime.Object) error { nad := newObj.(*cniv1.NetworkAttachmentDefinition) if err := v.checkRoute(nad.Annotations[utils.KeyNetworkRoute]); err != nil { @@ -53,7 +54,7 @@ func (v *Validator) Create(_ *types.Request, newObj runtime.Object) error { return nil } -func (v *Validator) Update(_ *types.Request, oldObj, newObj runtime.Object) error { +func (v *Validator) Update(_ *admission.Request, oldObj, newObj runtime.Object) error { newNad := newObj.(*cniv1.NetworkAttachmentDefinition) oldNad := oldObj.(*cniv1.NetworkAttachmentDefinition) @@ -89,7 +90,7 @@ func (v *Validator) Update(_ *types.Request, oldObj, newObj runtime.Object) erro return nil } -func (v *Validator) Delete(_ *types.Request, oldObj runtime.Object) error { +func (v *Validator) Delete(_ *admission.Request, oldObj runtime.Object) error { nad := oldObj.(*cniv1.NetworkAttachmentDefinition) if err := v.checkVmi(nad); err != nil { @@ -143,8 +144,8 @@ func (v *Validator) checkVmi(nad *cniv1.NetworkAttachmentDefinition) error { return nil } -func (v *Validator) Resource() types.Resource { - return types.Resource{ +func (v *Validator) Resource() admission.Resource { + return admission.Resource{ Names: []string{"network-attachment-definitions"}, Scope: admissionregv1.NamespacedScope, APIGroup: cniv1.SchemeGroupVersion.Group, diff --git a/pkg/webhook/vlanconfig/mutator.go b/pkg/webhook/vlanconfig/mutator.go index 41073765..3931ba97 100644 --- a/pkg/webhook/vlanconfig/mutator.go +++ b/pkg/webhook/vlanconfig/mutator.go @@ -5,23 +5,24 @@ import ( "fmt" "reflect" - "github.com/harvester/webhook/pkg/types" ctlcorev1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1" admissionregv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "github.com/harvester/webhook/pkg/server/admission" + networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1" "github.com/harvester/harvester-network-controller/pkg/utils" ) type Mutator struct { - types.DefaultMutator + admission.DefaultMutator nodeCache ctlcorev1.NodeCache } -var _ types.Mutator = &Mutator{} +var _ admission.Mutator = &Mutator{} func NewVlanConfigMutator(nodeCache ctlcorev1.NodeCache) *Mutator { return &Mutator{ @@ -29,7 +30,7 @@ func NewVlanConfigMutator(nodeCache ctlcorev1.NodeCache) *Mutator { } } -func (m *Mutator) Create(_ *types.Request, newObj runtime.Object) (types.Patch, error) { +func (m *Mutator) Create(_ *admission.Request, newObj runtime.Object) (admission.Patch, error) { vlanConfig := newObj.(*networkv1.VlanConfig) annotationPatch, err := m.matchNodes(vlanConfig) @@ -40,7 +41,7 @@ func (m *Mutator) Create(_ *types.Request, newObj runtime.Object) (types.Patch, return append(getCnLabelPatch(vlanConfig), annotationPatch...), nil } -func (m *Mutator) Update(_ *types.Request, oldObj, newObj runtime.Object) (types.Patch, error) { +func (m *Mutator) Update(_ *admission.Request, oldObj, newObj runtime.Object) (admission.Patch, error) { newVc := newObj.(*networkv1.VlanConfig) oldVc := oldObj.(*networkv1.VlanConfig) @@ -49,7 +50,7 @@ func (m *Mutator) Update(_ *types.Request, oldObj, newObj runtime.Object) (types return nil, nil } - var cnLabelPatch, annotationPatch types.Patch + var cnLabelPatch, annotationPatch admission.Patch if newVc.Spec.ClusterNetwork != oldVc.Spec.ClusterNetwork { cnLabelPatch = getCnLabelPatch(newVc) } @@ -62,7 +63,7 @@ func (m *Mutator) Update(_ *types.Request, oldObj, newObj runtime.Object) (types return append(cnLabelPatch, annotationPatch...), nil } -func getCnLabelPatch(v *networkv1.VlanConfig) types.Patch { +func getCnLabelPatch(v *networkv1.VlanConfig) admission.Patch { if v.Labels != nil && v.Labels[utils.KeyClusterNetworkLabel] == v.Spec.ClusterNetwork { return nil } @@ -73,15 +74,15 @@ func getCnLabelPatch(v *networkv1.VlanConfig) types.Patch { } labels[utils.KeyClusterNetworkLabel] = v.Spec.ClusterNetwork - return types.Patch{ - types.PatchOp{ - Op: types.PatchOpReplace, + return admission.Patch{ + admission.PatchOp{ + Op: admission.PatchOpReplace, Path: "/metadata/labels", Value: labels, }} } -func (m *Mutator) matchNodes(vc *networkv1.VlanConfig) (types.Patch, error) { +func (m *Mutator) matchNodes(vc *networkv1.VlanConfig) (admission.Patch, error) { nodes, err := m.nodeCache.List(labels.Set(vc.Spec.NodeSelector).AsSelector()) if err != nil { return nil, err @@ -98,7 +99,7 @@ func (m *Mutator) matchNodes(vc *networkv1.VlanConfig) (types.Patch, error) { return matchedNodesToPatch(vc, matchedNodes) } -func matchedNodesToPatch(vc *networkv1.VlanConfig, matchedNodes []string) (types.Patch, error) { +func matchedNodesToPatch(vc *networkv1.VlanConfig, matchedNodes []string) (admission.Patch, error) { annotations := vc.Annotations if annotations == nil { annotations = map[string]string{} @@ -110,17 +111,17 @@ func matchedNodesToPatch(vc *networkv1.VlanConfig, matchedNodes []string) (types } annotations[utils.KeyMatchedNodes] = string(nodesBytes) - return types.Patch{ - types.PatchOp{ - Op: types.PatchOpReplace, + return admission.Patch{ + admission.PatchOp{ + Op: admission.PatchOpReplace, Path: "/metadata/annotations", Value: annotations, }, }, nil } -func (m *Mutator) Resource() types.Resource { - return types.Resource{ +func (m *Mutator) Resource() admission.Resource { + return admission.Resource{ Names: []string{"vlanconfigs"}, Scope: admissionregv1.ClusterScope, APIGroup: networkv1.SchemeGroupVersion.Group, diff --git a/pkg/webhook/vlanconfig/validator.go b/pkg/webhook/vlanconfig/validator.go index c047e170..1dffe195 100644 --- a/pkg/webhook/vlanconfig/validator.go +++ b/pkg/webhook/vlanconfig/validator.go @@ -7,15 +7,16 @@ import ( "strings" mapset "github.com/deckarep/golang-set/v2" - ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1" - ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" - "github.com/harvester/webhook/pkg/types" admissionregv1 "k8s.io/api/admissionregistration/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" kubevirtv1 "kubevirt.io/api/core/v1" + ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1" + ctlkubevirtv1 "github.com/harvester/harvester/pkg/generated/controllers/kubevirt.io/v1" + "github.com/harvester/webhook/pkg/server/admission" + networkv1 "github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io/v1beta1" ctlnetworkv1 "github.com/harvester/harvester-network-controller/pkg/generated/controllers/network.harvesterhci.io/v1beta1" "github.com/harvester/harvester-network-controller/pkg/network/iface" @@ -29,7 +30,7 @@ const ( ) type Validator struct { - types.DefaultValidator + admission.DefaultValidator nadCache ctlcniv1.NetworkAttachmentDefinitionCache vcCache ctlnetworkv1.VlanConfigCache @@ -50,9 +51,9 @@ func NewVlanConfigValidator( } } -var _ types.Validator = &Validator{} +var _ admission.Validator = &Validator{} -func (v *Validator) Create(_ *types.Request, newObj runtime.Object) error { +func (v *Validator) Create(_ *admission.Request, newObj runtime.Object) error { vc := newObj.(*networkv1.VlanConfig) if vc.Spec.ClusterNetwork == utils.ManagementClusterNetworkName { @@ -83,7 +84,7 @@ func (v *Validator) Create(_ *types.Request, newObj runtime.Object) error { return nil } -func (v *Validator) Update(_ *types.Request, oldObj, newObj runtime.Object) error { +func (v *Validator) Update(_ *admission.Request, oldObj, newObj runtime.Object) error { oldVc := oldObj.(*networkv1.VlanConfig) newVc := newObj.(*networkv1.VlanConfig) @@ -131,7 +132,7 @@ func getAffectedNodes(oldCn, newCn string, oldNodes, newNodes mapset.Set[string] return oldNodes.Difference(newNodes) } -func (v *Validator) Delete(_ *types.Request, oldObj runtime.Object) error { +func (v *Validator) Delete(_ *admission.Request, oldObj runtime.Object) error { vc := oldObj.(*networkv1.VlanConfig) nodes, err := getMatchNodes(vc) @@ -146,8 +147,8 @@ func (v *Validator) Delete(_ *types.Request, oldObj runtime.Object) error { return nil } -func (v *Validator) Resource() types.Resource { - return types.Resource{ +func (v *Validator) Resource() admission.Resource { + return admission.Resource{ Names: []string{"vlanconfigs"}, Scope: admissionregv1.ClusterScope, APIGroup: networkv1.SchemeGroupVersion.Group, diff --git a/vendor/github.com/harvester/webhook/pkg/clients/clients.go b/vendor/github.com/harvester/webhook/pkg/clients/clients.go index 669c9ec5..ee6d283d 100644 --- a/vendor/github.com/harvester/webhook/pkg/clients/clients.go +++ b/vendor/github.com/harvester/webhook/pkg/clients/clients.go @@ -3,7 +3,8 @@ package clients import ( "github.com/rancher/wrangler/pkg/clients" "github.com/rancher/wrangler/pkg/schemes" - v1 "k8s.io/api/admissionregistration/v1" + admissionv1 "k8s.io/api/admissionregistration/v1" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/client-go/rest" ) @@ -17,7 +18,10 @@ func New(rest *rest.Config) (*Clients, error) { return nil, err } - if err := schemes.Register(v1.AddToScheme); err != nil { + if err := schemes.Register(admissionv1.AddToScheme); err != nil { + return nil, err + } + if err := schemes.Register(apiextv1.AddToScheme); err != nil { return nil, err } diff --git a/vendor/github.com/harvester/webhook/pkg/config/config.go b/vendor/github.com/harvester/webhook/pkg/config/config.go index df9ad47b..c1dfd692 100644 --- a/vendor/github.com/harvester/webhook/pkg/config/config.go +++ b/vendor/github.com/harvester/webhook/pkg/config/config.go @@ -1,6 +1,6 @@ package config -// Options for the admission webhook server +// Options for the webhook server type Options struct { Namespace string Threadiness int diff --git a/vendor/github.com/harvester/webhook/pkg/types/admission.go b/vendor/github.com/harvester/webhook/pkg/server/admission/admission.go similarity index 85% rename from vendor/github.com/harvester/webhook/pkg/types/admission.go rename to vendor/github.com/harvester/webhook/pkg/server/admission/admission.go index 3e7039a8..64550cbd 100644 --- a/vendor/github.com/harvester/webhook/pkg/types/admission.go +++ b/vendor/github.com/harvester/webhook/pkg/server/admission/admission.go @@ -1,8 +1,9 @@ -package types +package admission import ( "encoding/json" "fmt" + "reflect" "github.com/rancher/wrangler/pkg/webhook" "github.com/sirupsen/logrus" @@ -70,19 +71,19 @@ type Admitter interface { Resource() Resource } -// AdmissionHandler is a handler for the admission webhook server -type AdmissionHandler struct { +// Handler for the admitter webhook server +type Handler struct { admitter Admitter admissionType AdmissionType options *config.Options } -// NewAdmissionHandler returns a new admission handler -func NewAdmissionHandler(admitter Admitter, admissionType AdmissionType, options *config.Options) *AdmissionHandler { +// NewHandler returns a new admitter handler +func NewHandler(admitter Admitter, admissionType AdmissionType, options *config.Options) *Handler { if err := admitter.Resource().Validate(); err != nil { panic(err.Error()) } - return &AdmissionHandler{ + return &Handler{ admitter: admitter, admissionType: admissionType, options: options, @@ -90,11 +91,11 @@ func NewAdmissionHandler(admitter Admitter, admissionType AdmissionType, options } // Admit function handles the AdmissionReview request -func (v *AdmissionHandler) Admit(response *webhook.Response, request *webhook.Request) error { +func (v *Handler) Admit(response *webhook.Response, request *webhook.Request) error { return v.admit(response, NewRequest(request, v.options)) } -func (v *AdmissionHandler) admit(response *webhook.Response, req *Request) error { +func (v *Handler) admit(response *webhook.Response, req *Request) error { logrus.Debugf("%s admitting %s", req, v.admissionType) oldObj, newObj, err := req.DecodeObjects() @@ -150,7 +151,7 @@ func (v *AdmissionHandler) admit(response *webhook.Response, req *Request) error return nil } -func (v *AdmissionHandler) decodeObjects(request *Request) (oldObj runtime.Object, newObj runtime.Object, err error) { +func (v *Handler) decodeObjects(request *Request) (oldObj runtime.Object, newObj runtime.Object, err error) { operation := request.Operation if operation == admissionv1.Delete || operation == admissionv1.Update { oldObj, err = request.DecodeOldObject() @@ -165,3 +166,9 @@ func (v *AdmissionHandler) decodeObjects(request *Request) (oldObj runtime.Objec newObj, err = request.DecodeObject() return } + +func (v *Handler) AddToWebhookRouter(router *webhook.Router) { + rsc := v.admitter.Resource() + kind := reflect.Indirect(reflect.ValueOf(rsc.ObjectType)).Type().Name() + router.Kind(kind).Group(rsc.APIGroup).Type(rsc.ObjectType).Handle(v) +} diff --git a/vendor/github.com/harvester/webhook/pkg/types/mutator.go b/vendor/github.com/harvester/webhook/pkg/server/admission/mutator.go similarity index 97% rename from vendor/github.com/harvester/webhook/pkg/types/mutator.go rename to vendor/github.com/harvester/webhook/pkg/server/admission/mutator.go index dc542793..b6f07f77 100644 --- a/vendor/github.com/harvester/webhook/pkg/types/mutator.go +++ b/vendor/github.com/harvester/webhook/pkg/server/admission/mutator.go @@ -1,4 +1,4 @@ -package types +package admission import ( "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/github.com/harvester/webhook/pkg/types/request.go b/vendor/github.com/harvester/webhook/pkg/server/admission/request.go similarity index 98% rename from vendor/github.com/harvester/webhook/pkg/types/request.go rename to vendor/github.com/harvester/webhook/pkg/server/admission/request.go index fb687e2a..14430e34 100644 --- a/vendor/github.com/harvester/webhook/pkg/types/request.go +++ b/vendor/github.com/harvester/webhook/pkg/server/admission/request.go @@ -1,4 +1,4 @@ -package types +package admission import ( "fmt" diff --git a/vendor/github.com/harvester/webhook/pkg/types/resource.go b/vendor/github.com/harvester/webhook/pkg/server/admission/resource.go similarity index 98% rename from vendor/github.com/harvester/webhook/pkg/types/resource.go rename to vendor/github.com/harvester/webhook/pkg/server/admission/resource.go index fe52790b..cebba225 100644 --- a/vendor/github.com/harvester/webhook/pkg/types/resource.go +++ b/vendor/github.com/harvester/webhook/pkg/server/admission/resource.go @@ -1,4 +1,4 @@ -package types +package admission import ( "fmt" diff --git a/vendor/github.com/harvester/webhook/pkg/types/validator.go b/vendor/github.com/harvester/webhook/pkg/server/admission/validator.go similarity index 99% rename from vendor/github.com/harvester/webhook/pkg/types/validator.go rename to vendor/github.com/harvester/webhook/pkg/server/admission/validator.go index d652e1e1..656c1114 100644 --- a/vendor/github.com/harvester/webhook/pkg/types/validator.go +++ b/vendor/github.com/harvester/webhook/pkg/server/admission/validator.go @@ -1,4 +1,4 @@ -package types +package admission import ( "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/github.com/harvester/webhook/pkg/server/conversion/conversion.go b/vendor/github.com/harvester/webhook/pkg/server/conversion/conversion.go new file mode 100644 index 00000000..0b19f4fc --- /dev/null +++ b/vendor/github.com/harvester/webhook/pkg/server/conversion/conversion.go @@ -0,0 +1,122 @@ +package conversion + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/sirupsen/logrus" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// Converter is a interface to convert object to the desired version +type Converter interface { + GroupResource() schema.GroupResource + Convert(Object *unstructured.Unstructured, desiredAPIVersion string) (*unstructured.Unstructured, error) +} + +// Handler is a http handler for multiple converters +type Handler struct { + restMapper meta.RESTMapper + converters map[schema.GroupResource]Converter +} + +func NewHandler(converters []Converter, restMapper meta.RESTMapper) *Handler { + h := &Handler{ + restMapper: restMapper, + converters: map[schema.GroupResource]Converter{}, + } + for _, c := range converters { + h.converters[c.GroupResource()] = c + } + + return h +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + review := &apiextensionsv1.ConversionReview{} + err := json.NewDecoder(r.Body).Decode(review) + if err != nil { + sendError(w, review, err) + return + } + + if review.Request == nil { + sendError(w, review, fmt.Errorf("request is not set")) + return + } + + review.Response = h.doConversion(review.Request) + review.Request = nil + + writeResponse(w, review) +} + +func (h *Handler) doConversion(request *apiextensionsv1.ConversionRequest) *apiextensionsv1.ConversionResponse { + response := &apiextensionsv1.ConversionResponse{ + UID: request.UID, + } + + for _, obj := range request.Objects { + convertedObj, err := h.convertObject(&obj, request.DesiredAPIVersion) + if err != nil { + response.Result = errors.NewInternalError(err).ErrStatus + return response + } + response.ConvertedObjects = append(response.ConvertedObjects, *convertedObj) + } + + response.Result = metav1.Status{ + Status: metav1.StatusSuccess, + } + + return response +} + +func (h *Handler) convertObject(obj *runtime.RawExtension, desiredAPIVersion string) (*runtime.RawExtension, error) { + cr := &unstructured.Unstructured{} + if err := cr.UnmarshalJSON(obj.Raw); err != nil { + return nil, err + } + // use RESTMapping to get the group resource of the object + mapper, err := h.restMapper.RESTMapping(cr.GroupVersionKind().GroupKind()) + if err != nil { + return nil, err + } + groupResource := mapper.Resource.GroupResource() + converter, ok := h.converters[groupResource] + if !ok { + return nil, fmt.Errorf("converter for %s is not existing", groupResource.String()) + } + + convertedObj, err := converter.Convert(cr, desiredAPIVersion) + if err != nil { + return nil, err + } + convertedObj.SetAPIVersion(desiredAPIVersion) + + return &runtime.RawExtension{Object: convertedObj}, nil +} + +func writeResponse(w http.ResponseWriter, review *apiextensionsv1.ConversionReview) { + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(review); err != nil { + logrus.Errorf("encode review failed, review: %+v, error: %v", review, err) + } +} + +func sendError(w http.ResponseWriter, review *apiextensionsv1.ConversionReview, err error) { + logrus.Error(err) + if review == nil || review.Request == nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + review.Response.Result = errors.NewInternalError(err).ErrStatus + writeResponse(w, review) +} diff --git a/vendor/github.com/harvester/webhook/pkg/server/mutation.go b/vendor/github.com/harvester/webhook/pkg/server/mutation.go deleted file mode 100644 index af6fe382..00000000 --- a/vendor/github.com/harvester/webhook/pkg/server/mutation.go +++ /dev/null @@ -1,30 +0,0 @@ -package server - -import ( - "net/http" - "reflect" - - "github.com/rancher/wrangler/pkg/webhook" - "github.com/sirupsen/logrus" - - "github.com/harvester/webhook/pkg/config" - "github.com/harvester/webhook/pkg/types" -) - -func (s *AdmissionWebhookServer) mutation(options *config.Options) (http.Handler, []types.Resource, error) { - router := webhook.NewRouter() - resources := make([]types.Resource, 0) - for _, m := range s.admitters[types.AdmissionTypeMutation] { - addHandler(router, types.AdmissionTypeMutation, m, options) - resources = append(resources, m.Resource()) - } - - return router, resources, nil -} - -func addHandler(router *webhook.Router, admissionType types.AdmissionType, admitter types.Admitter, options *config.Options) { - rsc := admitter.Resource() - kind := reflect.Indirect(reflect.ValueOf(rsc.ObjectType)).Type().Name() - router.Kind(kind).Group(rsc.APIGroup).Type(rsc.ObjectType).Handle(types.NewAdmissionHandler(admitter, admissionType, options)) - logrus.Infof("add %s handler for %+v.%s (%s)", admissionType, rsc.Names, rsc.APIGroup, kind) -} diff --git a/vendor/github.com/harvester/webhook/pkg/server/server.go b/vendor/github.com/harvester/webhook/pkg/server/server.go index 86d70d0e..8ab78ceb 100644 --- a/vendor/github.com/harvester/webhook/pkg/server/server.go +++ b/vendor/github.com/harvester/webhook/pkg/server/server.go @@ -4,90 +4,106 @@ import ( "context" "fmt" "net/http" - "reflect" "time" "github.com/gorilla/mux" "github.com/rancher/dynamiclistener" - "github.com/rancher/dynamiclistener/server" + dls "github.com/rancher/dynamiclistener/server" + "github.com/rancher/wrangler/pkg/webhook" "github.com/sirupsen/logrus" v1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" "github.com/harvester/webhook/pkg/clients" "github.com/harvester/webhook/pkg/config" - "github.com/harvester/webhook/pkg/types" + "github.com/harvester/webhook/pkg/server/admission" + "github.com/harvester/webhook/pkg/server/conversion" ) var ( port = int32(443) validationPath = "/v1/webhook/validation" mutationPath = "/v1/webhook/mutation" + conversionPath = "/v1/webhook/conversion" failPolicyFail = v1.Fail failPolicyIgnore = v1.Ignore sideEffectClassNone = v1.SideEffectClassNone ) -// AdmissionWebhookServer for listening the AdmissionReview request sent by the apiservers -type AdmissionWebhookServer struct { +type server struct { context context.Context restConfig *rest.Config name string options *config.Options + caBundle []byte +} + +// WebhookServer for listening the AdmissionReview request sent by the apiservers +type WebhookServer struct { + server + + isStarted bool - admitters map[types.AdmissionType][]types.Admitter + validators []admission.Validator + mutators []admission.Mutator + converters []conversion.Converter } -// New admission webhook server -func New(ctx context.Context, restConfig *rest.Config, name string, options *config.Options) *AdmissionWebhookServer { - return &AdmissionWebhookServer{ - context: ctx, - restConfig: restConfig, - name: name, - options: options, - - admitters: map[types.AdmissionType][]types.Admitter{ - types.AdmissionTypeValidation: make([]types.Admitter, 0), - types.AdmissionTypeMutation: make([]types.Admitter, 0), +// NewWebhookServer creates a new server for admitter webhook +func NewWebhookServer(ctx context.Context, restConfig *rest.Config, name string, options *config.Options) *WebhookServer { + return &WebhookServer{ + server: server{ + context: ctx, + restConfig: restConfig, + name: name, + options: options, }, } } -// Start the admission webhook server. -// The server will apply the validatingwebhookconfiguration and mutatingwebhookconfiguration with cert authentication automatically. -func (s *AdmissionWebhookServer) Start() error { +// Start the admitter webhook server. +// The server will apply the validatingwebhookconfiguration, mutatingwebhookconfiguration +// and CRD conversion webhook configuration with cert authentication automatically. +func (s *WebhookServer) Start() error { client, err := clients.New(s.restConfig) if err != nil { return err } - validationHandler, validationResources, err := s.validation(s.options) - if err != nil { - return err + router := mux.NewRouter() + validatingHandler := s.validatingHandler() + if validatingHandler != nil { + router.Handle(validationPath, validatingHandler) } - mutationHandler, mutationResources, err := s.mutation(s.options) - if err != nil { - return err + + mutatingHandler := s.mutatingHandler() + if mutatingHandler != nil { + router.Handle(mutationPath, mutatingHandler) } - router := mux.NewRouter() - router.Handle(validationPath, validationHandler) - router.Handle(mutationPath, mutationHandler) - if err := s.listenAndServe(client, router, validationResources, mutationResources); err != nil { - logrus.Error(err) + if len(s.converters) != 0 { + router.Handle(conversionPath, conversion.NewHandler(s.converters, client.RESTMapper)) + } + + if err := s.listenAndServe(client, router); err != nil { + logrus.Errorf("listen and serve failed, err: %s", err.Error()) return err } if err := client.Start(s.context); err != nil { - logrus.Error(err) + logrus.Errorf("start clients failed, err: %s", err.Error()) return err } + + s.isStarted = true + return nil } -func (s *AdmissionWebhookServer) listenAndServe(clients *clients.Clients, handler http.Handler, validationResources []types.Resource, mutationResources []types.Resource) error { +func (s *WebhookServer) listenAndServe(clients *clients.Clients, handler http.Handler) error { apply := clients.Apply.WithDynamicLookup() caName, certName := s.name+"-ca", s.name+"-tls" @@ -99,65 +115,27 @@ func (s *AdmissionWebhookServer) listenAndServe(clients *clients.Clients, handle // Sleep here to make sure server is listening and all caches are primed time.Sleep(15 * time.Second) - logrus.Debugf("Building validation rules...") - validationRules := s.buildRules(validationResources) - logrus.Debugf("Building mutation rules...") - mutationRules := s.buildRules(mutationResources) - - validatingWebhookConfiguration := &v1.ValidatingWebhookConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: s.name, - }, - Webhooks: []v1.ValidatingWebhook{ - { - Name: "validator." + s.options.Namespace + "." + s.name, - ClientConfig: v1.WebhookClientConfig{ - Service: &v1.ServiceReference{ - Namespace: s.options.Namespace, - Name: s.name, - Path: &validationPath, - Port: &port, - }, - CABundle: secret.Data[corev1.TLSCertKey], - }, - Rules: validationRules, - FailurePolicy: &failPolicyFail, - SideEffects: &sideEffectClassNone, - AdmissionReviewVersions: []string{"v1", "v1beta1"}, - }, - }, + s.caBundle = secret.Data[corev1.TLSCertKey] + // configure admitter webhook + validatingWebhookConfiguration := s.validatingWebhookConfiguration() + mutatingWebhookConfiguration := s.mutatingWebhookConfiguration() + if validatingWebhookConfiguration != nil || mutatingWebhookConfiguration != nil { + if err := apply.WithOwner(secret).ApplyObjects(validatingWebhookConfiguration, mutatingWebhookConfiguration); err != nil { + return nil, fmt.Errorf("configure validatingwebhookconfiguration %s and mutatingwebhookconfiguration %s failed, error: %w", + validatingWebhookConfiguration.Name, mutatingWebhookConfiguration.Name, err) + } } - - mutatingWebhookConfiguration := &v1.MutatingWebhookConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: s.name, - }, - Webhooks: []v1.MutatingWebhook{ - { - Name: "mutator." + s.options.Namespace + "." + s.name, - ClientConfig: v1.WebhookClientConfig{ - Service: &v1.ServiceReference{ - Namespace: s.options.Namespace, - Name: s.name, - Path: &mutationPath, - Port: &port, - }, - CABundle: secret.Data[corev1.TLSCertKey], - }, - Rules: mutationRules, - FailurePolicy: &failPolicyIgnore, - SideEffects: &sideEffectClassNone, - AdmissionReviewVersions: []string{"v1", "v1beta1"}, - }, - }, + // configure conversion webhook + if err := s.configureCRDConversionWebhook(clients); err != nil { + return nil, fmt.Errorf("configure conversion webhook for CRD failed, error: %w", err) } - return secret, apply.WithOwner(secret).ApplyObjects(validatingWebhookConfiguration, mutatingWebhookConfiguration) + return secret, nil }) tlsName := fmt.Sprintf("%s.%s.svc", s.name, s.options.Namespace) - return server.ListenAndServe(s.context, s.options.HTTPSListenPort, 0, handler, &server.ListenOpts{ + return dls.ListenAndServe(s.context, s.options.HTTPSListenPort, 0, handler, &dls.ListenOpts{ Secrets: clients.Core.Secret(), CertNamespace: s.options.Namespace, CertName: certName, @@ -171,7 +149,167 @@ func (s *AdmissionWebhookServer) listenAndServe(clients *clients.Clients, handle }) } -func (s *AdmissionWebhookServer) buildRules(resources []types.Resource) []v1.RuleWithOperations { +func (s *WebhookServer) validatingWebhookConfiguration() *v1.ValidatingWebhookConfiguration { + if len(s.validators) == 0 { + return nil + } + + resources := make([]admission.Resource, 0, len(s.validators)) + for _, validator := range s.validators { + resources = append(resources, validator.Resource()) + } + + return &v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: s.name, + }, + Webhooks: []v1.ValidatingWebhook{ + { + Name: "validator." + s.options.Namespace + "." + s.name, + ClientConfig: v1.WebhookClientConfig{ + Service: &v1.ServiceReference{ + Namespace: s.options.Namespace, + Name: s.name, + Path: &validationPath, + Port: &port, + }, + CABundle: s.caBundle, + }, + Rules: buildRules(resources), + FailurePolicy: &failPolicyFail, + SideEffects: &sideEffectClassNone, + AdmissionReviewVersions: []string{"v1", "v1beta1"}, + }, + }, + } +} + +func (s *WebhookServer) mutatingWebhookConfiguration() *v1.MutatingWebhookConfiguration { + if len(s.mutators) == 0 { + return nil + } + + resources := make([]admission.Resource, 0, len(s.mutators)) + for _, mutator := range s.mutators { + resources = append(resources, mutator.Resource()) + } + return &v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: s.name, + }, + Webhooks: []v1.MutatingWebhook{ + { + Name: "mutator." + s.options.Namespace + "." + s.name, + ClientConfig: v1.WebhookClientConfig{ + Service: &v1.ServiceReference{ + Namespace: s.options.Namespace, + Name: s.name, + Path: &mutationPath, + Port: &port, + }, + CABundle: s.caBundle, + }, + Rules: buildRules(resources), + FailurePolicy: &failPolicyIgnore, + SideEffects: &sideEffectClassNone, + AdmissionReviewVersions: []string{"v1", "v1beta1"}, + }, + }, + } +} + +func (s *WebhookServer) configureCRDConversionWebhook(clients *clients.Clients) error { + crdClient := clients.CRD.CustomResourceDefinition() + for _, converter := range s.converters { + crd, err := crdClient.Get(converter.GroupResource().String(), metav1.GetOptions{}) + if err != nil { + return err + } + // configure conversion webhook + crdCopy := crd.DeepCopy() + crdCopy.Spec.Conversion.Strategy = apiextensionsv1.WebhookConverter + crdCopy.Spec.Conversion.Webhook = &apiextensionsv1.WebhookConversion{ + ConversionReviewVersions: []string{"v1"}, + ClientConfig: &apiextensionsv1.WebhookClientConfig{ + Service: &apiextensionsv1.ServiceReference{ + Namespace: s.options.Namespace, + Name: s.name, + Path: &conversionPath, + Port: &port, + }, + CABundle: s.caBundle, + }, + } + if _, err := crdClient.Update(crdCopy); err != nil { + return err + } + } + + return nil +} + +// RegisterValidators registers validator to the webhook server. +// Call it before starting the webhook server. +func (s *WebhookServer) RegisterValidators(validators ...admission.Validator) error { + if s.isStarted { + return fmt.Errorf("cannot register validators after the webhook server is started") + } + + s.validators = append(s.validators, validators...) + return nil +} + +// RegisterMutators registers mutator to the webhook server. +// Call it before start the webhook server. +func (s *WebhookServer) RegisterMutators(mutators ...admission.Mutator) error { + if s.isStarted { + return fmt.Errorf("cannot register mutators after the webhook server is started") + } + + s.mutators = append(s.mutators, mutators...) + return nil +} + +// RegisterConverters registers converters to the webhook server. +// Call it before start the webhook server. +func (s *WebhookServer) RegisterConverters(converters ...conversion.Converter) error { + if s.isStarted { + return fmt.Errorf("cannot register converters after the webhook server is started") + } + + s.converters = append(s.converters, converters...) + return nil +} + +func (s *WebhookServer) validatingHandler() http.Handler { + if len(s.validators) == 0 { + return nil + } + + router := webhook.NewRouter() + for _, v := range s.validators { + h := admission.NewHandler(admission.Validator2Admitter(v), admission.AdmissionTypeValidation, s.options) + h.AddToWebhookRouter(router) + } + + return router +} + +func (s *WebhookServer) mutatingHandler() http.Handler { + if len(s.mutators) == 0 { + return nil + } + + router := webhook.NewRouter() + for _, m := range s.mutators { + h := admission.NewHandler(m, admission.AdmissionTypeMutation, s.options) + h.AddToWebhookRouter(router) + } + + return router +} + +func buildRules(resources []admission.Resource) []v1.RuleWithOperations { rules := make([]v1.RuleWithOperations, 0) for _, rsc := range resources { logrus.Debugf("Add rule for %+v", rsc) @@ -189,19 +327,3 @@ func (s *AdmissionWebhookServer) buildRules(resources []types.Resource) []v1.Rul return rules } - -// Register validator or mutator to the admission webhook server. -// Call it before start the admission webhook server. -func (s *AdmissionWebhookServer) Register(admitters []types.Admitter) { - mutatorType := reflect.TypeOf((*types.ValidatorAdapter)(nil)) - - for _, admitter := range admitters { - typ := reflect.TypeOf(admitter) - logrus.Debugf("admitter type: %s", typ.String()) - if typ == mutatorType { - s.admitters[types.AdmissionTypeValidation] = append(s.admitters[types.AdmissionTypeValidation], admitter) - continue - } - s.admitters[types.AdmissionTypeMutation] = append(s.admitters[types.AdmissionTypeMutation], admitter) - } -} diff --git a/vendor/github.com/harvester/webhook/pkg/server/validation.go b/vendor/github.com/harvester/webhook/pkg/server/validation.go deleted file mode 100644 index 06665c2d..00000000 --- a/vendor/github.com/harvester/webhook/pkg/server/validation.go +++ /dev/null @@ -1,21 +0,0 @@ -package server - -import ( - "net/http" - - "github.com/rancher/wrangler/pkg/webhook" - - "github.com/harvester/webhook/pkg/config" - "github.com/harvester/webhook/pkg/types" -) - -func (s *AdmissionWebhookServer) validation(options *config.Options) (http.Handler, []types.Resource, error) { - router := webhook.NewRouter() - resources := make([]types.Resource, 0) - for _, v := range s.admitters[types.AdmissionTypeValidation] { - addHandler(router, types.AdmissionTypeValidation, v, options) - resources = append(resources, v.Resource()) - } - - return router, resources, nil -} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go index ecdaa918..054d058c 100644 --- a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go @@ -39,7 +39,6 @@ type desiredSet struct { noDeleteGVK map[schema.GroupVersionKind]struct{} setID string objs *objectset.ObjectSet - codeVersion string owner runtime.Object injectors []injectors.ConfigInjector ratelimitingQps float32 diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go index b478f12c..cf4ee232 100644 --- a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go @@ -144,7 +144,7 @@ func (o *desiredSet) debugID() string { func (o *desiredSet) collect(objList []runtime.Object) objectset.ObjectByGVK { result := objectset.ObjectByGVK{} for _, obj := range objList { - result.Add(obj) + _, _ = result.Add(obj) } return result } diff --git a/vendor/github.com/rancher/wrangler/pkg/condition/condition.go b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go index 65c5b0bc..ace8dea3 100644 --- a/vendor/github.com/rancher/wrangler/pkg/condition/condition.go +++ b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go @@ -223,7 +223,6 @@ func getValue(obj interface{}, name ...string) reflect.Value { t := v.Type() if t.Kind() == reflect.Ptr { v = v.Elem() - t = v.Type() } field := v.FieldByName(name[0]) diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go index f74f509c..beea92a0 100644 --- a/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go @@ -3,7 +3,6 @@ package controllergen import ( "fmt" "io" - "io/ioutil" "os" "path/filepath" "sort" @@ -46,7 +45,7 @@ func Run(opts cgargs.Options) { genericArgs.InputDirs = parseTypes(customArgs) if genericArgs.OutputBase == "./" { //go modules - tempDir, err := ioutil.TempDir("", "") + tempDir, err := os.MkdirTemp("", "") if err != nil { return } @@ -123,7 +122,7 @@ func sourcePackagePath(customArgs *cgargs.CustomArgs, pkgName string) string { return pkg } -//until k8s code-gen supports gopath +// until k8s code-gen supports gopath func copyGoPathToModules(customArgs *cgargs.CustomArgs) error { pathsToCopy := map[string]bool{} @@ -137,7 +136,7 @@ func copyGoPathToModules(customArgs *cgargs.CustomArgs) error { pkg := sourcePackagePath(customArgs, customArgs.Package) pathsToCopy[pkg] = true - for pkg, _ := range pathsToCopy { + for pkg := range pathsToCopy { if _, err := os.Stat(pkg); os.IsNotExist(err) { continue } diff --git a/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go b/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go index c87f8b21..ff67f049 100644 --- a/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go +++ b/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go @@ -10,6 +10,8 @@ import ( "time" "unicode" + "golang.org/x/text/cases" + "golang.org/x/text/language" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -235,7 +237,8 @@ func EncodeToMap(obj interface{}) (map[string]interface{}, error) { func ToJSONKey(str string) string { parts := strings.Split(str, "_") for i := 1; i < len(parts); i++ { - parts[i] = strings.Title(parts[i]) + caser := cases.Title(language.English) + parts[i] = caser.String(parts[i]) } return strings.Join(parts, "") diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/factory.go b/vendor/github.com/rancher/wrangler/pkg/generic/factory.go index 946af865..ce4370d9 100644 --- a/vendor/github.com/rancher/wrangler/pkg/generic/factory.go +++ b/vendor/github.com/rancher/wrangler/pkg/generic/factory.go @@ -103,7 +103,7 @@ func (c *Factory) setControllerFactoryWithLock() error { func (c *Factory) Sync(ctx context.Context) error { if c.cacheFactory != nil { - c.cacheFactory.Start(ctx) + _ = c.cacheFactory.Start(ctx) c.cacheFactory.WaitForCacheSync(ctx) } return nil diff --git a/vendor/github.com/rancher/wrangler/pkg/kubeconfig/loader.go b/vendor/github.com/rancher/wrangler/pkg/kubeconfig/loader.go index 16902a42..8e4112b8 100644 --- a/vendor/github.com/rancher/wrangler/pkg/kubeconfig/loader.go +++ b/vendor/github.com/rancher/wrangler/pkg/kubeconfig/loader.go @@ -2,7 +2,6 @@ package kubeconfig import ( "io" - "io/ioutil" "os" "path/filepath" @@ -51,7 +50,7 @@ func GetLoadingRules(kubeConfig string) *clientcmd.ClientConfigLoadingRules { func canRead(files []string) (result []string) { for _, f := range files { - _, err := ioutil.ReadFile(f) + _, err := os.ReadFile(f) if err == nil { result = append(result, f) } diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go index 06f1e88b..b426e455 100644 --- a/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go @@ -42,7 +42,7 @@ func (m Move) ModifySchema(s *types.Schema, schemas *types.Schemas) error { return fmt.Errorf("failed to find field %s on schema %s", m.From, s.ID) } - toSchema, toFieldName, _, ok, err := getField(s, schemas, m.To) + toSchema, toFieldName, _, _, err := getField(s, schemas, m.To) if err != nil { return err } diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go index b32c8b01..970dd6dc 100644 --- a/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go @@ -345,9 +345,7 @@ func (s *Schemas) processFieldsMappers(t reflect.Type, fieldName string, schema parts := strings.SplitN(fieldMapper, "=", 2) name = parts[0] if len(parts) == 2 { - for _, opt := range strings.Split(parts[1], "|") { - opts = append(opts, opt) - } + opts = append(opts, strings.Split(parts[1], "|")...) } factory, ok := s.fieldMappers[name] diff --git a/vendor/github.com/rancher/wrangler/pkg/summary/summarized.go b/vendor/github.com/rancher/wrangler/pkg/summary/summarized.go index 346efb3e..7526dde7 100644 --- a/vendor/github.com/rancher/wrangler/pkg/summary/summarized.go +++ b/vendor/github.com/rancher/wrangler/pkg/summary/summarized.go @@ -54,7 +54,6 @@ func (in *SummarizedObjectList) DeepCopyInto(out *SummarizedObjectList) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } func (in *SummarizedObjectList) DeepCopy() *SummarizedObjectList { @@ -78,7 +77,6 @@ func (in *SummarizedObject) DeepCopyInto(out *SummarizedObject) { out.TypeMeta = in.TypeMeta out.ObjectMeta = *in.ObjectMeta.DeepCopy() out.Summary = *in.Summary.DeepCopy() - return } func (in *SummarizedObject) DeepCopy() *SummarizedObject { diff --git a/vendor/github.com/rancher/wrangler/pkg/webhook/router.go b/vendor/github.com/rancher/wrangler/pkg/webhook/router.go index 1d7c70dc..7c53d403 100644 --- a/vendor/github.com/rancher/wrangler/pkg/webhook/router.go +++ b/vendor/github.com/rancher/wrangler/pkg/webhook/router.go @@ -42,7 +42,10 @@ func (r *Router) sendError(rw http.ResponseWriter, review *v1.AdmissionReview, e func writeResponse(rw http.ResponseWriter, review *v1.AdmissionReview) { rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(review) + err := json.NewEncoder(rw).Encode(review) + if err != nil { + logrus.Errorf("Failed to write response: %s", err) + } } // ServeHTTP inspects the http.Request and calls the Admit function on all matching handlers. diff --git a/vendor/modules.txt b/vendor/modules.txt index 0caa6964..47310ac9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -186,13 +186,14 @@ github.com/harvester/harvester/pkg/indexeres github.com/harvester/harvester/pkg/ref github.com/harvester/harvester/pkg/util github.com/harvester/harvester/pkg/util/crd -# github.com/harvester/webhook v0.1.2 -## explicit; go 1.18 +# github.com/harvester/webhook v0.1.3 +## explicit; go 1.19 github.com/harvester/webhook/pkg/clients github.com/harvester/webhook/pkg/config github.com/harvester/webhook/pkg/error github.com/harvester/webhook/pkg/server -github.com/harvester/webhook/pkg/types +github.com/harvester/webhook/pkg/server/admission +github.com/harvester/webhook/pkg/server/conversion # github.com/iancoleman/orderedmap v0.2.0 ## explicit github.com/iancoleman/orderedmap @@ -439,7 +440,7 @@ github.com/rancher/steve/pkg/summarycache github.com/rancher/system-upgrade-controller/pkg/apis/condition github.com/rancher/system-upgrade-controller/pkg/apis/upgrade.cattle.io github.com/rancher/system-upgrade-controller/pkg/apis/upgrade.cattle.io/v1 -# github.com/rancher/wrangler v1.1.0 +# github.com/rancher/wrangler v1.1.1 ## explicit; go 1.19 github.com/rancher/wrangler/pkg/apply github.com/rancher/wrangler/pkg/apply/injectors