github.com/kubewharf/katalyst-core@v0.5.3/pkg/webhook/mutating/node/node.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package node
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	kubewebhook "github.com/slok/kubewebhook/pkg/webhook"
    25  	whcontext "github.com/slok/kubewebhook/pkg/webhook/context"
    26  	"github.com/slok/kubewebhook/pkg/webhook/mutating"
    27  	admissionv1beta1 "k8s.io/api/admission/v1beta1"
    28  	core "k8s.io/api/core/v1"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	"k8s.io/klog/v2"
    31  
    32  	katalystbase "github.com/kubewharf/katalyst-core/cmd/base"
    33  	webhookconsts "github.com/kubewharf/katalyst-core/cmd/katalyst-webhook/app/webhook"
    34  	"github.com/kubewharf/katalyst-core/pkg/config/generic"
    35  	webhookconfig "github.com/kubewharf/katalyst-core/pkg/config/webhook"
    36  	"github.com/kubewharf/katalyst-core/pkg/metrics"
    37  )
    38  
    39  type WebhookNodeMutator interface {
    40  	MutateNode(node *core.Node, admissionRequest *admissionv1beta1.AdmissionRequest) error
    41  	Name() string
    42  }
    43  
    44  // WebhookNode is the implementation of Kubernetes Webhook
    45  // any implementation should at least implement the interface of mutating.Mutator of validating.Validator
    46  type WebhookNode struct {
    47  	ctx context.Context
    48  
    49  	metricEmitter metrics.MetricEmitter
    50  
    51  	mutators []WebhookNodeMutator
    52  }
    53  
    54  func NewWebhookNode(
    55  	ctx context.Context,
    56  	webhookCtx *katalystbase.GenericContext,
    57  	_ *generic.GenericConfiguration,
    58  	_ *webhookconfig.GenericWebhookConfiguration,
    59  	_ *webhookconfig.WebhooksConfiguration,
    60  ) (kubewebhook.Webhook, webhookconsts.GenericStartFunc, error) {
    61  	metricEmitter := webhookCtx.EmitterPool.GetDefaultMetricsEmitter()
    62  	if metricEmitter == nil {
    63  		metricEmitter = metrics.DummyMetrics{}
    64  	}
    65  
    66  	wn := &WebhookNode{
    67  		ctx:           ctx,
    68  		metricEmitter: metricEmitter,
    69  		mutators:      []WebhookNodeMutator{},
    70  	}
    71  
    72  	wn.mutators = append(
    73  		wn.mutators,
    74  		NewWebhookNodeAllocatableMutator(),
    75  	)
    76  
    77  	cfg := mutating.WebhookConfig{
    78  		Name: "nodeMutator",
    79  		Obj:  &core.Node{},
    80  	}
    81  	webhook, err := mutating.NewWebhook(cfg, wn, nil, nil, nil)
    82  	if err != nil {
    83  		return nil, nil, err
    84  	}
    85  
    86  	return webhook, wn.Run, nil
    87  }
    88  
    89  func (wn *WebhookNode) Run() bool {
    90  	klog.Infof("node webhook run")
    91  
    92  	return true
    93  }
    94  
    95  func (wn *WebhookNode) Mutate(ctx context.Context, obj metav1.Object) (bool, error) {
    96  	klog.V(5).Info("webhookNode notice an obj to be mutated")
    97  
    98  	node, ok := obj.(*core.Node)
    99  	if !ok {
   100  		err := fmt.Errorf("failed to convert obj to node: %v", obj)
   101  		klog.Error(err)
   102  		return false, err
   103  	}
   104  	if node == nil {
   105  		err := fmt.Errorf("node can't be nil")
   106  		klog.Error(err)
   107  		return false, err
   108  	}
   109  
   110  	admissionRequest := whcontext.GetAdmissionRequest(ctx)
   111  	if admissionRequest == nil {
   112  		err := fmt.Errorf("failed to get admission request from ctx")
   113  		klog.Error(err)
   114  		return false, err
   115  	}
   116  
   117  	klog.V(5).Infof("begin to mutate node %s", node.Name)
   118  	for _, mutator := range wn.mutators {
   119  		start := time.Now()
   120  		err := mutator.MutateNode(node, admissionRequest)
   121  		if err != nil {
   122  			klog.Errorf("failed to mutate node %s: %v", node.Name, err)
   123  			wn.emitMetrics(false, start, mutator)
   124  			return false, err
   125  		}
   126  		wn.emitMetrics(true, start, mutator)
   127  	}
   128  	klog.Infof("node %s was mutated", node.Name)
   129  	return true, nil
   130  }
   131  
   132  func (wn *WebhookNode) emitMetrics(success bool, start time.Time, mutator WebhookNodeMutator) {
   133  	_ = wn.metricEmitter.StoreInt64("node_mutator_request_total", 1, metrics.MetricTypeNameCount, metrics.MetricTag{Key: "type", Val: mutator.Name()})
   134  	_ = wn.metricEmitter.StoreFloat64("node_mutator_latency", time.Since(start).Seconds(), metrics.MetricTypeNameCount, metrics.MetricTag{Key: "type", Val: mutator.Name()})
   135  	if !success {
   136  		_ = wn.metricEmitter.StoreInt64("node_mutator_request_fail", 1, metrics.MetricTypeNameCount, metrics.MetricTag{Key: "type", Val: mutator.Name()})
   137  	}
   138  }