1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-10 09:56:55 +00:00
kyverno/pkg/webhookconfig/registration.go
Thomas Hartland 6e9609409b
Use non-blocking channel send for UpdateWebhookChan (#4204)
If the channel send is blocked then there is already an
update queued, and there is no point waiting to queue
another one.

In profiling, the channel send in monitor.go has been
seen to "leak" goroutines as the channel is not being
read from fast enough, but the root cause is not known.

Signed-off-by: Thomas Hartland <thomas.hartland@diamond.ac.uk>
2022-07-12 00:21:20 +08:00

601 lines
23 KiB
Go

package webhookconfig
import (
"context"
"encoding/json"
"fmt"
"reflect"
"strings"
"sync"
"time"
"github.com/go-logr/logr"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/utils"
"github.com/pkg/errors"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
errorsapi "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
admissionregistrationv1informers "k8s.io/client-go/informers/admissionregistration/v1"
appsv1informers "k8s.io/client-go/informers/apps/v1"
"k8s.io/client-go/kubernetes"
admissionregistrationv1listers "k8s.io/client-go/listers/admissionregistration/v1"
appsv1listers "k8s.io/client-go/listers/apps/v1"
rest "k8s.io/client-go/rest"
)
const (
kindMutating string = "MutatingWebhookConfiguration"
kindValidating string = "ValidatingWebhookConfiguration"
)
// Register manages webhook registration. There are five webhooks:
// 1. Policy Validation
// 2. Policy Mutation
// 3. Resource Validation
// 4. Resource Mutation
// 5. Webhook Status Mutation
type Register struct {
// clients
kubeClient kubernetes.Interface
clientConfig *rest.Config
// listers
mwcLister admissionregistrationv1listers.MutatingWebhookConfigurationLister
vwcLister admissionregistrationv1listers.ValidatingWebhookConfigurationLister
kDeplLister appsv1listers.DeploymentLister
// channels
stopCh <-chan struct{}
UpdateWebhookChan chan bool
createDefaultWebhook chan string
serverIP string // when running outside a cluster
timeoutSeconds int32
log logr.Logger
debug bool
autoUpdateWebhooks bool
// manage implements methods to manage webhook configurations
manage
}
// NewRegister creates new Register instance
func NewRegister(
clientConfig *rest.Config,
client dclient.Interface,
kubeClient kubernetes.Interface,
kyvernoClient kyvernoclient.Interface,
mwcInformer admissionregistrationv1informers.MutatingWebhookConfigurationInformer,
vwcInformer admissionregistrationv1informers.ValidatingWebhookConfigurationInformer,
kDeplInformer appsv1informers.DeploymentInformer,
pInformer kyvernov1informers.ClusterPolicyInformer,
npInformer kyvernov1informers.PolicyInformer,
serverIP string,
webhookTimeout int32,
debug bool,
autoUpdateWebhooks bool,
stopCh <-chan struct{},
log logr.Logger,
) *Register {
register := &Register{
clientConfig: clientConfig,
kubeClient: kubeClient,
mwcLister: mwcInformer.Lister(),
vwcLister: vwcInformer.Lister(),
kDeplLister: kDeplInformer.Lister(),
UpdateWebhookChan: make(chan bool),
createDefaultWebhook: make(chan string),
stopCh: stopCh,
serverIP: serverIP,
timeoutSeconds: webhookTimeout,
log: log.WithName("Register"),
debug: debug,
autoUpdateWebhooks: autoUpdateWebhooks,
}
register.manage = newWebhookConfigManager(client.Discovery(), kubeClient, kyvernoClient, pInformer, npInformer, mwcInformer, vwcInformer, serverIP, register.autoUpdateWebhooks, register.createDefaultWebhook, stopCh, log.WithName("WebhookConfigManager"))
return register
}
// Register clean up the old webhooks and re-creates admission webhooks configs on cluster
func (wrc *Register) Register() error {
logger := wrc.log
if wrc.serverIP != "" {
logger.Info("Registering webhook", "url", fmt.Sprintf("https://%s", wrc.serverIP))
}
if !wrc.debug {
if err := wrc.checkEndpoint(); err != nil {
return err
}
}
caData := wrc.readCaData()
if caData == nil {
return errors.New("Unable to extract CA data from configuration")
}
var errors []string
if err := wrc.createVerifyMutatingWebhookConfiguration(caData); err != nil {
errors = append(errors, err.Error())
}
if err := wrc.createPolicyValidatingWebhookConfiguration(caData); err != nil {
errors = append(errors, err.Error())
}
if err := wrc.createPolicyMutatingWebhookConfiguration(caData); err != nil {
errors = append(errors, err.Error())
}
if err := wrc.createResourceValidatingWebhookConfiguration(caData); err != nil {
errors = append(errors, err.Error())
}
if err := wrc.createResourceMutatingWebhookConfiguration(caData); err != nil {
errors = append(errors, err.Error())
}
if len(errors) > 0 {
return fmt.Errorf("%s", strings.Join(errors, ","))
}
go wrc.manage.start()
return nil
}
// Check returns an error if any of the webhooks are not configured
func (wrc *Register) Check() error {
if _, err := wrc.mwcLister.Get(getVerifyMutatingWebhookConfigName(wrc.serverIP)); err != nil {
return err
}
if _, err := wrc.mwcLister.Get(getResourceMutatingWebhookConfigName(wrc.serverIP)); err != nil {
return err
}
if _, err := wrc.vwcLister.Get(getResourceValidatingWebhookConfigName(wrc.serverIP)); err != nil {
return err
}
if _, err := wrc.mwcLister.Get(getPolicyMutatingWebhookConfigName(wrc.serverIP)); err != nil {
return err
}
if _, err := wrc.vwcLister.Get(getPolicyValidatingWebhookConfigName(wrc.serverIP)); err != nil {
return err
}
return nil
}
// Remove removes all webhook configurations
func (wrc *Register) Remove(cleanUp chan<- struct{}) {
defer close(cleanUp)
// delete Lease object to let init container do the cleanup
if err := wrc.kubeClient.CoordinationV1().Leases(config.KyvernoNamespace()).Delete(context.TODO(), "kyvernopre-lock", metav1.DeleteOptions{}); err != nil && errorsapi.IsNotFound(err) {
wrc.log.WithName("cleanup").Error(err, "failed to clean up Lease lock")
}
if wrc.shouldCleanupKyvernoResource() {
wrc.removeWebhookConfigurations()
}
}
// GetWebhookTimeOut returns the value of webhook timeout
func (wrc *Register) GetWebhookTimeOut() time.Duration {
return time.Duration(wrc.timeoutSeconds)
}
func (wrc *Register) UpdateWebhooksCaBundle() error {
selector := &metav1.LabelSelector{
MatchLabels: map[string]string{
managedByLabel: kyvernoValue,
},
}
caData := wrc.readCaData()
m := wrc.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations()
v := wrc.kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations()
if list, err := m.List(context.TODO(), metav1.ListOptions{LabelSelector: metav1.FormatLabelSelector(selector)}); err != nil {
return err
} else {
for _, item := range list.Items {
copy := item
for r := range copy.Webhooks {
copy.Webhooks[r].ClientConfig.CABundle = caData
}
if _, err := m.Update(context.TODO(), &copy, metav1.UpdateOptions{}); err != nil {
return err
}
}
}
if list, err := v.List(context.TODO(), metav1.ListOptions{LabelSelector: metav1.FormatLabelSelector(selector)}); err != nil {
return err
} else {
for _, item := range list.Items {
copy := item
for r := range copy.Webhooks {
copy.Webhooks[r].ClientConfig.CABundle = caData
}
if _, err := v.Update(context.TODO(), &copy, metav1.UpdateOptions{}); err != nil {
return err
}
}
}
return nil
}
// UpdateWebhookConfigurations updates resource webhook configurations dynamically
// based on the UPDATEs of Kyverno ConfigMap defined in INIT_CONFIG env
//
// it currently updates namespaceSelector only, can be extend to update other fields
// +deprecated
func (wrc *Register) UpdateWebhookConfigurations(configHandler config.Configuration) {
logger := wrc.log.WithName("UpdateWebhookConfigurations")
for {
<-wrc.UpdateWebhookChan
logger.V(4).Info("received the signal to update webhook configurations")
webhookCfgs := configHandler.GetWebhooks()
webhookCfg := config.WebhookConfig{}
if len(webhookCfgs) > 0 {
webhookCfg = webhookCfgs[0]
}
retry := false
if err := wrc.updateResourceMutatingWebhookConfiguration(webhookCfg); err != nil {
logger.Error(err, "unable to update mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
retry = true
}
if err := wrc.updateResourceValidatingWebhookConfiguration(webhookCfg); err != nil {
logger.Error(err, "unable to update validatingWebhookConfigurations", "name", getResourceValidatingWebhookConfigName(wrc.serverIP))
retry = true
}
if retry {
go func() {
time.Sleep(1 * time.Second)
select {
case wrc.UpdateWebhookChan <- true:
return
default:
return
}
}()
}
}
}
func (wrc *Register) ValidateWebhookConfigurations(namespace, name string) error {
logger := wrc.log.WithName("ValidateWebhookConfigurations")
cm, err := wrc.kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
logger.Error(err, "unable to fetch ConfigMap", "namespace", namespace, "name", name)
return nil
}
webhooks, ok := cm.Data["webhooks"]
if !ok {
logger.V(4).Info("webhook configurations not defined")
return nil
}
webhookCfgs := make([]config.WebhookConfig, 0, 10)
return json.Unmarshal([]byte(webhooks), &webhookCfgs)
}
func (wrc *Register) createMutatingWebhookConfiguration(config *admissionregistrationv1.MutatingWebhookConfiguration) error {
logger := wrc.log.WithValues("kind", kindMutating, "name", config.Name)
if _, err := wrc.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), config, metav1.CreateOptions{}); err != nil {
if errorsapi.IsAlreadyExists(err) {
logger.V(6).Info("resource mutating webhook configuration already exists", "name", config.Name)
return wrc.updateMutatingWebhookConfiguration(config)
}
logger.Error(err, "failed to create resource mutating webhook configuration", "name", config.Name)
return err
}
logger.Info("created webhook")
return nil
}
func (wrc *Register) createValidatingWebhookConfiguration(config *admissionregistrationv1.ValidatingWebhookConfiguration) error {
logger := wrc.log.WithValues("kind", kindValidating, "name", config.Name)
if _, err := wrc.kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(context.TODO(), config, metav1.CreateOptions{}); err != nil {
if errorsapi.IsAlreadyExists(err) {
logger.V(6).Info("resource validating webhook configuration already exists", "name", config.Name)
return wrc.updateValidatingWebhookConfiguration(config)
}
logger.Error(err, "failed to create resource validating webhook configuration", "name", config.Name)
return err
}
logger.Info("created webhook")
return nil
}
func (wrc *Register) createResourceMutatingWebhookConfiguration(caData []byte) error {
owner := wrc.constructOwner()
var config *admissionregistrationv1.MutatingWebhookConfiguration
if wrc.serverIP != "" {
config = constructDefaultDebugMutatingWebhookConfig(wrc.serverIP, caData, wrc.timeoutSeconds, wrc.autoUpdateWebhooks, owner)
} else {
config = constructDefaultMutatingWebhookConfig(caData, wrc.timeoutSeconds, wrc.autoUpdateWebhooks, owner)
}
return wrc.createMutatingWebhookConfiguration(config)
}
func (wrc *Register) createResourceValidatingWebhookConfiguration(caData []byte) error {
owner := wrc.constructOwner()
var config *admissionregistrationv1.ValidatingWebhookConfiguration
if wrc.serverIP != "" {
config = constructDefaultDebugValidatingWebhookConfig(wrc.serverIP, caData, wrc.timeoutSeconds, wrc.autoUpdateWebhooks, owner)
} else {
config = constructDefaultValidatingWebhookConfig(caData, wrc.timeoutSeconds, wrc.autoUpdateWebhooks, owner)
}
return wrc.createValidatingWebhookConfiguration(config)
}
func (wrc *Register) createPolicyValidatingWebhookConfiguration(caData []byte) error {
owner := wrc.constructOwner()
var config *admissionregistrationv1.ValidatingWebhookConfiguration
if wrc.serverIP != "" {
config = constructDebugPolicyValidatingWebhookConfig(wrc.serverIP, caData, wrc.timeoutSeconds, owner)
} else {
config = constructPolicyValidatingWebhookConfig(caData, wrc.timeoutSeconds, owner)
}
return wrc.createValidatingWebhookConfiguration(config)
}
func (wrc *Register) createPolicyMutatingWebhookConfiguration(caData []byte) error {
owner := wrc.constructOwner()
var config *admissionregistrationv1.MutatingWebhookConfiguration
if wrc.serverIP != "" {
config = constructDebugPolicyMutatingWebhookConfig(wrc.serverIP, caData, wrc.timeoutSeconds, owner)
} else {
config = constructPolicyMutatingWebhookConfig(caData, wrc.timeoutSeconds, owner)
}
return wrc.createMutatingWebhookConfiguration(config)
}
func (wrc *Register) createVerifyMutatingWebhookConfiguration(caData []byte) error {
owner := wrc.constructOwner()
var config *admissionregistrationv1.MutatingWebhookConfiguration
if wrc.serverIP != "" {
config = constructDebugVerifyMutatingWebhookConfig(wrc.serverIP, caData, wrc.timeoutSeconds, owner)
} else {
config = constructVerifyMutatingWebhookConfig(caData, wrc.timeoutSeconds, owner)
}
return wrc.createMutatingWebhookConfiguration(config)
}
func (wrc *Register) checkEndpoint() error {
endpoint, err := wrc.kubeClient.CoreV1().Endpoints(config.KyvernoNamespace()).Get(context.TODO(), config.KyvernoServiceName(), metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get endpoint %s/%s: %v", config.KyvernoNamespace(), config.KyvernoServiceName(), err)
}
selector := &metav1.LabelSelector{
MatchLabels: map[string]string{
"app.kubernetes.io/name": "kyverno",
},
}
pods, err := wrc.kubeClient.CoreV1().Pods(config.KyvernoNamespace()).List(context.TODO(), metav1.ListOptions{LabelSelector: metav1.FormatLabelSelector(selector)})
if err != nil {
return fmt.Errorf("failed to list Kyverno Pod: %v", err)
}
ips := getHealthyPodsIP(pods.Items)
if len(ips) == 0 {
return fmt.Errorf("pod is not assigned to any node yet")
}
for _, subset := range endpoint.Subsets {
if len(subset.Addresses) == 0 {
continue
}
for _, addr := range subset.Addresses {
if utils.ContainsString(ips, addr.IP) {
wrc.log.Info("Endpoint ready", "ns", config.KyvernoNamespace(), "name", config.KyvernoServiceName())
return nil
}
}
}
err = fmt.Errorf("endpoint not ready")
wrc.log.V(3).Info(err.Error(), "ns", config.KyvernoNamespace(), "name", config.KyvernoServiceName())
return err
}
func (wrc *Register) updateResourceValidatingWebhookConfiguration(webhookCfg config.WebhookConfig) error {
resource, err := wrc.vwcLister.Get(getResourceValidatingWebhookConfigName(wrc.serverIP))
if err != nil {
return errors.Wrapf(err, "unable to get validatingWebhookConfigurations")
}
copy := resource.DeepCopy()
for i := range copy.Webhooks {
copy.Webhooks[i].ObjectSelector = webhookCfg.ObjectSelector
copy.Webhooks[i].NamespaceSelector = webhookCfg.NamespaceSelector
}
if reflect.DeepEqual(resource.Webhooks, copy.Webhooks) {
wrc.log.V(4).Info("namespaceSelector unchanged, skip updating validatingWebhookConfigurations")
return nil
}
if _, err := wrc.kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), copy, metav1.UpdateOptions{}); err != nil {
return err
}
wrc.log.V(3).Info("successfully updated validatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
return nil
}
func (wrc *Register) updateResourceMutatingWebhookConfiguration(webhookCfg config.WebhookConfig) error {
resource, err := wrc.mwcLister.Get(getResourceMutatingWebhookConfigName(wrc.serverIP))
if err != nil {
return errors.Wrapf(err, "unable to get mutatingWebhookConfigurations")
}
copy := resource.DeepCopy()
for i := range copy.Webhooks {
copy.Webhooks[i].ObjectSelector = webhookCfg.ObjectSelector
copy.Webhooks[i].NamespaceSelector = webhookCfg.NamespaceSelector
}
if reflect.DeepEqual(resource.Webhooks, copy.Webhooks) {
wrc.log.V(4).Info("namespaceSelector unchanged, skip updating mutatingWebhookConfigurations")
return nil
}
if _, err := wrc.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(context.TODO(), copy, metav1.UpdateOptions{}); err != nil {
return err
}
wrc.log.V(3).Info("successfully updated mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
return nil
}
// updateMutatingWebhookConfiguration updates an existing MutatingWebhookConfiguration with the rules provided by
// the targetConfig. If the targetConfig doesn't provide any rules, the existing rules will be preserved.
func (wrc *Register) updateMutatingWebhookConfiguration(targetConfig *admissionregistrationv1.MutatingWebhookConfiguration) error {
// Fetch the existing webhook.
currentConfiguration, err := wrc.mwcLister.Get(targetConfig.Name)
if err != nil {
return fmt.Errorf("failed to get %s %s: %v", kindMutating, targetConfig.Name, err)
}
// Create a map of the target webhooks.
targetWebhooksMap := make(map[string]admissionregistrationv1.MutatingWebhook)
for _, w := range targetConfig.Webhooks {
targetWebhooksMap[w.Name] = w
}
// Update the webhooks.
newWebhooks := make([]admissionregistrationv1.MutatingWebhook, 0)
for _, w := range currentConfiguration.Webhooks {
target, exist := targetWebhooksMap[w.Name]
if !exist {
continue
}
delete(targetWebhooksMap, w.Name)
// Update the webhook configuration
w.ClientConfig.URL = target.ClientConfig.URL
w.ClientConfig.Service = target.ClientConfig.Service
w.ClientConfig.CABundle = target.ClientConfig.CABundle
if target.Rules != nil {
// If the target webhook has rule definitions override the current.
w.Rules = target.Rules
}
newWebhooks = append(newWebhooks, w)
}
// Check if there are additional webhooks defined and add them.
for _, w := range targetWebhooksMap {
newWebhooks = append(newWebhooks, w)
}
// Update the current configuration.
currentConfiguration.Webhooks = newWebhooks
if _, err := wrc.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(context.TODO(), currentConfiguration, metav1.UpdateOptions{}); err != nil {
return err
}
wrc.log.V(3).Info("successfully updated mutatingWebhookConfigurations", "name", targetConfig.Name)
return nil
}
// updateValidatingWebhookConfiguration updates an existing ValidatingWebhookConfiguration with the rules provided by
// the targetConfig. If the targetConfig doesn't provide any rules, the existing rules will be preserved.
func (wrc *Register) updateValidatingWebhookConfiguration(targetConfig *admissionregistrationv1.ValidatingWebhookConfiguration) error {
// Fetch the existing webhook.
currentConfiguration, err := wrc.vwcLister.Get(targetConfig.Name)
if err != nil {
return fmt.Errorf("failed to get %s %s: %v", kindValidating, targetConfig.Name, err)
}
// Create a map of the target webhooks.
targetWebhooksMap := make(map[string]admissionregistrationv1.ValidatingWebhook)
for _, w := range targetConfig.Webhooks {
targetWebhooksMap[w.Name] = w
}
// Update the webhooks.
newWebhooks := make([]admissionregistrationv1.ValidatingWebhook, 0)
for _, w := range currentConfiguration.Webhooks {
target, exist := targetWebhooksMap[w.Name]
if !exist {
continue
}
delete(targetWebhooksMap, w.Name)
// Update the webhook configuration
w.ClientConfig.URL = target.ClientConfig.URL
w.ClientConfig.Service = target.ClientConfig.Service
w.ClientConfig.CABundle = target.ClientConfig.CABundle
if target.Rules != nil {
// If the target webhook has rule definitions override the current.
w.Rules = target.Rules
}
newWebhooks = append(newWebhooks, w)
}
// Check if there are additional webhooks defined and add them.
for _, w := range targetWebhooksMap {
newWebhooks = append(newWebhooks, w)
}
// Update the current configuration.
currentConfiguration.Webhooks = newWebhooks
if _, err := wrc.kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), currentConfiguration, metav1.UpdateOptions{}); err != nil {
return err
}
wrc.log.V(3).Info("successfully updated validatingWebhookConfigurations", "name", targetConfig.Name)
return nil
}
func (wrc *Register) shouldCleanupKyvernoResource() bool {
logger := wrc.log.WithName("cleanupKyvernoResource")
deploy, err := wrc.kubeClient.AppsV1().Deployments(config.KyvernoNamespace()).Get(context.TODO(), config.KyvernoDeploymentName(), metav1.GetOptions{})
if err != nil {
if errorsapi.IsNotFound(err) {
logger.Info("Kyverno deployment not found, cleanup Kyverno resources")
return true
}
logger.Error(err, "failed to get deployment, not cleaning up kyverno resources")
return false
}
if deploy.GetDeletionTimestamp() != nil {
logger.Info("Kyverno is terminating, cleanup Kyverno resources")
return true
}
if deploy.Spec.Replicas != nil && *deploy.Spec.Replicas == 0 {
logger.Info("Kyverno is scaled to zero, cleanup Kyverno resources")
return true
}
logger.Info("updating Kyverno Pod, won't clean up Kyverno resources")
return false
}
func (wrc *Register) removeWebhookConfigurations() {
startTime := time.Now()
wrc.log.V(3).Info("deleting all webhook configurations")
defer wrc.log.V(4).Info("removed webhook configurations", "processingTime", time.Since(startTime).String())
var wg sync.WaitGroup
wg.Add(5)
go wrc.removeResourceMutatingWebhookConfiguration(&wg)
go wrc.removeResourceValidatingWebhookConfiguration(&wg)
go wrc.removePolicyMutatingWebhookConfiguration(&wg)
go wrc.removePolicyValidatingWebhookConfiguration(&wg)
go wrc.removeVerifyWebhookMutatingWebhookConfig(&wg)
wg.Wait()
}
func (wrc *Register) removeResourceMutatingWebhookConfiguration(wg *sync.WaitGroup) {
defer wg.Done()
wrc.removeMutatingWebhookConfiguration(getResourceMutatingWebhookConfigName(wrc.serverIP))
}
func (wrc *Register) removeResourceValidatingWebhookConfiguration(wg *sync.WaitGroup) {
defer wg.Done()
wrc.removeValidatingWebhookConfiguration(getResourceValidatingWebhookConfigName(wrc.serverIP))
}
func (wrc *Register) removePolicyMutatingWebhookConfiguration(wg *sync.WaitGroup) {
defer wg.Done()
wrc.removeMutatingWebhookConfiguration(getPolicyMutatingWebhookConfigName(wrc.serverIP))
}
func (wrc *Register) removePolicyValidatingWebhookConfiguration(wg *sync.WaitGroup) {
defer wg.Done()
wrc.removeValidatingWebhookConfiguration(getPolicyValidatingWebhookConfigName(wrc.serverIP))
}
func (wrc *Register) removeVerifyWebhookMutatingWebhookConfig(wg *sync.WaitGroup) {
defer wg.Done()
wrc.removeMutatingWebhookConfiguration(getVerifyMutatingWebhookConfigName(wrc.serverIP))
}
func (wrc *Register) removeMutatingWebhookConfiguration(name string) {
logger := wrc.log.WithValues("kind", kindMutating, "name", name)
if err := wrc.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil && !errorsapi.IsNotFound(err) {
logger.Error(err, "failed to delete the mutating webhook configuration")
} else {
logger.Info("webhook configuration deleted")
}
}
func (wrc *Register) removeValidatingWebhookConfiguration(name string) {
logger := wrc.log.WithValues("kind", kindValidating, "name", name)
if err := wrc.kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil && !errorsapi.IsNotFound(err) {
logger.Error(err, "failed to delete the validating webhook configuration")
} else {
logger.Info("webhook configuration deleted")
}
}