177 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
| package resourceinterpreter
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 
 | |
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 | |
| 	"k8s.io/apimachinery/pkg/runtime/schema"
 | |
| 	"k8s.io/klog/v2"
 | |
| 
 | |
| 	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | |
| 	workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
 | |
| 	"github.com/karmada-io/karmada/pkg/resourceinterpreter/customizedinterpreter"
 | |
| 	"github.com/karmada-io/karmada/pkg/resourceinterpreter/customizedinterpreter/webhook"
 | |
| 	"github.com/karmada-io/karmada/pkg/resourceinterpreter/defaultinterpreter"
 | |
| 	"github.com/karmada-io/karmada/pkg/util/informermanager"
 | |
| )
 | |
| 
 | |
| // ResourceInterpreter manages both default and customized webhooks to interpret custom resource structure.
 | |
| type ResourceInterpreter interface {
 | |
| 	// Start starts running the component and will never stop running until the context is closed or an error occurs.
 | |
| 	Start(ctx context.Context) (err error)
 | |
| 
 | |
| 	// HookEnabled tells if any hook exist for specific resource type and operation.
 | |
| 	HookEnabled(objGVK schema.GroupVersionKind, operationType configv1alpha1.InterpreterOperation) bool
 | |
| 
 | |
| 	// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | |
| 	GetReplicas(object *unstructured.Unstructured) (replica int32, replicaRequires *workv1alpha2.ReplicaRequirements, err error)
 | |
| 
 | |
| 	// ReviseReplica revises the replica of the given object.
 | |
| 	ReviseReplica(object *unstructured.Unstructured, replica int64) (*unstructured.Unstructured, error)
 | |
| 
 | |
| 	// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
 | |
| 	Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error)
 | |
| 
 | |
| 	// AggregateStatus returns the objects that based on the 'object' but with status aggregated.
 | |
| 	AggregateStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error)
 | |
| 
 | |
| 	// GetDependencies returns the dependent resources of the given object.
 | |
| 	GetDependencies(object *unstructured.Unstructured) (dependencies []configv1alpha1.DependentObjectReference, err error)
 | |
| 	// other common method
 | |
| }
 | |
| 
 | |
| // NewResourceInterpreter builds a new ResourceInterpreter object.
 | |
| func NewResourceInterpreter(kubeconfig string, informer informermanager.SingleClusterInformerManager) ResourceInterpreter {
 | |
| 	return &customResourceInterpreterImpl{
 | |
| 		kubeconfig: kubeconfig,
 | |
| 		informer:   informer,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type customResourceInterpreterImpl struct {
 | |
| 	kubeconfig string
 | |
| 	informer   informermanager.SingleClusterInformerManager
 | |
| 
 | |
| 	customizedInterpreter *customizedinterpreter.CustomizedInterpreter
 | |
| 	defaultInterpreter    *defaultinterpreter.DefaultInterpreter
 | |
| }
 | |
| 
 | |
| // Start starts running the component and will never stop running until the context is closed or an error occurs.
 | |
| func (i *customResourceInterpreterImpl) Start(ctx context.Context) (err error) {
 | |
| 	klog.Infof("Starting custom resource interpreter.")
 | |
| 
 | |
| 	i.customizedInterpreter, err = customizedinterpreter.NewCustomizedInterpreter(i.kubeconfig, i.informer)
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	i.defaultInterpreter = defaultinterpreter.NewDefaultInterpreter()
 | |
| 
 | |
| 	i.informer.Start()
 | |
| 	<-ctx.Done()
 | |
| 	klog.Infof("Stopped as stopCh closed.")
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // HookEnabled tells if any hook exist for specific resource type and operation.
 | |
| func (i *customResourceInterpreterImpl) HookEnabled(objGVK schema.GroupVersionKind, operation configv1alpha1.InterpreterOperation) bool {
 | |
| 	return i.customizedInterpreter.HookEnabled(objGVK, operation) ||
 | |
| 		i.defaultInterpreter.HookEnabled(objGVK, operation)
 | |
| }
 | |
| 
 | |
| // GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | |
| func (i *customResourceInterpreterImpl) GetReplicas(object *unstructured.Unstructured) (replica int32, requires *workv1alpha2.ReplicaRequirements, err error) {
 | |
| 	klog.V(4).Infof("Begin to get replicas for request object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
 | |
| 
 | |
| 	var hookEnabled bool
 | |
| 	replica, requires, hookEnabled, err = i.customizedInterpreter.GetReplicas(context.TODO(), &webhook.RequestAttributes{
 | |
| 		Operation: configv1alpha1.InterpreterOperationInterpretReplica,
 | |
| 		Object:    object,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 	if hookEnabled {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	replica, requires, err = i.defaultInterpreter.GetReplicas(object)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // ReviseReplica revises the replica of the given object.
 | |
| func (i *customResourceInterpreterImpl) ReviseReplica(object *unstructured.Unstructured, replica int64) (*unstructured.Unstructured, error) {
 | |
| 	klog.V(4).Infof("Begin to revise replicas for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
 | |
| 
 | |
| 	obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
 | |
| 		Operation:   configv1alpha1.InterpreterOperationReviseReplica,
 | |
| 		Object:      object,
 | |
| 		ReplicasSet: int32(replica),
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if hookEnabled {
 | |
| 		return obj, nil
 | |
| 	}
 | |
| 
 | |
| 	return i.defaultInterpreter.ReviseReplica(object, replica)
 | |
| }
 | |
| 
 | |
| // Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
 | |
| func (i *customResourceInterpreterImpl) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (*unstructured.Unstructured, error) {
 | |
| 	klog.V(4).Infof("Begin to retain object: %v %s/%s.", desired.GroupVersionKind(), desired.GetNamespace(), desired.GetName())
 | |
| 
 | |
| 	obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
 | |
| 		Operation:   configv1alpha1.InterpreterOperationRetain,
 | |
| 		Object:      desired,
 | |
| 		ObservedObj: observed,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if hookEnabled {
 | |
| 		return obj, nil
 | |
| 	}
 | |
| 
 | |
| 	return i.defaultInterpreter.Retain(desired, observed)
 | |
| }
 | |
| 
 | |
| // AggregateStatus returns the objects that based on the 'object' but with status aggregated.
 | |
| func (i *customResourceInterpreterImpl) AggregateStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error) {
 | |
| 	klog.V(4).Infof("Begin to aggregate status for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
 | |
| 
 | |
| 	obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
 | |
| 		Operation:        configv1alpha1.InterpreterOperationAggregateStatus,
 | |
| 		Object:           object.DeepCopy(),
 | |
| 		AggregatedStatus: aggregatedStatusItems,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if hookEnabled {
 | |
| 		return obj, nil
 | |
| 	}
 | |
| 
 | |
| 	return i.defaultInterpreter.AggregateStatus(object, aggregatedStatusItems)
 | |
| }
 | |
| 
 | |
| // GetDependencies returns the dependent resources of the given object.
 | |
| func (i *customResourceInterpreterImpl) GetDependencies(object *unstructured.Unstructured) (dependencies []configv1alpha1.DependentObjectReference, err error) {
 | |
| 	klog.V(4).Infof("Begin to get dependencies for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
 | |
| 
 | |
| 	dependencies, hookEnabled, err := i.customizedInterpreter.GetDependencies(context.TODO(), &webhook.RequestAttributes{
 | |
| 		Operation: configv1alpha1.InterpreterOperationInterpretDependency,
 | |
| 		Object:    object,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 	if hookEnabled {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	dependencies, err = i.defaultInterpreter.GetDependencies(object)
 | |
| 	return
 | |
| }
 |