Merge pull request #998 from XiShanYongYe-Chang/update-explorewebhook
Update resource interpreter api (aka. explorewebhook)
This commit is contained in:
		
						commit
						b1a48a82ea
					
				| 
						 | 
				
			
			@ -116,10 +116,10 @@ webhooks:
 | 
			
		|||
      - operations: ["CREATE", "UPDATE"]
 | 
			
		||||
        apiGroups: ["config.karmada.io"]
 | 
			
		||||
        apiVersions: ["*"]
 | 
			
		||||
        resources: ["resourceexploringwebhookconfigurations"]
 | 
			
		||||
        resources: ["resourceinterpreterwebhookconfigurations"]
 | 
			
		||||
        scope: "Cluster"
 | 
			
		||||
    clientConfig:
 | 
			
		||||
      url: https://karmada-webhook.karmada-system.svc:443/validate-resourceexploringwebhookconfiguration
 | 
			
		||||
      url: https://karmada-webhook.karmada-system.svc:443/validate-resourceinterpreterwebhookconfiguration
 | 
			
		||||
      caBundle: {{caBundle}}
 | 
			
		||||
    failurePolicy: Fail
 | 
			
		||||
    sideEffects: None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,20 +6,20 @@ metadata:
 | 
			
		|||
  annotations:
 | 
			
		||||
    controller-gen.kubebuilder.io/version: v0.6.2
 | 
			
		||||
  creationTimestamp: null
 | 
			
		||||
  name: resourceexploringwebhookconfigurations.config.karmada.io
 | 
			
		||||
  name: resourceinterpreterwebhookconfigurations.config.karmada.io
 | 
			
		||||
spec:
 | 
			
		||||
  group: config.karmada.io
 | 
			
		||||
  names:
 | 
			
		||||
    kind: ResourceExploringWebhookConfiguration
 | 
			
		||||
    listKind: ResourceExploringWebhookConfigurationList
 | 
			
		||||
    plural: resourceexploringwebhookconfigurations
 | 
			
		||||
    singular: resourceexploringwebhookconfiguration
 | 
			
		||||
    kind: ResourceInterpreterWebhookConfiguration
 | 
			
		||||
    listKind: ResourceInterpreterWebhookConfigurationList
 | 
			
		||||
    plural: resourceinterpreterwebhookconfigurations
 | 
			
		||||
    singular: resourceinterpreterwebhookconfiguration
 | 
			
		||||
  scope: Cluster
 | 
			
		||||
  versions:
 | 
			
		||||
  - name: v1alpha1
 | 
			
		||||
    schema:
 | 
			
		||||
      openAPIV3Schema:
 | 
			
		||||
        description: ResourceExploringWebhookConfiguration describes the configuration
 | 
			
		||||
        description: ResourceInterpreterWebhookConfiguration describes the configuration
 | 
			
		||||
          of webhooks which take the responsibility to tell karmada the details of
 | 
			
		||||
          the resource object, especially for custom resources.
 | 
			
		||||
        properties:
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ spec:
 | 
			
		|||
            description: Webhooks is a list of webhooks and the affected resources
 | 
			
		||||
              and operations.
 | 
			
		||||
            items:
 | 
			
		||||
              description: ResourceExploringWebhook describes the webhook as well
 | 
			
		||||
              description: ResourceInterpreterWebhook describes the webhook as well
 | 
			
		||||
                as the resources and operations it applies to.
 | 
			
		||||
              properties:
 | 
			
		||||
                clientConfig:
 | 
			
		||||
| 
						 | 
				
			
			@ -100,23 +100,18 @@ spec:
 | 
			
		|||
                        and query parameters (\"?...\") are not allowed, either."
 | 
			
		||||
                      type: string
 | 
			
		||||
                  type: object
 | 
			
		||||
                exploreReviewVersions:
 | 
			
		||||
                  description: ExploreReviewVersions is an ordered list of preferred
 | 
			
		||||
                    `ExploreReview` versions the Webhook expects. Karmada will try
 | 
			
		||||
                    to use first version in the list which it supports. If none of
 | 
			
		||||
                    the versions specified in this list supported by Karmada, validation
 | 
			
		||||
                    will fail for this object. If a persisted webhook configuration
 | 
			
		||||
                interpreterContextVersions:
 | 
			
		||||
                  description: InterpreterContextVersions is an ordered list of preferred
 | 
			
		||||
                    `ResourceInterpreterContext` versions the Webhook expects. Karmada
 | 
			
		||||
                    will try to use first version in the list which it supports. If
 | 
			
		||||
                    none of the versions specified in this list supported by Karmada,
 | 
			
		||||
                    validation will fail for this object. If a persisted webhook configuration
 | 
			
		||||
                    specifies allowed versions and does not include any versions known
 | 
			
		||||
                    to the Karmada, calls to the webhook will fail and be subject
 | 
			
		||||
                    to the failure policy.
 | 
			
		||||
                  items:
 | 
			
		||||
                    type: string
 | 
			
		||||
                  type: array
 | 
			
		||||
                failurePolicy:
 | 
			
		||||
                  description: FailurePolicy defines how unrecognized errors from
 | 
			
		||||
                    the webhook are handled, allowed values are Ignore or Fail. Defaults
 | 
			
		||||
                    to Fail.
 | 
			
		||||
                  type: string
 | 
			
		||||
                name:
 | 
			
		||||
                  description: Name is the full-qualified name of the webhook.
 | 
			
		||||
                  type: string
 | 
			
		||||
| 
						 | 
				
			
			@ -160,8 +155,8 @@ spec:
 | 
			
		|||
                        description: Operations is the operations the hook cares about.
 | 
			
		||||
                          If '*' is present, the length of the slice must be one.
 | 
			
		||||
                        items:
 | 
			
		||||
                          description: OperationType specifies an operation for a
 | 
			
		||||
                            request.
 | 
			
		||||
                          description: InterpreterOperation specifies an operation
 | 
			
		||||
                            for a request.
 | 
			
		||||
                          type: string
 | 
			
		||||
                        type: array
 | 
			
		||||
                    required:
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +175,7 @@ spec:
 | 
			
		|||
                  type: integer
 | 
			
		||||
              required:
 | 
			
		||||
              - clientConfig
 | 
			
		||||
              - exploreReviewVersions
 | 
			
		||||
              - interpreterContextVersions
 | 
			
		||||
              - name
 | 
			
		||||
              type: object
 | 
			
		||||
            type: array
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ resources:
 | 
			
		|||
- bases/work.karmada.io_resourcebindings.yaml
 | 
			
		||||
- bases/work.karmada.io_clusterresourcebindings.yaml
 | 
			
		||||
- bases/work.karmada.io_works.yaml
 | 
			
		||||
- bases/config.karmada.io_resourceexploringwebhookconfigurations.yaml
 | 
			
		||||
- bases/config.karmada.io_resourceinterpreterwebhookconfigurations.yaml
 | 
			
		||||
 | 
			
		||||
patchesStrategicMerge:
 | 
			
		||||
- patches/webhook_in_resourcebindings.yaml
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,10 +120,10 @@ webhooks:
 | 
			
		|||
      - operations: ["CREATE", "UPDATE"]
 | 
			
		||||
        apiGroups: ["config.karmada.io"]
 | 
			
		||||
        apiVersions: ["*"]
 | 
			
		||||
        resources: ["resourceexploringwebhookconfigurations"]
 | 
			
		||||
        resources: ["resourceinterpreterwebhookconfigurations"]
 | 
			
		||||
        scope: "Cluster"
 | 
			
		||||
    clientConfig:
 | 
			
		||||
      url: https://{{ $name }}-webhook.{{ $namespace }}.svc:443/validate-resourceexploringwebhookconfiguration
 | 
			
		||||
      url: https://{{ $name }}-webhook.{{ $namespace }}.svc:443/validate-resourceinterpreterwebhookconfiguration
 | 
			
		||||
      {{- include "karmada.webhook.caBundle" . | nindent 6 }}
 | 
			
		||||
    failurePolicy: Fail
 | 
			
		||||
    sideEffects: None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,8 @@ import (
 | 
			
		|||
	"github.com/karmada-io/karmada/pkg/controllers/execution"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/controllers/mcs"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/controllers/status"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/karmadactl"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/gclient"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/helper"
 | 
			
		||||
| 
						 | 
				
			
			@ -131,12 +131,12 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
 | 
			
		|||
	restConfig := mgr.GetConfig()
 | 
			
		||||
	dynamicClientSet := dynamic.NewForConfigOrDie(restConfig)
 | 
			
		||||
	controlPlaneInformerManager := informermanager.NewSingleClusterInformerManager(dynamicClientSet, 0, stopChan)
 | 
			
		||||
	crdExplorer := crdexplorer.NewCustomResourceExplorer("", controlPlaneInformerManager)
 | 
			
		||||
	if err := mgr.Add(crdExplorer); err != nil {
 | 
			
		||||
		klog.Fatalf("Failed to setup custom resource explorer: %v", err)
 | 
			
		||||
	resourceInterpreter := resourceinterpreter.NewResourceInterpreter("", controlPlaneInformerManager)
 | 
			
		||||
	if err := mgr.Add(resourceInterpreter); err != nil {
 | 
			
		||||
		klog.Fatalf("Failed to setup custom resource interpreter: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	objectWatcher := objectwatcher.NewObjectWatcher(mgr.GetClient(), mgr.GetRESTMapper(), util.NewClusterDynamicClientSetForAgent, crdExplorer)
 | 
			
		||||
	objectWatcher := objectwatcher.NewObjectWatcher(mgr.GetClient(), mgr.GetRESTMapper(), util.NewClusterDynamicClientSetForAgent, resourceInterpreter)
 | 
			
		||||
	executionController := &execution.Controller{
 | 
			
		||||
		Client:          mgr.GetClient(),
 | 
			
		||||
		EventRecorder:   mgr.GetEventRecorderFor(execution.ControllerName),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,9 @@ import (
 | 
			
		|||
	"github.com/karmada-io/karmada/pkg/controllers/mcs"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/controllers/namespace"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/controllers/status"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/detector"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/karmadactl"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/gclient"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/helper"
 | 
			
		||||
| 
						 | 
				
			
			@ -124,12 +124,12 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
 | 
			
		|||
 | 
			
		||||
	controlPlaneInformerManager := informermanager.NewSingleClusterInformerManager(dynamicClientSet, 0, stopChan)
 | 
			
		||||
 | 
			
		||||
	crdExplorer := crdexplorer.NewCustomResourceExplorer("", controlPlaneInformerManager)
 | 
			
		||||
	if err := mgr.Add(crdExplorer); err != nil {
 | 
			
		||||
		klog.Fatalf("Failed to setup custom resource explorer: %v", err)
 | 
			
		||||
	resourceInterpreter := resourceinterpreter.NewResourceInterpreter("", controlPlaneInformerManager)
 | 
			
		||||
	if err := mgr.Add(resourceInterpreter); err != nil {
 | 
			
		||||
		klog.Fatalf("Failed to setup custom resource interpreter: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	objectWatcher := objectwatcher.NewObjectWatcher(mgr.GetClient(), mgr.GetRESTMapper(), util.NewClusterDynamicClientSet, crdExplorer)
 | 
			
		||||
	objectWatcher := objectwatcher.NewObjectWatcher(mgr.GetClient(), mgr.GetRESTMapper(), util.NewClusterDynamicClientSet, resourceInterpreter)
 | 
			
		||||
 | 
			
		||||
	resourceDetector := &detector.ResourceDetector{
 | 
			
		||||
		DiscoveryClientSet:           discoverClientSet,
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
 | 
			
		|||
		DynamicClient:                dynamicClientSet,
 | 
			
		||||
		SkippedResourceConfig:        skippedResourceConfig,
 | 
			
		||||
		SkippedPropagatingNamespaces: skippedPropagatingNamespaces,
 | 
			
		||||
		ResourceExplorer:             crdExplorer,
 | 
			
		||||
		ResourceInterpreter:          resourceInterpreter,
 | 
			
		||||
	}
 | 
			
		||||
	if err := mgr.Add(resourceDetector); err != nil {
 | 
			
		||||
		klog.Fatalf("Failed to setup resource detector: %v", err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ import (
 | 
			
		|||
	"github.com/karmada-io/karmada/pkg/version/sharedcommand"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/cluster"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/clusterpropagationpolicy"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/configuration"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/overridepolicy"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/propagationpolicy"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/webhook/work"
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ func Run(ctx context.Context, opts *options.Options) error {
 | 
			
		|||
	hookServer.Register("/mutate-overridepolicy", &webhook.Admission{Handler: &overridepolicy.MutatingAdmission{}})
 | 
			
		||||
	hookServer.Register("/mutate-work", &webhook.Admission{Handler: &work.MutatingAdmission{}})
 | 
			
		||||
	hookServer.Register("/convert", &conversion.Webhook{})
 | 
			
		||||
	hookServer.Register("/validate-resourceexploringwebhookconfiguration", &webhook.Admission{Handler: &crdexplorer.ValidatingAdmission{}})
 | 
			
		||||
	hookServer.Register("/validate-resourceinterpreterwebhookconfiguration", &webhook.Admission{Handler: &configuration.ValidatingAdmission{}})
 | 
			
		||||
	hookServer.WebhookMux.Handle("/readyz/", http.StripPrefix("/readyz/", &healthz.Handler{}))
 | 
			
		||||
 | 
			
		||||
	// blocks until the context is done.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
# Examples
 | 
			
		||||
 | 
			
		||||
### Custom Resource Explorer
 | 
			
		||||
This example implements a new CustomResourceDefinition(CRD), `Workload`, and creates a custom resource explorer webhook.
 | 
			
		||||
### Resource Interpreter
 | 
			
		||||
This example implements a new CustomResourceDefinition(CRD), `Workload`, and creates a resource interpreter webhook.
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +40,8 @@ deepcopy-gen \
 | 
			
		|||
  --output-file-base=zz_generated.deepcopy
 | 
			
		||||
deepcopy-gen \
 | 
			
		||||
  --go-header-file hack/boilerplate/boilerplate.go.txt \
 | 
			
		||||
  --input-dirs=github.com/karmada-io/karmada/examples/customresourceexplorer/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-package=github.com/karmada-io/karmada/examples/customresourceexplorer/apis/workload/v1alpha1 \
 | 
			
		||||
  --input-dirs=github.com/karmada-io/karmada/examples/customresourceinterpreter/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-package=github.com/karmada-io/karmada/examples/customresourceinterpreter/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-file-base=zz_generated.deepcopy
 | 
			
		||||
 | 
			
		||||
echo "Generating with register-gen"
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +73,8 @@ register-gen \
 | 
			
		|||
  --output-file-base=zz_generated.register
 | 
			
		||||
register-gen \
 | 
			
		||||
  --go-header-file hack/boilerplate/boilerplate.go.txt \
 | 
			
		||||
  --input-dirs=github.com/karmada-io/karmada/examples/customresourceexplorer/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-package=github.com/karmada-io/karmada/examples/customresourceexplorer/apis/workload/v1alpha1 \
 | 
			
		||||
  --input-dirs=github.com/karmada-io/karmada/examples/customresourceinterpreter/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-package=github.com/karmada-io/karmada/examples/customresourceinterpreter/apis/workload/v1alpha1 \
 | 
			
		||||
  --output-file-base=zz_generated.register
 | 
			
		||||
 | 
			
		||||
echo "Generating with client-gen"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,4 +14,4 @@ util::install_tools ${CONTROLLER_GEN_PKG} ${CONTROLLER_GEN_VER} >/dev/null 2>&1
 | 
			
		|||
 | 
			
		||||
# Unify the crds used by helm chart and the installation scripts
 | 
			
		||||
controller-gen crd paths=./pkg/apis/... output:crd:dir=./charts/_crds/bases
 | 
			
		||||
controller-gen crd paths=./examples/customresourceexplorer/apis/... output:crd:dir=./examples/customresourceexplorer/apis/
 | 
			
		||||
controller-gen crd paths=./examples/customresourceinterpreter/apis/... output:crd:dir=./examples/customresourceinterpreter/apis/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,21 +11,21 @@ import (
 | 
			
		|||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// ExploreReview describes an explore review request and response.
 | 
			
		||||
type ExploreReview struct {
 | 
			
		||||
// ResourceInterpreterContext describes an interpreter context request and response.
 | 
			
		||||
type ResourceInterpreterContext struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
 | 
			
		||||
	// Request describes the attributes for the explore request.
 | 
			
		||||
	// Request describes the attributes for the interpreter request.
 | 
			
		||||
	// +optional
 | 
			
		||||
	Request *ExploreRequest `json:"request,omitempty"`
 | 
			
		||||
	Request *ResourceInterpreterRequest `json:"request,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Response describes the attributes for the explore response.
 | 
			
		||||
	// Response describes the attributes for the interpreter response.
 | 
			
		||||
	// +optional
 | 
			
		||||
	Response *ExploreResponse `json:"response,omitempty"`
 | 
			
		||||
	Response *ResourceInterpreterResponse `json:"response,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExploreRequest describes the explore.Attributes for the explore request.
 | 
			
		||||
type ExploreRequest struct {
 | 
			
		||||
// ResourceInterpreterRequest describes the interpreter.Attributes for the interpreter request.
 | 
			
		||||
type ResourceInterpreterRequest struct {
 | 
			
		||||
	// UID is an identifier for the individual request/response.
 | 
			
		||||
	// The UID is meant to track the round trip (request/response) between the karmada and the WebHook, not the user request.
 | 
			
		||||
	// It is suitable for correlating log entries between the webhook and karmada, for either auditing or debugging.
 | 
			
		||||
| 
						 | 
				
			
			@ -46,19 +46,19 @@ type ExploreRequest struct {
 | 
			
		|||
 | 
			
		||||
	// Operation is the operation being performed.
 | 
			
		||||
	// +required
 | 
			
		||||
	Operation OperationType `json:"operation"`
 | 
			
		||||
	Operation InterpreterOperation `json:"operation"`
 | 
			
		||||
 | 
			
		||||
	// Object is the object from the incoming request.
 | 
			
		||||
	// +optional
 | 
			
		||||
	Object runtime.RawExtension `json:"object,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// ObservedObject is the object observed from the kube-apiserver of member clusters.
 | 
			
		||||
	// Not nil only when OperationType is ExploreRetaining.
 | 
			
		||||
	// Not nil only when InterpreterOperation is InterpreterOperationRetain.
 | 
			
		||||
	// +optional
 | 
			
		||||
	ObservedObject *runtime.RawExtension `json:"observedObject,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// DesiredReplicas represents the desired pods number which webhook should revise with.
 | 
			
		||||
	// It'll be set only if OperationType is ExploreReplicaRevising.
 | 
			
		||||
	// It'll be set only if InterpreterOperation is InterpreterOperationReviseReplica.
 | 
			
		||||
	// +optional
 | 
			
		||||
	DesiredReplicas *int32 `json:"replicas,omitempty"`
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,10 +67,10 @@ type ExploreRequest struct {
 | 
			
		|||
	AggregatedStatus []workv1alpha1.AggregatedStatusItem `json:"aggregatedStatus,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExploreResponse describes an explore response.
 | 
			
		||||
type ExploreResponse struct {
 | 
			
		||||
// ResourceInterpreterResponse describes an interpreter response.
 | 
			
		||||
type ResourceInterpreterResponse struct {
 | 
			
		||||
	// UID is an identifier for the individual request/response.
 | 
			
		||||
	// This must be copied over from the corresponding ExploreRequest.
 | 
			
		||||
	// This must be copied over from the corresponding ResourceInterpreterRequest.
 | 
			
		||||
	// +required
 | 
			
		||||
	UID types.UID `json:"uid"`
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -92,18 +92,18 @@ type ExploreResponse struct {
 | 
			
		|||
	PatchType *PatchType `json:"patchType,omitempty" protobuf:"bytes,5,opt,name=patchType"`
 | 
			
		||||
 | 
			
		||||
	// ReplicaRequirements represents the requirements required by each replica.
 | 
			
		||||
	// Required if OperationType is ExploreReplica.
 | 
			
		||||
	// Required if InterpreterOperation is InterpreterOperationInterpretReplica.
 | 
			
		||||
	// +optional
 | 
			
		||||
	ReplicaRequirements *workv1alpha2.ReplicaRequirements `json:"replicaRequirements,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Replicas represents the number of desired pods. This is a pointer to distinguish between explicit
 | 
			
		||||
	// zero and not specified.
 | 
			
		||||
	// Required if OperationType is ExploreReplica.
 | 
			
		||||
	// Required if InterpreterOperation is InterpreterOperationInterpretReplica.
 | 
			
		||||
	// +optional
 | 
			
		||||
	Replicas *int32 `json:"replicas,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Dependencies represents the reference of dependencies object.
 | 
			
		||||
	// Required if OperationType is ExploreDependencies.
 | 
			
		||||
	// Required if InterpreterOperation is InterpreterOperationInterpretDependency.
 | 
			
		||||
	// +optional
 | 
			
		||||
	Dependencies []DependentObjectReference `json:"dependencies,omitempty"`
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,19 +11,19 @@ import (
 | 
			
		|||
// +kubebuilder:resource:scope="Cluster"
 | 
			
		||||
// +kubebuilder:storageversion
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfiguration describes the configuration of webhooks which take the responsibility to
 | 
			
		||||
// ResourceInterpreterWebhookConfiguration describes the configuration of webhooks which take the responsibility to
 | 
			
		||||
// tell karmada the details of the resource object, especially for custom resources.
 | 
			
		||||
type ResourceExploringWebhookConfiguration struct {
 | 
			
		||||
type ResourceInterpreterWebhookConfiguration struct {
 | 
			
		||||
	metav1.TypeMeta   `json:",inline"`
 | 
			
		||||
	metav1.ObjectMeta `json:"metadata,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Webhooks is a list of webhooks and the affected resources and operations.
 | 
			
		||||
	// +required
 | 
			
		||||
	Webhooks []ResourceExploringWebhook `json:"webhooks"`
 | 
			
		||||
	Webhooks []ResourceInterpreterWebhook `json:"webhooks"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhook describes the webhook as well as the resources and operations it applies to.
 | 
			
		||||
type ResourceExploringWebhook struct {
 | 
			
		||||
// ResourceInterpreterWebhook describes the webhook as well as the resources and operations it applies to.
 | 
			
		||||
type ResourceInterpreterWebhook struct {
 | 
			
		||||
	// Name is the full-qualified name of the webhook.
 | 
			
		||||
	// +required
 | 
			
		||||
	Name string `json:"name"`
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +37,6 @@ type ResourceExploringWebhook struct {
 | 
			
		|||
	// +optional
 | 
			
		||||
	Rules []RuleWithOperations `json:"rules,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// FailurePolicy defines how unrecognized errors from the webhook are handled,
 | 
			
		||||
	// allowed values are Ignore or Fail. Defaults to Fail.
 | 
			
		||||
	// +optional
 | 
			
		||||
	FailurePolicy *admissionregistrationv1.FailurePolicyType `json:"failurePolicy,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// TimeoutSeconds specifies the timeout for this webhook. After the timeout passes,
 | 
			
		||||
	// the webhook call will be ignored or the API call will fail based on the
 | 
			
		||||
	// failure policy.
 | 
			
		||||
| 
						 | 
				
			
			@ -50,14 +45,14 @@ type ResourceExploringWebhook struct {
 | 
			
		|||
	// +optional
 | 
			
		||||
	TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// ExploreReviewVersions is an ordered list of preferred `ExploreReview`
 | 
			
		||||
	// InterpreterContextVersions is an ordered list of preferred `ResourceInterpreterContext`
 | 
			
		||||
	// versions the Webhook expects. Karmada will try to use first version in
 | 
			
		||||
	// the list which it supports. If none of the versions specified in this list
 | 
			
		||||
	// supported by Karmada, validation will fail for this object.
 | 
			
		||||
	// If a persisted webhook configuration specifies allowed versions and does not
 | 
			
		||||
	// include any versions known to the Karmada, calls to the webhook will fail
 | 
			
		||||
	// and be subject to the failure policy.
 | 
			
		||||
	ExploreReviewVersions []string `json:"exploreReviewVersions"`
 | 
			
		||||
	InterpreterContextVersions []string `json:"interpreterContextVersions"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RuleWithOperations is a tuple of Operations and Resources. It is recommended to make
 | 
			
		||||
| 
						 | 
				
			
			@ -66,50 +61,50 @@ type RuleWithOperations struct {
 | 
			
		|||
	// Operations is the operations the hook cares about.
 | 
			
		||||
	// If '*' is present, the length of the slice must be one.
 | 
			
		||||
	// +required
 | 
			
		||||
	Operations []OperationType `json:"operations"`
 | 
			
		||||
	Operations []InterpreterOperation `json:"operations"`
 | 
			
		||||
 | 
			
		||||
	// Rule is embedded, it describes other criteria of the rule, like
 | 
			
		||||
	// APIGroups, APIVersions, Kinds, etc.
 | 
			
		||||
	Rule `json:",inline"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OperationType specifies an operation for a request.
 | 
			
		||||
type OperationType string
 | 
			
		||||
// InterpreterOperation specifies an operation for a request.
 | 
			
		||||
type InterpreterOperation string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// OperationAll indicates math all OperationType.
 | 
			
		||||
	OperationAll OperationType = "*"
 | 
			
		||||
	// InterpreterOperationAll indicates math all InterpreterOperation.
 | 
			
		||||
	InterpreterOperationAll InterpreterOperation = "*"
 | 
			
		||||
 | 
			
		||||
	// ExploreReplica indicates that karmada want to figure out the replica declaration of a specific object.
 | 
			
		||||
	// InterpreterOperationInterpretReplica indicates that karmada want to figure out the replica declaration of a specific object.
 | 
			
		||||
	// Only necessary for those resource types that have replica declaration, like Deployment or similar custom resources.
 | 
			
		||||
	ExploreReplica OperationType = "ExploreReplica"
 | 
			
		||||
	InterpreterOperationInterpretReplica InterpreterOperation = "InterpretReplica"
 | 
			
		||||
 | 
			
		||||
	// ExploreStatus indicates that karmada want to figure out how to get the status.
 | 
			
		||||
	// InterpreterOperationReviseReplica indicates that karmada request webhook to modify the replica.
 | 
			
		||||
	InterpreterOperationReviseReplica InterpreterOperation = "ReviseReplica"
 | 
			
		||||
 | 
			
		||||
	// InterpreterOperationInterpretStatus indicates that karmada want to figure out how to get the status.
 | 
			
		||||
	// Only necessary for those resource types that define their status in a special path(not '.status').
 | 
			
		||||
	ExploreStatus OperationType = "ExploreStatus"
 | 
			
		||||
	InterpreterOperationInterpretStatus InterpreterOperation = "InterpretStatus"
 | 
			
		||||
 | 
			
		||||
	// ExplorePacking indicates that karmada want to figure out how to package resource template to Work.
 | 
			
		||||
	ExplorePacking OperationType = "ExplorePacking"
 | 
			
		||||
	// InterpreterOperationPrune indicates that karmada want to figure out how to package resource template to Work.
 | 
			
		||||
	InterpreterOperationPrune InterpreterOperation = "Prune"
 | 
			
		||||
 | 
			
		||||
	// ExploreReplicaRevising indicates that karmada request webhook to modify the replica.
 | 
			
		||||
	ExploreReplicaRevising OperationType = "ExploreReplicaRevising"
 | 
			
		||||
 | 
			
		||||
	// ExploreRetaining indicates that karmada request webhook to retain the desired resource template.
 | 
			
		||||
	// InterpreterOperationRetain indicates that karmada request webhook to retain the desired resource template.
 | 
			
		||||
	// Only necessary for those resources which specification will be updated by their controllers running in member cluster.
 | 
			
		||||
	ExploreRetaining OperationType = "ExploreRetaining"
 | 
			
		||||
	InterpreterOperationRetain InterpreterOperation = "Retain"
 | 
			
		||||
 | 
			
		||||
	// ExploreStatusAggregating indicates that karmada want to figure out how to aggregate status to resource template.
 | 
			
		||||
	// InterpreterOperationAggregateStatus indicates that karmada want to figure out how to aggregate status to resource template.
 | 
			
		||||
	// Only necessary for those resource types that want to aggregate status to resource template.
 | 
			
		||||
	ExploreStatusAggregating OperationType = "ExploreStatusAggregating"
 | 
			
		||||
	InterpreterOperationAggregateStatus InterpreterOperation = "AggregateStatus"
 | 
			
		||||
 | 
			
		||||
	// ExploreHealthy indicates that karmada want to figure out the healthy status of a specific object.
 | 
			
		||||
	// InterpreterOperationInterpretHealthy indicates that karmada want to figure out the healthy status of a specific object.
 | 
			
		||||
	// Only necessary for those resource types that have and want to reflect their healthy status.
 | 
			
		||||
	ExploreHealthy OperationType = "ExploreHealthy"
 | 
			
		||||
	InterpreterOperationInterpretHealthy InterpreterOperation = "InterpretHealthy"
 | 
			
		||||
 | 
			
		||||
	// ExploreDependencies indicates that karmada want to figure out the dependencies of a specific object.
 | 
			
		||||
	// InterpreterOperationInterpretDependency indicates that karmada want to figure out the dependencies of a specific object.
 | 
			
		||||
	// Only necessary for those resource types that have dependencies resources and expect the dependencies be propagated
 | 
			
		||||
	// together, like Deployment depends on ConfigMap/Secret.
 | 
			
		||||
	ExploreDependencies OperationType = "ExploreDependencies"
 | 
			
		||||
	InterpreterOperationInterpretDependency InterpreterOperation = "InterpretDependency"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Rule is a tuple of APIGroups, APIVersion, and Kinds.
 | 
			
		||||
| 
						 | 
				
			
			@ -143,11 +138,11 @@ type Rule struct {
 | 
			
		|||
 | 
			
		||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationList contains a list of ResourceExploringWebhookConfiguration.
 | 
			
		||||
type ResourceExploringWebhookConfigurationList struct {
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationList contains a list of ResourceInterpreterWebhookConfiguration.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationList struct {
 | 
			
		||||
	metav1.TypeMeta `json:",inline"`
 | 
			
		||||
	metav1.ListMeta `json:"metadata,omitempty"`
 | 
			
		||||
 | 
			
		||||
	// Items holds a list of ResourceExploringWebhookConfiguration.
 | 
			
		||||
	Items []ResourceExploringWebhookConfiguration `json:"items"`
 | 
			
		||||
	// Items holds a list of ResourceInterpreterWebhookConfiguration.
 | 
			
		||||
	Items []ResourceInterpreterWebhookConfiguration `json:"items"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ package v1alpha1
 | 
			
		|||
import (
 | 
			
		||||
	workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
 | 
			
		||||
	v1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
 | 
			
		||||
	v1 "k8s.io/api/admissionregistration/v1"
 | 
			
		||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +27,58 @@ func (in *DependentObjectReference) DeepCopy() *DependentObjectReference {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ExploreRequest) DeepCopyInto(out *ExploreRequest) {
 | 
			
		||||
func (in *RequestStatus) DeepCopyInto(out *RequestStatus) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestStatus.
 | 
			
		||||
func (in *RequestStatus) DeepCopy() *RequestStatus {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(RequestStatus)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ResourceInterpreterContext) DeepCopyInto(out *ResourceInterpreterContext) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Request != nil {
 | 
			
		||||
		in, out := &in.Request, &out.Request
 | 
			
		||||
		*out = new(ResourceInterpreterRequest)
 | 
			
		||||
		(*in).DeepCopyInto(*out)
 | 
			
		||||
	}
 | 
			
		||||
	if in.Response != nil {
 | 
			
		||||
		in, out := &in.Response, &out.Response
 | 
			
		||||
		*out = new(ResourceInterpreterResponse)
 | 
			
		||||
		(*in).DeepCopyInto(*out)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterContext.
 | 
			
		||||
func (in *ResourceInterpreterContext) DeepCopy() *ResourceInterpreterContext {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ResourceInterpreterContext)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *ResourceInterpreterContext) DeepCopyObject() runtime.Object {
 | 
			
		||||
	if c := in.DeepCopy(); c != nil {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ResourceInterpreterRequest) DeepCopyInto(out *ResourceInterpreterRequest) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.Kind = in.Kind
 | 
			
		||||
	in.Object.DeepCopyInto(&out.Object)
 | 
			
		||||
| 
						 | 
				
			
			@ -52,18 +102,18 @@ func (in *ExploreRequest) DeepCopyInto(out *ExploreRequest) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExploreRequest.
 | 
			
		||||
func (in *ExploreRequest) DeepCopy() *ExploreRequest {
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterRequest.
 | 
			
		||||
func (in *ResourceInterpreterRequest) DeepCopy() *ResourceInterpreterRequest {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ExploreRequest)
 | 
			
		||||
	out := new(ResourceInterpreterRequest)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ExploreResponse) DeepCopyInto(out *ExploreResponse) {
 | 
			
		||||
func (in *ResourceInterpreterResponse) DeepCopyInto(out *ResourceInterpreterResponse) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	if in.Status != nil {
 | 
			
		||||
		in, out := &in.Status, &out.Status
 | 
			
		||||
| 
						 | 
				
			
			@ -108,69 +158,18 @@ func (in *ExploreResponse) DeepCopyInto(out *ExploreResponse) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExploreResponse.
 | 
			
		||||
func (in *ExploreResponse) DeepCopy() *ExploreResponse {
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterResponse.
 | 
			
		||||
func (in *ResourceInterpreterResponse) DeepCopy() *ResourceInterpreterResponse {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ExploreResponse)
 | 
			
		||||
	out := new(ResourceInterpreterResponse)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ExploreReview) DeepCopyInto(out *ExploreReview) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	if in.Request != nil {
 | 
			
		||||
		in, out := &in.Request, &out.Request
 | 
			
		||||
		*out = new(ExploreRequest)
 | 
			
		||||
		(*in).DeepCopyInto(*out)
 | 
			
		||||
	}
 | 
			
		||||
	if in.Response != nil {
 | 
			
		||||
		in, out := &in.Response, &out.Response
 | 
			
		||||
		*out = new(ExploreResponse)
 | 
			
		||||
		(*in).DeepCopyInto(*out)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExploreReview.
 | 
			
		||||
func (in *ExploreReview) DeepCopy() *ExploreReview {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ExploreReview)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *ExploreReview) DeepCopyObject() runtime.Object {
 | 
			
		||||
	if c := in.DeepCopy(); c != nil {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *RequestStatus) DeepCopyInto(out *RequestStatus) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestStatus.
 | 
			
		||||
func (in *RequestStatus) DeepCopy() *RequestStatus {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(RequestStatus)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ResourceExploringWebhook) DeepCopyInto(out *ResourceExploringWebhook) {
 | 
			
		||||
func (in *ResourceInterpreterWebhook) DeepCopyInto(out *ResourceInterpreterWebhook) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	in.ClientConfig.DeepCopyInto(&out.ClientConfig)
 | 
			
		||||
	if in.Rules != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -180,42 +179,37 @@ func (in *ResourceExploringWebhook) DeepCopyInto(out *ResourceExploringWebhook)
 | 
			
		|||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if in.FailurePolicy != nil {
 | 
			
		||||
		in, out := &in.FailurePolicy, &out.FailurePolicy
 | 
			
		||||
		*out = new(v1.FailurePolicyType)
 | 
			
		||||
		**out = **in
 | 
			
		||||
	}
 | 
			
		||||
	if in.TimeoutSeconds != nil {
 | 
			
		||||
		in, out := &in.TimeoutSeconds, &out.TimeoutSeconds
 | 
			
		||||
		*out = new(int32)
 | 
			
		||||
		**out = **in
 | 
			
		||||
	}
 | 
			
		||||
	if in.ExploreReviewVersions != nil {
 | 
			
		||||
		in, out := &in.ExploreReviewVersions, &out.ExploreReviewVersions
 | 
			
		||||
	if in.InterpreterContextVersions != nil {
 | 
			
		||||
		in, out := &in.InterpreterContextVersions, &out.InterpreterContextVersions
 | 
			
		||||
		*out = make([]string, len(*in))
 | 
			
		||||
		copy(*out, *in)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceExploringWebhook.
 | 
			
		||||
func (in *ResourceExploringWebhook) DeepCopy() *ResourceExploringWebhook {
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterWebhook.
 | 
			
		||||
func (in *ResourceInterpreterWebhook) DeepCopy() *ResourceInterpreterWebhook {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ResourceExploringWebhook)
 | 
			
		||||
	out := new(ResourceInterpreterWebhook)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ResourceExploringWebhookConfiguration) DeepCopyInto(out *ResourceExploringWebhookConfiguration) {
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfiguration) DeepCopyInto(out *ResourceInterpreterWebhookConfiguration) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
 | 
			
		||||
	if in.Webhooks != nil {
 | 
			
		||||
		in, out := &in.Webhooks, &out.Webhooks
 | 
			
		||||
		*out = make([]ResourceExploringWebhook, len(*in))
 | 
			
		||||
		*out = make([]ResourceInterpreterWebhook, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -223,18 +217,18 @@ func (in *ResourceExploringWebhookConfiguration) DeepCopyInto(out *ResourceExplo
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceExploringWebhookConfiguration.
 | 
			
		||||
func (in *ResourceExploringWebhookConfiguration) DeepCopy() *ResourceExploringWebhookConfiguration {
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterWebhookConfiguration.
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfiguration) DeepCopy() *ResourceInterpreterWebhookConfiguration {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ResourceExploringWebhookConfiguration)
 | 
			
		||||
	out := new(ResourceInterpreterWebhookConfiguration)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *ResourceExploringWebhookConfiguration) DeepCopyObject() runtime.Object {
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfiguration) DeepCopyObject() runtime.Object {
 | 
			
		||||
	if c := in.DeepCopy(); c != nil {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -242,13 +236,13 @@ func (in *ResourceExploringWebhookConfiguration) DeepCopyObject() runtime.Object
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *ResourceExploringWebhookConfigurationList) DeepCopyInto(out *ResourceExploringWebhookConfigurationList) {
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfigurationList) DeepCopyInto(out *ResourceInterpreterWebhookConfigurationList) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	out.TypeMeta = in.TypeMeta
 | 
			
		||||
	in.ListMeta.DeepCopyInto(&out.ListMeta)
 | 
			
		||||
	if in.Items != nil {
 | 
			
		||||
		in, out := &in.Items, &out.Items
 | 
			
		||||
		*out = make([]ResourceExploringWebhookConfiguration, len(*in))
 | 
			
		||||
		*out = make([]ResourceInterpreterWebhookConfiguration, len(*in))
 | 
			
		||||
		for i := range *in {
 | 
			
		||||
			(*in)[i].DeepCopyInto(&(*out)[i])
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -256,18 +250,18 @@ func (in *ResourceExploringWebhookConfigurationList) DeepCopyInto(out *ResourceE
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceExploringWebhookConfigurationList.
 | 
			
		||||
func (in *ResourceExploringWebhookConfigurationList) DeepCopy() *ResourceExploringWebhookConfigurationList {
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInterpreterWebhookConfigurationList.
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfigurationList) DeepCopy() *ResourceInterpreterWebhookConfigurationList {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(ResourceExploringWebhookConfigurationList)
 | 
			
		||||
	out := new(ResourceInterpreterWebhookConfigurationList)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
			
		||||
func (in *ResourceExploringWebhookConfigurationList) DeepCopyObject() runtime.Object {
 | 
			
		||||
func (in *ResourceInterpreterWebhookConfigurationList) DeepCopyObject() runtime.Object {
 | 
			
		||||
	if c := in.DeepCopy(); c != nil {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +304,7 @@ func (in *RuleWithOperations) DeepCopyInto(out *RuleWithOperations) {
 | 
			
		|||
	*out = *in
 | 
			
		||||
	if in.Operations != nil {
 | 
			
		||||
		in, out := &in.Operations, &out.Operations
 | 
			
		||||
		*out = make([]OperationType, len(*in))
 | 
			
		||||
		*out = make([]InterpreterOperation, len(*in))
 | 
			
		||||
		copy(*out, *in)
 | 
			
		||||
	}
 | 
			
		||||
	in.Rule.DeepCopyInto(&out.Rule)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,9 +42,9 @@ func init() {
 | 
			
		|||
// Adds the list of known types to Scheme.
 | 
			
		||||
func addKnownTypes(scheme *runtime.Scheme) error {
 | 
			
		||||
	scheme.AddKnownTypes(SchemeGroupVersion,
 | 
			
		||||
		&ExploreReview{},
 | 
			
		||||
		&ResourceExploringWebhookConfiguration{},
 | 
			
		||||
		&ResourceExploringWebhookConfigurationList{},
 | 
			
		||||
		&ResourceInterpreterContext{},
 | 
			
		||||
		&ResourceInterpreterWebhookConfiguration{},
 | 
			
		||||
		&ResourceInterpreterWebhookConfigurationList{},
 | 
			
		||||
	)
 | 
			
		||||
	// AddToGroupVersion allows the serialization of client types like ListOptions.
 | 
			
		||||
	v1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,65 +0,0 @@
 | 
			
		|||
package defaultexplorer
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultExplorer contains all default operation explorer factory
 | 
			
		||||
// for exploring common resource.
 | 
			
		||||
type DefaultExplorer struct {
 | 
			
		||||
	replicaHandlers   map[schema.GroupVersionKind]replicaExplorer
 | 
			
		||||
	retentionHandlers map[schema.GroupVersionKind]retentionExplorer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultExplorer return a new DefaultExplorer.
 | 
			
		||||
func NewDefaultExplorer() *DefaultExplorer {
 | 
			
		||||
	return &DefaultExplorer{
 | 
			
		||||
		replicaHandlers:   getAllDefaultReplicaExplorer(),
 | 
			
		||||
		retentionHandlers: getAllDefaultRetentionExplorer(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookEnabled tells if any hook exist for specific resource type and operation type.
 | 
			
		||||
func (e *DefaultExplorer) HookEnabled(kind schema.GroupVersionKind, operationType configv1alpha1.OperationType) bool {
 | 
			
		||||
	switch operationType {
 | 
			
		||||
	case configv1alpha1.ExploreReplica:
 | 
			
		||||
		if _, exist := e.replicaHandlers[kind]; exist {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	case configv1alpha1.ExploreRetaining:
 | 
			
		||||
		if _, exist := e.retentionHandlers[kind]; exist {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO(RainbowMango): more cases should be added here
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	klog.V(4).Infof("Default explorer is not enabled for kind %q with operation %q.", kind, operationType)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | 
			
		||||
func (e *DefaultExplorer) GetReplicas(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
	handler, exist := e.replicaHandlers[object.GroupVersionKind()]
 | 
			
		||||
	if !exist {
 | 
			
		||||
		return 0, &workv1alpha2.ReplicaRequirements{}, fmt.Errorf("defalut explorer for operation %s not found", configv1alpha1.ExploreReplica)
 | 
			
		||||
	}
 | 
			
		||||
	return handler(object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
 | 
			
		||||
func (e *DefaultExplorer) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
 | 
			
		||||
	handler, exist := e.retentionHandlers[desired.GroupVersionKind()]
 | 
			
		||||
	if !exist {
 | 
			
		||||
		return nil, fmt.Errorf("default retain explorer for %q not found", desired.GroupVersionKind())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return handler(desired, observed)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ import (
 | 
			
		|||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
 | 
			
		||||
	workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/helper"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/informermanager"
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +50,8 @@ type ResourceDetector struct {
 | 
			
		|||
	Processor                    util.AsyncWorker
 | 
			
		||||
	SkippedResourceConfig        *util.SkippedResourceConfig
 | 
			
		||||
	SkippedPropagatingNamespaces map[string]struct{}
 | 
			
		||||
	// ResourceExplorer knows the details of resource structure.
 | 
			
		||||
	ResourceExplorer crdexplorer.CustomResourceExplorer
 | 
			
		||||
	// ResourceInterpreter knows the details of resource structure.
 | 
			
		||||
	ResourceInterpreter resourceinterpreter.ResourceInterpreter
 | 
			
		||||
 | 
			
		||||
	// policyReconcileWorker maintains a rate limited queue which used to store PropagationPolicy's key and
 | 
			
		||||
	// a reconcile function to consume the items in queue.
 | 
			
		||||
| 
						 | 
				
			
			@ -642,8 +642,8 @@ func (d *ResourceDetector) BuildResourceBinding(object *unstructured.Unstructure
 | 
			
		|||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if d.ResourceExplorer.HookEnabled(object, configv1alpha1.ExploreReplica) {
 | 
			
		||||
		replicas, replicaRequirements, err := d.ResourceExplorer.GetReplicas(object)
 | 
			
		||||
	if d.ResourceInterpreter.HookEnabled(object, configv1alpha1.InterpreterOperationInterpretReplica) {
 | 
			
		||||
		replicas, replicaRequirements, err := d.ResourceInterpreter.GetReplicas(object)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			klog.Errorf("Failed to customize replicas for %s(%s), %v", object.GroupVersionKind(), object.GetName(), err)
 | 
			
		||||
			return nil, err
 | 
			
		||||
| 
						 | 
				
			
			@ -677,8 +677,8 @@ func (d *ResourceDetector) BuildClusterResourceBinding(object *unstructured.Unst
 | 
			
		|||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if d.ResourceExplorer.HookEnabled(object, configv1alpha1.ExploreReplica) {
 | 
			
		||||
		replicas, replicaRequirements, err := d.ResourceExplorer.GetReplicas(object)
 | 
			
		||||
	if d.ResourceInterpreter.HookEnabled(object, configv1alpha1.InterpreterOperationInterpretReplica) {
 | 
			
		||||
		replicas, replicaRequirements, err := d.ResourceInterpreter.GetReplicas(object)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			klog.Errorf("Failed to customize replicas for %s(%s), %v", object.GroupVersionKind(), object.GetName(), err)
 | 
			
		||||
			return nil, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ import (
 | 
			
		|||
 | 
			
		||||
type ConfigV1alpha1Interface interface {
 | 
			
		||||
	RESTClient() rest.Interface
 | 
			
		||||
	ResourceExploringWebhookConfigurationsGetter
 | 
			
		||||
	ResourceInterpreterWebhookConfigurationsGetter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfigV1alpha1Client is used to interact with features provided by the config.karmada.io group.
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +18,8 @@ type ConfigV1alpha1Client struct {
 | 
			
		|||
	restClient rest.Interface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ConfigV1alpha1Client) ResourceExploringWebhookConfigurations() ResourceExploringWebhookConfigurationInterface {
 | 
			
		||||
	return newResourceExploringWebhookConfigurations(c)
 | 
			
		||||
func (c *ConfigV1alpha1Client) ResourceInterpreterWebhookConfigurations() ResourceInterpreterWebhookConfigurationInterface {
 | 
			
		||||
	return newResourceInterpreterWebhookConfigurations(c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewForConfig creates a new ConfigV1alpha1Client for the given config.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,8 @@ type FakeConfigV1alpha1 struct {
 | 
			
		|||
	*testing.Fake
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *FakeConfigV1alpha1) ResourceExploringWebhookConfigurations() v1alpha1.ResourceExploringWebhookConfigurationInterface {
 | 
			
		||||
	return &FakeResourceExploringWebhookConfigurations{c}
 | 
			
		||||
func (c *FakeConfigV1alpha1) ResourceInterpreterWebhookConfigurations() v1alpha1.ResourceInterpreterWebhookConfigurationInterface {
 | 
			
		||||
	return &FakeResourceInterpreterWebhookConfigurations{c}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RESTClient returns a RESTClient that is used to communicate
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,106 +0,0 @@
 | 
			
		|||
// Code generated by client-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package fake
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	labels "k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	schema "k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	types "k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	testing "k8s.io/client-go/testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FakeResourceExploringWebhookConfigurations implements ResourceExploringWebhookConfigurationInterface
 | 
			
		||||
type FakeResourceExploringWebhookConfigurations struct {
 | 
			
		||||
	Fake *FakeConfigV1alpha1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var resourceexploringwebhookconfigurationsResource = schema.GroupVersionResource{Group: "config.karmada.io", Version: "v1alpha1", Resource: "resourceexploringwebhookconfigurations"}
 | 
			
		||||
 | 
			
		||||
var resourceexploringwebhookconfigurationsKind = schema.GroupVersionKind{Group: "config.karmada.io", Version: "v1alpha1", Kind: "ResourceExploringWebhookConfiguration"}
 | 
			
		||||
 | 
			
		||||
// Get takes name of the resourceExploringWebhookConfiguration, and returns the corresponding resourceExploringWebhookConfiguration object, and an error if there is any.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootGetAction(resourceexploringwebhookconfigurationsResource, name), &v1alpha1.ResourceExploringWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceExploringWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List takes label and field selectors, and returns the list of ResourceExploringWebhookConfigurations that match those selectors.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceExploringWebhookConfigurationList, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootListAction(resourceexploringwebhookconfigurationsResource, resourceexploringwebhookconfigurationsKind, opts), &v1alpha1.ResourceExploringWebhookConfigurationList{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	label, _, _ := testing.ExtractFromListOptions(opts)
 | 
			
		||||
	if label == nil {
 | 
			
		||||
		label = labels.Everything()
 | 
			
		||||
	}
 | 
			
		||||
	list := &v1alpha1.ResourceExploringWebhookConfigurationList{ListMeta: obj.(*v1alpha1.ResourceExploringWebhookConfigurationList).ListMeta}
 | 
			
		||||
	for _, item := range obj.(*v1alpha1.ResourceExploringWebhookConfigurationList).Items {
 | 
			
		||||
		if label.Matches(labels.Set(item.Labels)) {
 | 
			
		||||
			list.Items = append(list.Items, item)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return list, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Watch returns a watch.Interface that watches the requested resourceExploringWebhookConfigurations.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
	return c.Fake.
 | 
			
		||||
		InvokesWatch(testing.NewRootWatchAction(resourceexploringwebhookconfigurationsResource, opts))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create takes the representation of a resourceExploringWebhookConfiguration and creates it.  Returns the server's representation of the resourceExploringWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Create(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.CreateOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootCreateAction(resourceexploringwebhookconfigurationsResource, resourceExploringWebhookConfiguration), &v1alpha1.ResourceExploringWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceExploringWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update takes the representation of a resourceExploringWebhookConfiguration and updates it. Returns the server's representation of the resourceExploringWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Update(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.UpdateOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootUpdateAction(resourceexploringwebhookconfigurationsResource, resourceExploringWebhookConfiguration), &v1alpha1.ResourceExploringWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceExploringWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete takes name of the resourceExploringWebhookConfiguration and deletes it. Returns an error if one occurs.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
 | 
			
		||||
	_, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootDeleteAction(resourceexploringwebhookconfigurationsResource, name), &v1alpha1.ResourceExploringWebhookConfiguration{})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollection deletes a collection of objects.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
 | 
			
		||||
	action := testing.NewRootDeleteCollectionAction(resourceexploringwebhookconfigurationsResource, listOpts)
 | 
			
		||||
 | 
			
		||||
	_, err := c.Fake.Invokes(action, &v1alpha1.ResourceExploringWebhookConfigurationList{})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Patch applies the patch and returns the patched resourceExploringWebhookConfiguration.
 | 
			
		||||
func (c *FakeResourceExploringWebhookConfigurations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootPatchSubresourceAction(resourceexploringwebhookconfigurationsResource, name, pt, data, subresources...), &v1alpha1.ResourceExploringWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceExploringWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
// Code generated by client-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package fake
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	labels "k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	schema "k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	types "k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	testing "k8s.io/client-go/testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FakeResourceInterpreterWebhookConfigurations implements ResourceInterpreterWebhookConfigurationInterface
 | 
			
		||||
type FakeResourceInterpreterWebhookConfigurations struct {
 | 
			
		||||
	Fake *FakeConfigV1alpha1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var resourceinterpreterwebhookconfigurationsResource = schema.GroupVersionResource{Group: "config.karmada.io", Version: "v1alpha1", Resource: "resourceinterpreterwebhookconfigurations"}
 | 
			
		||||
 | 
			
		||||
var resourceinterpreterwebhookconfigurationsKind = schema.GroupVersionKind{Group: "config.karmada.io", Version: "v1alpha1", Kind: "ResourceInterpreterWebhookConfiguration"}
 | 
			
		||||
 | 
			
		||||
// Get takes name of the resourceInterpreterWebhookConfiguration, and returns the corresponding resourceInterpreterWebhookConfiguration object, and an error if there is any.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootGetAction(resourceinterpreterwebhookconfigurationsResource, name), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceInterpreterWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List takes label and field selectors, and returns the list of ResourceInterpreterWebhookConfigurations that match those selectors.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceInterpreterWebhookConfigurationList, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootListAction(resourceinterpreterwebhookconfigurationsResource, resourceinterpreterwebhookconfigurationsKind, opts), &v1alpha1.ResourceInterpreterWebhookConfigurationList{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	label, _, _ := testing.ExtractFromListOptions(opts)
 | 
			
		||||
	if label == nil {
 | 
			
		||||
		label = labels.Everything()
 | 
			
		||||
	}
 | 
			
		||||
	list := &v1alpha1.ResourceInterpreterWebhookConfigurationList{ListMeta: obj.(*v1alpha1.ResourceInterpreterWebhookConfigurationList).ListMeta}
 | 
			
		||||
	for _, item := range obj.(*v1alpha1.ResourceInterpreterWebhookConfigurationList).Items {
 | 
			
		||||
		if label.Matches(labels.Set(item.Labels)) {
 | 
			
		||||
			list.Items = append(list.Items, item)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return list, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Watch returns a watch.Interface that watches the requested resourceInterpreterWebhookConfigurations.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
	return c.Fake.
 | 
			
		||||
		InvokesWatch(testing.NewRootWatchAction(resourceinterpreterwebhookconfigurationsResource, opts))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create takes the representation of a resourceInterpreterWebhookConfiguration and creates it.  Returns the server's representation of the resourceInterpreterWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Create(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.CreateOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootCreateAction(resourceinterpreterwebhookconfigurationsResource, resourceInterpreterWebhookConfiguration), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceInterpreterWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update takes the representation of a resourceInterpreterWebhookConfiguration and updates it. Returns the server's representation of the resourceInterpreterWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Update(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.UpdateOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootUpdateAction(resourceinterpreterwebhookconfigurationsResource, resourceInterpreterWebhookConfiguration), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceInterpreterWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete takes name of the resourceInterpreterWebhookConfiguration and deletes it. Returns an error if one occurs.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
 | 
			
		||||
	_, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootDeleteAction(resourceinterpreterwebhookconfigurationsResource, name), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollection deletes a collection of objects.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
 | 
			
		||||
	action := testing.NewRootDeleteCollectionAction(resourceinterpreterwebhookconfigurationsResource, listOpts)
 | 
			
		||||
 | 
			
		||||
	_, err := c.Fake.Invokes(action, &v1alpha1.ResourceInterpreterWebhookConfigurationList{})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Patch applies the patch and returns the patched resourceInterpreterWebhookConfiguration.
 | 
			
		||||
func (c *FakeResourceInterpreterWebhookConfigurations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	obj, err := c.Fake.
 | 
			
		||||
		Invokes(testing.NewRootPatchSubresourceAction(resourceinterpreterwebhookconfigurationsResource, name, pt, data, subresources...), &v1alpha1.ResourceInterpreterWebhookConfiguration{})
 | 
			
		||||
	if obj == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceInterpreterWebhookConfiguration), err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,4 +2,4 @@
 | 
			
		|||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
type ResourceExploringWebhookConfigurationExpansion interface{}
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationExpansion interface{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,152 +0,0 @@
 | 
			
		|||
// Code generated by client-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	scheme "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	types "k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	rest "k8s.io/client-go/rest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationsGetter has a method to return a ResourceExploringWebhookConfigurationInterface.
 | 
			
		||||
// A group's client should implement this interface.
 | 
			
		||||
type ResourceExploringWebhookConfigurationsGetter interface {
 | 
			
		||||
	ResourceExploringWebhookConfigurations() ResourceExploringWebhookConfigurationInterface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationInterface has methods to work with ResourceExploringWebhookConfiguration resources.
 | 
			
		||||
type ResourceExploringWebhookConfigurationInterface interface {
 | 
			
		||||
	Create(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.CreateOptions) (*v1alpha1.ResourceExploringWebhookConfiguration, error)
 | 
			
		||||
	Update(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.UpdateOptions) (*v1alpha1.ResourceExploringWebhookConfiguration, error)
 | 
			
		||||
	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
 | 
			
		||||
	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
 | 
			
		||||
	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ResourceExploringWebhookConfiguration, error)
 | 
			
		||||
	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ResourceExploringWebhookConfigurationList, error)
 | 
			
		||||
	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
 | 
			
		||||
	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error)
 | 
			
		||||
	ResourceExploringWebhookConfigurationExpansion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resourceExploringWebhookConfigurations implements ResourceExploringWebhookConfigurationInterface
 | 
			
		||||
type resourceExploringWebhookConfigurations struct {
 | 
			
		||||
	client rest.Interface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newResourceExploringWebhookConfigurations returns a ResourceExploringWebhookConfigurations
 | 
			
		||||
func newResourceExploringWebhookConfigurations(c *ConfigV1alpha1Client) *resourceExploringWebhookConfigurations {
 | 
			
		||||
	return &resourceExploringWebhookConfigurations{
 | 
			
		||||
		client: c.RESTClient(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get takes name of the resourceExploringWebhookConfiguration, and returns the corresponding resourceExploringWebhookConfiguration object, and an error if there is any.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Get().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		VersionedParams(&options, scheme.ParameterCodec).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List takes label and field selectors, and returns the list of ResourceExploringWebhookConfigurations that match those selectors.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceExploringWebhookConfigurationList, err error) {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if opts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	result = &v1alpha1.ResourceExploringWebhookConfigurationList{}
 | 
			
		||||
	err = c.client.Get().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Watch returns a watch.Interface that watches the requested resourceExploringWebhookConfigurations.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if opts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	opts.Watch = true
 | 
			
		||||
	return c.client.Get().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Watch(ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create takes the representation of a resourceExploringWebhookConfiguration and creates it.  Returns the server's representation of the resourceExploringWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Create(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.CreateOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Post().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(resourceExploringWebhookConfiguration).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update takes the representation of a resourceExploringWebhookConfiguration and updates it. Returns the server's representation of the resourceExploringWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Update(ctx context.Context, resourceExploringWebhookConfiguration *v1alpha1.ResourceExploringWebhookConfiguration, opts v1.UpdateOptions) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Put().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		Name(resourceExploringWebhookConfiguration.Name).
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(resourceExploringWebhookConfiguration).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete takes name of the resourceExploringWebhookConfiguration and deletes it. Returns an error if one occurs.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
 | 
			
		||||
	return c.client.Delete().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		Body(&opts).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollection deletes a collection of objects.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if listOpts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	return c.client.Delete().
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&listOpts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Body(&opts).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Patch applies the patch and returns the patched resourceExploringWebhookConfiguration.
 | 
			
		||||
func (c *resourceExploringWebhookConfigurations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Patch(pt).
 | 
			
		||||
		Resource("resourceexploringwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		SubResource(subresources...).
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(data).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
// Code generated by client-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	scheme "github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	types "k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	rest "k8s.io/client-go/rest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationsGetter has a method to return a ResourceInterpreterWebhookConfigurationInterface.
 | 
			
		||||
// A group's client should implement this interface.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationsGetter interface {
 | 
			
		||||
	ResourceInterpreterWebhookConfigurations() ResourceInterpreterWebhookConfigurationInterface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationInterface has methods to work with ResourceInterpreterWebhookConfiguration resources.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationInterface interface {
 | 
			
		||||
	Create(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.CreateOptions) (*v1alpha1.ResourceInterpreterWebhookConfiguration, error)
 | 
			
		||||
	Update(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.UpdateOptions) (*v1alpha1.ResourceInterpreterWebhookConfiguration, error)
 | 
			
		||||
	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
 | 
			
		||||
	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
 | 
			
		||||
	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ResourceInterpreterWebhookConfiguration, error)
 | 
			
		||||
	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ResourceInterpreterWebhookConfigurationList, error)
 | 
			
		||||
	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
 | 
			
		||||
	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error)
 | 
			
		||||
	ResourceInterpreterWebhookConfigurationExpansion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resourceInterpreterWebhookConfigurations implements ResourceInterpreterWebhookConfigurationInterface
 | 
			
		||||
type resourceInterpreterWebhookConfigurations struct {
 | 
			
		||||
	client rest.Interface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newResourceInterpreterWebhookConfigurations returns a ResourceInterpreterWebhookConfigurations
 | 
			
		||||
func newResourceInterpreterWebhookConfigurations(c *ConfigV1alpha1Client) *resourceInterpreterWebhookConfigurations {
 | 
			
		||||
	return &resourceInterpreterWebhookConfigurations{
 | 
			
		||||
		client: c.RESTClient(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get takes name of the resourceInterpreterWebhookConfiguration, and returns the corresponding resourceInterpreterWebhookConfiguration object, and an error if there is any.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Get().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		VersionedParams(&options, scheme.ParameterCodec).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List takes label and field selectors, and returns the list of ResourceInterpreterWebhookConfigurations that match those selectors.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceInterpreterWebhookConfigurationList, err error) {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if opts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	result = &v1alpha1.ResourceInterpreterWebhookConfigurationList{}
 | 
			
		||||
	err = c.client.Get().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Watch returns a watch.Interface that watches the requested resourceInterpreterWebhookConfigurations.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if opts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	opts.Watch = true
 | 
			
		||||
	return c.client.Get().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Watch(ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create takes the representation of a resourceInterpreterWebhookConfiguration and creates it.  Returns the server's representation of the resourceInterpreterWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Create(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.CreateOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Post().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(resourceInterpreterWebhookConfiguration).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update takes the representation of a resourceInterpreterWebhookConfiguration and updates it. Returns the server's representation of the resourceInterpreterWebhookConfiguration, and an error, if there is any.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Update(ctx context.Context, resourceInterpreterWebhookConfiguration *v1alpha1.ResourceInterpreterWebhookConfiguration, opts v1.UpdateOptions) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Put().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		Name(resourceInterpreterWebhookConfiguration.Name).
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(resourceInterpreterWebhookConfiguration).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete takes name of the resourceInterpreterWebhookConfiguration and deletes it. Returns an error if one occurs.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
 | 
			
		||||
	return c.client.Delete().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		Body(&opts).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollection deletes a collection of objects.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
 | 
			
		||||
	var timeout time.Duration
 | 
			
		||||
	if listOpts.TimeoutSeconds != nil {
 | 
			
		||||
		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	return c.client.Delete().
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		VersionedParams(&listOpts, scheme.ParameterCodec).
 | 
			
		||||
		Timeout(timeout).
 | 
			
		||||
		Body(&opts).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Patch applies the patch and returns the patched resourceInterpreterWebhookConfiguration.
 | 
			
		||||
func (c *resourceInterpreterWebhookConfigurations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	result = &v1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
	err = c.client.Patch(pt).
 | 
			
		||||
		Resource("resourceinterpreterwebhookconfigurations").
 | 
			
		||||
		Name(name).
 | 
			
		||||
		SubResource(subresources...).
 | 
			
		||||
		VersionedParams(&opts, scheme.ParameterCodec).
 | 
			
		||||
		Body(data).
 | 
			
		||||
		Do(ctx).
 | 
			
		||||
		Into(result)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,8 +8,8 @@ import (
 | 
			
		|||
 | 
			
		||||
// Interface provides access to all the informers in this group version.
 | 
			
		||||
type Interface interface {
 | 
			
		||||
	// ResourceExploringWebhookConfigurations returns a ResourceExploringWebhookConfigurationInformer.
 | 
			
		||||
	ResourceExploringWebhookConfigurations() ResourceExploringWebhookConfigurationInformer
 | 
			
		||||
	// ResourceInterpreterWebhookConfigurations returns a ResourceInterpreterWebhookConfigurationInformer.
 | 
			
		||||
	ResourceInterpreterWebhookConfigurations() ResourceInterpreterWebhookConfigurationInformer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type version struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
 | 
			
		|||
	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurations returns a ResourceExploringWebhookConfigurationInformer.
 | 
			
		||||
func (v *version) ResourceExploringWebhookConfigurations() ResourceExploringWebhookConfigurationInformer {
 | 
			
		||||
	return &resourceExploringWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
 | 
			
		||||
// ResourceInterpreterWebhookConfigurations returns a ResourceInterpreterWebhookConfigurationInformer.
 | 
			
		||||
func (v *version) ResourceInterpreterWebhookConfigurations() ResourceInterpreterWebhookConfigurationInformer {
 | 
			
		||||
	return &resourceInterpreterWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,73 +0,0 @@
 | 
			
		|||
// Code generated by informer-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	time "time"
 | 
			
		||||
 | 
			
		||||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	versioned "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
 | 
			
		||||
	internalinterfaces "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/internalinterfaces"
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/generated/listers/config/v1alpha1"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	cache "k8s.io/client-go/tools/cache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationInformer provides access to a shared informer and lister for
 | 
			
		||||
// ResourceExploringWebhookConfigurations.
 | 
			
		||||
type ResourceExploringWebhookConfigurationInformer interface {
 | 
			
		||||
	Informer() cache.SharedIndexInformer
 | 
			
		||||
	Lister() v1alpha1.ResourceExploringWebhookConfigurationLister
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type resourceExploringWebhookConfigurationInformer struct {
 | 
			
		||||
	factory          internalinterfaces.SharedInformerFactory
 | 
			
		||||
	tweakListOptions internalinterfaces.TweakListOptionsFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewResourceExploringWebhookConfigurationInformer constructs a new informer for ResourceExploringWebhookConfiguration type.
 | 
			
		||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
 | 
			
		||||
// one. This reduces memory footprint and number of connections to the server.
 | 
			
		||||
func NewResourceExploringWebhookConfigurationInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
 | 
			
		||||
	return NewFilteredResourceExploringWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewFilteredResourceExploringWebhookConfigurationInformer constructs a new informer for ResourceExploringWebhookConfiguration type.
 | 
			
		||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
 | 
			
		||||
// one. This reduces memory footprint and number of connections to the server.
 | 
			
		||||
func NewFilteredResourceExploringWebhookConfigurationInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
 | 
			
		||||
	return cache.NewSharedIndexInformer(
 | 
			
		||||
		&cache.ListWatch{
 | 
			
		||||
			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
 | 
			
		||||
				if tweakListOptions != nil {
 | 
			
		||||
					tweakListOptions(&options)
 | 
			
		||||
				}
 | 
			
		||||
				return client.ConfigV1alpha1().ResourceExploringWebhookConfigurations().List(context.TODO(), options)
 | 
			
		||||
			},
 | 
			
		||||
			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
				if tweakListOptions != nil {
 | 
			
		||||
					tweakListOptions(&options)
 | 
			
		||||
				}
 | 
			
		||||
				return client.ConfigV1alpha1().ResourceExploringWebhookConfigurations().Watch(context.TODO(), options)
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		&configv1alpha1.ResourceExploringWebhookConfiguration{},
 | 
			
		||||
		resyncPeriod,
 | 
			
		||||
		indexers,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceExploringWebhookConfigurationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
 | 
			
		||||
	return NewFilteredResourceExploringWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceExploringWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
 | 
			
		||||
	return f.factory.InformerFor(&configv1alpha1.ResourceExploringWebhookConfiguration{}, f.defaultInformer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceExploringWebhookConfigurationInformer) Lister() v1alpha1.ResourceExploringWebhookConfigurationLister {
 | 
			
		||||
	return v1alpha1.NewResourceExploringWebhookConfigurationLister(f.Informer().GetIndexer())
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
// Code generated by informer-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	time "time"
 | 
			
		||||
 | 
			
		||||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	versioned "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
 | 
			
		||||
	internalinterfaces "github.com/karmada-io/karmada/pkg/generated/informers/externalversions/internalinterfaces"
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/generated/listers/config/v1alpha1"
 | 
			
		||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	runtime "k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	watch "k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	cache "k8s.io/client-go/tools/cache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationInformer provides access to a shared informer and lister for
 | 
			
		||||
// ResourceInterpreterWebhookConfigurations.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationInformer interface {
 | 
			
		||||
	Informer() cache.SharedIndexInformer
 | 
			
		||||
	Lister() v1alpha1.ResourceInterpreterWebhookConfigurationLister
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type resourceInterpreterWebhookConfigurationInformer struct {
 | 
			
		||||
	factory          internalinterfaces.SharedInformerFactory
 | 
			
		||||
	tweakListOptions internalinterfaces.TweakListOptionsFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewResourceInterpreterWebhookConfigurationInformer constructs a new informer for ResourceInterpreterWebhookConfiguration type.
 | 
			
		||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
 | 
			
		||||
// one. This reduces memory footprint and number of connections to the server.
 | 
			
		||||
func NewResourceInterpreterWebhookConfigurationInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
 | 
			
		||||
	return NewFilteredResourceInterpreterWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewFilteredResourceInterpreterWebhookConfigurationInformer constructs a new informer for ResourceInterpreterWebhookConfiguration type.
 | 
			
		||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
 | 
			
		||||
// one. This reduces memory footprint and number of connections to the server.
 | 
			
		||||
func NewFilteredResourceInterpreterWebhookConfigurationInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
 | 
			
		||||
	return cache.NewSharedIndexInformer(
 | 
			
		||||
		&cache.ListWatch{
 | 
			
		||||
			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
 | 
			
		||||
				if tweakListOptions != nil {
 | 
			
		||||
					tweakListOptions(&options)
 | 
			
		||||
				}
 | 
			
		||||
				return client.ConfigV1alpha1().ResourceInterpreterWebhookConfigurations().List(context.TODO(), options)
 | 
			
		||||
			},
 | 
			
		||||
			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
 | 
			
		||||
				if tweakListOptions != nil {
 | 
			
		||||
					tweakListOptions(&options)
 | 
			
		||||
				}
 | 
			
		||||
				return client.ConfigV1alpha1().ResourceInterpreterWebhookConfigurations().Watch(context.TODO(), options)
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		&configv1alpha1.ResourceInterpreterWebhookConfiguration{},
 | 
			
		||||
		resyncPeriod,
 | 
			
		||||
		indexers,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceInterpreterWebhookConfigurationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
 | 
			
		||||
	return NewFilteredResourceInterpreterWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceInterpreterWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
 | 
			
		||||
	return f.factory.InformerFor(&configv1alpha1.ResourceInterpreterWebhookConfiguration{}, f.defaultInformer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *resourceInterpreterWebhookConfigurationInformer) Lister() v1alpha1.ResourceInterpreterWebhookConfigurationLister {
 | 
			
		||||
	return v1alpha1.NewResourceInterpreterWebhookConfigurationLister(f.Informer().GetIndexer())
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
 | 
			
		|||
		return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().Clusters().Informer()}, nil
 | 
			
		||||
 | 
			
		||||
		// Group=config.karmada.io, Version=v1alpha1
 | 
			
		||||
	case configv1alpha1.SchemeGroupVersion.WithResource("resourceexploringwebhookconfigurations"):
 | 
			
		||||
		return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().ResourceExploringWebhookConfigurations().Informer()}, nil
 | 
			
		||||
	case configv1alpha1.SchemeGroupVersion.WithResource("resourceinterpreterwebhookconfigurations"):
 | 
			
		||||
		return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().ResourceInterpreterWebhookConfigurations().Informer()}, nil
 | 
			
		||||
 | 
			
		||||
		// Group=policy.karmada.io, Version=v1alpha1
 | 
			
		||||
	case policyv1alpha1.SchemeGroupVersion.WithResource("clusteroverridepolicies"):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,6 @@
 | 
			
		|||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationListerExpansion allows custom methods to be added to
 | 
			
		||||
// ResourceExploringWebhookConfigurationLister.
 | 
			
		||||
type ResourceExploringWebhookConfigurationListerExpansion interface{}
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationListerExpansion allows custom methods to be added to
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationLister.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationListerExpansion interface{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,52 +0,0 @@
 | 
			
		|||
// Code generated by lister-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/errors"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	"k8s.io/client-go/tools/cache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceExploringWebhookConfigurationLister helps list ResourceExploringWebhookConfigurations.
 | 
			
		||||
// All objects returned here must be treated as read-only.
 | 
			
		||||
type ResourceExploringWebhookConfigurationLister interface {
 | 
			
		||||
	// List lists all ResourceExploringWebhookConfigurations in the indexer.
 | 
			
		||||
	// Objects returned here must be treated as read-only.
 | 
			
		||||
	List(selector labels.Selector) (ret []*v1alpha1.ResourceExploringWebhookConfiguration, err error)
 | 
			
		||||
	// Get retrieves the ResourceExploringWebhookConfiguration from the index for a given name.
 | 
			
		||||
	// Objects returned here must be treated as read-only.
 | 
			
		||||
	Get(name string) (*v1alpha1.ResourceExploringWebhookConfiguration, error)
 | 
			
		||||
	ResourceExploringWebhookConfigurationListerExpansion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resourceExploringWebhookConfigurationLister implements the ResourceExploringWebhookConfigurationLister interface.
 | 
			
		||||
type resourceExploringWebhookConfigurationLister struct {
 | 
			
		||||
	indexer cache.Indexer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewResourceExploringWebhookConfigurationLister returns a new ResourceExploringWebhookConfigurationLister.
 | 
			
		||||
func NewResourceExploringWebhookConfigurationLister(indexer cache.Indexer) ResourceExploringWebhookConfigurationLister {
 | 
			
		||||
	return &resourceExploringWebhookConfigurationLister{indexer: indexer}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List lists all ResourceExploringWebhookConfigurations in the indexer.
 | 
			
		||||
func (s *resourceExploringWebhookConfigurationLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceExploringWebhookConfiguration, err error) {
 | 
			
		||||
	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
 | 
			
		||||
		ret = append(ret, m.(*v1alpha1.ResourceExploringWebhookConfiguration))
 | 
			
		||||
	})
 | 
			
		||||
	return ret, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves the ResourceExploringWebhookConfiguration from the index for a given name.
 | 
			
		||||
func (s *resourceExploringWebhookConfigurationLister) Get(name string) (*v1alpha1.ResourceExploringWebhookConfiguration, error) {
 | 
			
		||||
	obj, exists, err := s.indexer.GetByKey(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if !exists {
 | 
			
		||||
		return nil, errors.NewNotFound(v1alpha1.Resource("resourceexploringwebhookconfiguration"), name)
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceExploringWebhookConfiguration), nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
// Code generated by lister-gen. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package v1alpha1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	v1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/errors"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	"k8s.io/client-go/tools/cache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ResourceInterpreterWebhookConfigurationLister helps list ResourceInterpreterWebhookConfigurations.
 | 
			
		||||
// All objects returned here must be treated as read-only.
 | 
			
		||||
type ResourceInterpreterWebhookConfigurationLister interface {
 | 
			
		||||
	// List lists all ResourceInterpreterWebhookConfigurations in the indexer.
 | 
			
		||||
	// Objects returned here must be treated as read-only.
 | 
			
		||||
	List(selector labels.Selector) (ret []*v1alpha1.ResourceInterpreterWebhookConfiguration, err error)
 | 
			
		||||
	// Get retrieves the ResourceInterpreterWebhookConfiguration from the index for a given name.
 | 
			
		||||
	// Objects returned here must be treated as read-only.
 | 
			
		||||
	Get(name string) (*v1alpha1.ResourceInterpreterWebhookConfiguration, error)
 | 
			
		||||
	ResourceInterpreterWebhookConfigurationListerExpansion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resourceInterpreterWebhookConfigurationLister implements the ResourceInterpreterWebhookConfigurationLister interface.
 | 
			
		||||
type resourceInterpreterWebhookConfigurationLister struct {
 | 
			
		||||
	indexer cache.Indexer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewResourceInterpreterWebhookConfigurationLister returns a new ResourceInterpreterWebhookConfigurationLister.
 | 
			
		||||
func NewResourceInterpreterWebhookConfigurationLister(indexer cache.Indexer) ResourceInterpreterWebhookConfigurationLister {
 | 
			
		||||
	return &resourceInterpreterWebhookConfigurationLister{indexer: indexer}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// List lists all ResourceInterpreterWebhookConfigurations in the indexer.
 | 
			
		||||
func (s *resourceInterpreterWebhookConfigurationLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceInterpreterWebhookConfiguration, err error) {
 | 
			
		||||
	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
 | 
			
		||||
		ret = append(ret, m.(*v1alpha1.ResourceInterpreterWebhookConfiguration))
 | 
			
		||||
	})
 | 
			
		||||
	return ret, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get retrieves the ResourceInterpreterWebhookConfiguration from the index for a given name.
 | 
			
		||||
func (s *resourceInterpreterWebhookConfigurationLister) Get(name string) (*v1alpha1.ResourceInterpreterWebhookConfiguration, error) {
 | 
			
		||||
	obj, exists, err := s.indexer.GetByKey(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if !exists {
 | 
			
		||||
		return nil, errors.NewNotFound(v1alpha1.Resource("resourceinterpreterwebhookconfiguration"), name)
 | 
			
		||||
	}
 | 
			
		||||
	return obj.(*v1alpha1.ResourceInterpreterWebhookConfiguration), nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -22,19 +22,17 @@ type WebhookAccessor interface {
 | 
			
		|||
	GetClientConfig() admissionregistrationv1.WebhookClientConfig
 | 
			
		||||
	// GetRules gets the webhook Rules field.
 | 
			
		||||
	GetRules() []configv1alpha1.RuleWithOperations
 | 
			
		||||
	// GetFailurePolicy gets the webhook FailurePolicy field.
 | 
			
		||||
	GetFailurePolicy() *admissionregistrationv1.FailurePolicyType
 | 
			
		||||
	// GetTimeoutSeconds gets the webhook TimeoutSeconds field.
 | 
			
		||||
	GetTimeoutSeconds() *int32
 | 
			
		||||
	// GetExploreReviewVersions gets the webhook ExploreReviewVersions field.
 | 
			
		||||
	GetExploreReviewVersions() []string
 | 
			
		||||
	// GetInterpreterContextVersions gets the webhook InterpreterContextVersions field.
 | 
			
		||||
	GetInterpreterContextVersions() []string
 | 
			
		||||
 | 
			
		||||
	// GetRESTClient gets the webhook client.
 | 
			
		||||
	GetRESTClient(clientManager *webhookutil.ClientManager) (*rest.RESTClient, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type resourceExploringAccessor struct {
 | 
			
		||||
	*configv1alpha1.ResourceExploringWebhook
 | 
			
		||||
	*configv1alpha1.ResourceInterpreterWebhook
 | 
			
		||||
	uid               string
 | 
			
		||||
	configurationName string
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +42,8 @@ type resourceExploringAccessor struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// NewResourceExploringAccessor create an accessor for webhook.
 | 
			
		||||
func NewResourceExploringAccessor(uid, configurationName string, hook *configv1alpha1.ResourceExploringWebhook) WebhookAccessor {
 | 
			
		||||
	return &resourceExploringAccessor{uid: uid, configurationName: configurationName, ResourceExploringWebhook: hook}
 | 
			
		||||
func NewResourceExploringAccessor(uid, configurationName string, hook *configv1alpha1.ResourceInterpreterWebhook) WebhookAccessor {
 | 
			
		||||
	return &resourceExploringAccessor{uid: uid, configurationName: configurationName, ResourceInterpreterWebhook: hook}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUID gets a string that uniquely identifies the webhook.
 | 
			
		||||
| 
						 | 
				
			
			@ -73,19 +71,14 @@ func (a *resourceExploringAccessor) GetRules() []configv1alpha1.RuleWithOperatio
 | 
			
		|||
	return a.Rules
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFailurePolicy gets the webhook FailurePolicy field.
 | 
			
		||||
func (a *resourceExploringAccessor) GetFailurePolicy() *admissionregistrationv1.FailurePolicyType {
 | 
			
		||||
	return a.FailurePolicy
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTimeoutSeconds gets the webhook TimeoutSeconds field.
 | 
			
		||||
func (a *resourceExploringAccessor) GetTimeoutSeconds() *int32 {
 | 
			
		||||
	return a.TimeoutSeconds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExploreReviewVersions gets the webhook ExploreReviewVersions field.
 | 
			
		||||
func (a *resourceExploringAccessor) GetExploreReviewVersions() []string {
 | 
			
		||||
	return a.ExploreReviewVersions
 | 
			
		||||
// GetExploreReviewVersions gets the webhook InterpreterContextVersions field.
 | 
			
		||||
func (a *resourceExploringAccessor) GetInterpreterContextVersions() []string {
 | 
			
		||||
	return a.InterpreterContextVersions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRESTClient gets the webhook client.
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +90,7 @@ func (a *resourceExploringAccessor) GetRESTClient(clientManager *webhookutil.Cli
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// hookClientConfigForWebhook construct a webhookutil.ClientConfig using an admissionregistrationv1.WebhookClientConfig
 | 
			
		||||
// to access v1alpha1.ResourceExploringWebhook. webhookutil.ClientConfig is used to create a HookClient
 | 
			
		||||
// to access v1alpha1.ResourceInterpreterWebhook. webhookutil.ClientConfig is used to create a HookClient
 | 
			
		||||
// and the purpose of the config struct is to share that with other packages that need to create a HookClient.
 | 
			
		||||
func hookClientConfigForWebhook(hookName string, config admissionregistrationv1.WebhookClientConfig) webhookutil.ClientConfig {
 | 
			
		||||
	clientConfig := webhookutil.ClientConfig{Name: hookName, CABundle: config.CABundle}
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ import (
 | 
			
		|||
var resourceExploringWebhookConfigurationsGVR = schema.GroupVersionResource{
 | 
			
		||||
	Group:    configv1alpha1.GroupVersion.Group,
 | 
			
		||||
	Version:  configv1alpha1.GroupVersion.Version,
 | 
			
		||||
	Resource: "resourceexploringwebhookconfigurations",
 | 
			
		||||
	Resource: "resourceinterpreterwebhookconfigurations",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfigManager can list dynamic webhooks.
 | 
			
		||||
| 
						 | 
				
			
			@ -30,20 +30,20 @@ type ConfigManager interface {
 | 
			
		|||
	HasSynced() bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// exploreConfigManager collect the resource explore webhook configuration.
 | 
			
		||||
type exploreConfigManager struct {
 | 
			
		||||
// interpreterConfigManager collect the resource interpreter webhook configuration.
 | 
			
		||||
type interpreterConfigManager struct {
 | 
			
		||||
	configuration *atomic.Value
 | 
			
		||||
	lister        cache.GenericLister
 | 
			
		||||
	initialSynced *atomic.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookAccessors return all configured resource explore webhook.
 | 
			
		||||
func (m *exploreConfigManager) HookAccessors() []WebhookAccessor {
 | 
			
		||||
// HookAccessors return all configured resource interpreter webhook.
 | 
			
		||||
func (m *interpreterConfigManager) HookAccessors() []WebhookAccessor {
 | 
			
		||||
	return m.configuration.Load().([]WebhookAccessor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasSynced return true when the manager is synced with existing configuration.
 | 
			
		||||
func (m *exploreConfigManager) HasSynced() bool {
 | 
			
		||||
func (m *interpreterConfigManager) HasSynced() bool {
 | 
			
		||||
	if m.initialSynced.Load().(bool) {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -60,9 +60,9 @@ func (m *exploreConfigManager) HasSynced() bool {
 | 
			
		|||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewExploreConfigManager return a new exploreConfigManager with resourceexploringwebhookconfigurations handlers.
 | 
			
		||||
// NewExploreConfigManager return a new interpreterConfigManager with resourceinterpreterwebhookconfigurations handlers.
 | 
			
		||||
func NewExploreConfigManager(inform informermanager.SingleClusterInformerManager) ConfigManager {
 | 
			
		||||
	manager := &exploreConfigManager{
 | 
			
		||||
	manager := &interpreterConfigManager{
 | 
			
		||||
		configuration: &atomic.Value{},
 | 
			
		||||
		lister:        inform.Lister(resourceExploringWebhookConfigurationsGVR),
 | 
			
		||||
		initialSynced: &atomic.Value{},
 | 
			
		||||
| 
						 | 
				
			
			@ -80,18 +80,18 @@ func NewExploreConfigManager(inform informermanager.SingleClusterInformerManager
 | 
			
		|||
	return manager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *exploreConfigManager) updateConfiguration() {
 | 
			
		||||
func (m *interpreterConfigManager) updateConfiguration() {
 | 
			
		||||
	configurations, err := m.lister.List(labels.Everything())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		utilruntime.HandleError(fmt.Errorf("error updating configuration: %v", err))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configs := make([]*configv1alpha1.ResourceExploringWebhookConfiguration, 0)
 | 
			
		||||
	configs := make([]*configv1alpha1.ResourceInterpreterWebhookConfiguration, 0)
 | 
			
		||||
	for _, c := range configurations {
 | 
			
		||||
		unstructuredConfig, err := runtime.DefaultUnstructuredConverter.ToUnstructured(c)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			klog.Errorf("Failed to transform ResourceExploringWebhookConfiguration: %w", err)
 | 
			
		||||
			klog.Errorf("Failed to transform ResourceInterpreterWebhookConfiguration: %w", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +107,7 @@ func (m *exploreConfigManager) updateConfiguration() {
 | 
			
		|||
	m.initialSynced.Store(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mergeResourceExploreWebhookConfigurations(configurations []*configv1alpha1.ResourceExploringWebhookConfiguration) []WebhookAccessor {
 | 
			
		||||
func mergeResourceExploreWebhookConfigurations(configurations []*configv1alpha1.ResourceInterpreterWebhookConfiguration) []WebhookAccessor {
 | 
			
		||||
	sort.SliceStable(configurations, func(i, j int) bool {
 | 
			
		||||
		return configurations[i].Name < configurations[j].Name
 | 
			
		||||
	})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package customizedexplorer
 | 
			
		||||
package customizedinterpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -15,20 +15,20 @@ import (
 | 
			
		|||
 | 
			
		||||
	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/crdexplorer/customizedexplorer/configmanager"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer/customizedexplorer/webhook"
 | 
			
		||||
	crdexplorerutil "github.com/karmada-io/karmada/pkg/util/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter/customizedinterpreter/configmanager"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter/customizedinterpreter/webhook"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/informermanager"
 | 
			
		||||
	interpreterutil "github.com/karmada-io/karmada/pkg/util/interpreter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CustomizedExplorer explore custom resource with webhook configuration.
 | 
			
		||||
type CustomizedExplorer struct {
 | 
			
		||||
// CustomizedInterpreter interpret custom resource with webhook configuration.
 | 
			
		||||
type CustomizedInterpreter struct {
 | 
			
		||||
	hookManager   configmanager.ConfigManager
 | 
			
		||||
	configManager *webhookutil.ClientManager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCustomizedExplorer return a new CustomizedExplorer.
 | 
			
		||||
func NewCustomizedExplorer(kubeconfig string, informer informermanager.SingleClusterInformerManager) (*CustomizedExplorer, error) {
 | 
			
		||||
// NewCustomizedInterpreter return a new CustomizedInterpreter.
 | 
			
		||||
func NewCustomizedInterpreter(kubeconfig string, informer informermanager.SingleClusterInformerManager) (*CustomizedInterpreter, error) {
 | 
			
		||||
	cm, err := webhookutil.NewClientManager(
 | 
			
		||||
		[]schema.GroupVersion{configv1alpha1.SchemeGroupVersion},
 | 
			
		||||
		configv1alpha1.AddToScheme,
 | 
			
		||||
| 
						 | 
				
			
			@ -43,14 +43,14 @@ func NewCustomizedExplorer(kubeconfig string, informer informermanager.SingleClu
 | 
			
		|||
	cm.SetAuthenticationInfoResolver(authInfoResolver)
 | 
			
		||||
	cm.SetServiceResolver(webhookutil.NewDefaultServiceResolver())
 | 
			
		||||
 | 
			
		||||
	return &CustomizedExplorer{
 | 
			
		||||
	return &CustomizedInterpreter{
 | 
			
		||||
		hookManager:   configmanager.NewExploreConfigManager(informer),
 | 
			
		||||
		configManager: &cm,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookEnabled tells if any hook exist for specific resource type and operation type.
 | 
			
		||||
func (e *CustomizedExplorer) HookEnabled(attributes *webhook.RequestAttributes) bool {
 | 
			
		||||
func (e *CustomizedInterpreter) HookEnabled(attributes *webhook.RequestAttributes) bool {
 | 
			
		||||
	if !e.hookManager.HasSynced() {
 | 
			
		||||
		klog.Errorf("not yet ready to handle request")
 | 
			
		||||
		return false
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ func (e *CustomizedExplorer) HookEnabled(attributes *webhook.RequestAttributes)
 | 
			
		|||
 | 
			
		||||
	hook := e.getFirstRelevantHook(attributes)
 | 
			
		||||
	if hook == nil {
 | 
			
		||||
		klog.V(4).Infof("Hook explorer is not enabled for kind %q with operation %q.",
 | 
			
		||||
		klog.V(4).Infof("Hook interpreter is not enabled for kind %q with operation %q.",
 | 
			
		||||
			attributes.Object.GroupVersionKind(), attributes.Operation)
 | 
			
		||||
	}
 | 
			
		||||
	return hook != nil
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +66,9 @@ func (e *CustomizedExplorer) HookEnabled(attributes *webhook.RequestAttributes)
 | 
			
		|||
 | 
			
		||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | 
			
		||||
// return matched value to indicate whether there is a matching hook.
 | 
			
		||||
func (e *CustomizedExplorer) GetReplicas(ctx context.Context, attributes *webhook.RequestAttributes) (replica int32, requires *workv1alpha2.ReplicaRequirements, matched bool, err error) {
 | 
			
		||||
func (e *CustomizedInterpreter) GetReplicas(ctx context.Context, attributes *webhook.RequestAttributes) (replica int32, requires *workv1alpha2.ReplicaRequirements, matched bool, err error) {
 | 
			
		||||
	var response *webhook.ResponseAttributes
 | 
			
		||||
	response, matched, err = e.explore(ctx, attributes)
 | 
			
		||||
	response, matched, err = e.interpret(ctx, attributes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -81,9 +81,9 @@ func (e *CustomizedExplorer) GetReplicas(ctx context.Context, attributes *webhoo
 | 
			
		|||
 | 
			
		||||
// Retain returns the patch that based on the "desired" object but with values retained from the "observed" object.
 | 
			
		||||
// return matched value to indicate whether there is a matching hook.
 | 
			
		||||
func (e *CustomizedExplorer) Retain(ctx context.Context, attributes *webhook.RequestAttributes) (patch []byte, patchType configv1alpha1.PatchType, matched bool, err error) {
 | 
			
		||||
func (e *CustomizedInterpreter) Retain(ctx context.Context, attributes *webhook.RequestAttributes) (patch []byte, patchType configv1alpha1.PatchType, matched bool, err error) {
 | 
			
		||||
	var response *webhook.ResponseAttributes
 | 
			
		||||
	response, matched, err = e.explore(ctx, attributes)
 | 
			
		||||
	response, matched, err = e.interpret(ctx, attributes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +94,7 @@ func (e *CustomizedExplorer) Retain(ctx context.Context, attributes *webhook.Req
 | 
			
		|||
	return response.Patch, response.PatchType, matched, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomizedExplorer) getFirstRelevantHook(attributes *webhook.RequestAttributes) configmanager.WebhookAccessor {
 | 
			
		||||
func (e *CustomizedInterpreter) getFirstRelevantHook(attributes *webhook.RequestAttributes) configmanager.WebhookAccessor {
 | 
			
		||||
	relevantHooks := make([]configmanager.WebhookAccessor, 0)
 | 
			
		||||
	for _, hook := range e.hookManager.HookAccessors() {
 | 
			
		||||
		if shouldCallHook(hook, attributes) {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ func (e *CustomizedExplorer) getFirstRelevantHook(attributes *webhook.RequestAtt
 | 
			
		|||
	return relevantHooks[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomizedExplorer) explore(ctx context.Context, attributes *webhook.RequestAttributes) (*webhook.ResponseAttributes, bool, error) {
 | 
			
		||||
func (e *CustomizedInterpreter) interpret(ctx context.Context, attributes *webhook.RequestAttributes) (*webhook.ResponseAttributes, bool, error) {
 | 
			
		||||
	if !e.hookManager.HasSynced() {
 | 
			
		||||
		return nil, false, fmt.Errorf("not yet ready to handle request")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +158,7 @@ func (e *CustomizedExplorer) explore(ctx context.Context, attributes *webhook.Re
 | 
			
		|||
 | 
			
		||||
func shouldCallHook(hook configmanager.WebhookAccessor, attributes *webhook.RequestAttributes) bool {
 | 
			
		||||
	for _, rule := range hook.GetRules() {
 | 
			
		||||
		matcher := crdexplorerutil.Matcher{
 | 
			
		||||
		matcher := interpreterutil.Matcher{
 | 
			
		||||
			Operation: attributes.Operation,
 | 
			
		||||
			Object:    attributes.Object,
 | 
			
		||||
			Rule:      rule,
 | 
			
		||||
| 
						 | 
				
			
			@ -170,12 +170,12 @@ func shouldCallHook(hook configmanager.WebhookAccessor, attributes *webhook.Requ
 | 
			
		|||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomizedExplorer) callHook(ctx context.Context, hook configmanager.WebhookAccessor, attributes *webhook.RequestAttributes) (*webhook.ResponseAttributes, error) {
 | 
			
		||||
	uid, req, err := webhook.CreateExploreReview(hook.GetExploreReviewVersions(), attributes)
 | 
			
		||||
func (e *CustomizedInterpreter) callHook(ctx context.Context, hook configmanager.WebhookAccessor, attributes *webhook.RequestAttributes) (*webhook.ResponseAttributes, error) {
 | 
			
		||||
	uid, req, err := webhook.CreateResourceInterpreterContext(hook.GetInterpreterContextVersions(), attributes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &webhookutil.ErrCallingWebhook{
 | 
			
		||||
			WebhookName: hook.GetUID(),
 | 
			
		||||
			Reason:      fmt.Errorf("could not create ExploreReview objects: %w", err),
 | 
			
		||||
			Reason:      fmt.Errorf("could not create ResourceInterpreterContext objects: %w", err),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +187,7 @@ func (e *CustomizedExplorer) callHook(ctx context.Context, hook configmanager.We
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	trace := utiltrace.New("Call resource explore webhook",
 | 
			
		||||
	trace := utiltrace.New("Call resource interpret webhook",
 | 
			
		||||
		utiltrace.Field{Key: "configuration", Value: hook.GetConfigurationName()},
 | 
			
		||||
		utiltrace.Field{Key: "webhook", Value: hook.GetName()},
 | 
			
		||||
		utiltrace.Field{Key: "kind", Value: attributes.Object.GroupVersionKind()},
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +215,7 @@ func (e *CustomizedExplorer) callHook(ctx context.Context, hook configmanager.We
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := &configv1alpha1.ExploreReview{}
 | 
			
		||||
	response := &configv1alpha1.ResourceInterpreterContext{}
 | 
			
		||||
	err = r.Do(ctx).Into(response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &webhookutil.ErrCallingWebhook{
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +226,7 @@ func (e *CustomizedExplorer) callHook(ctx context.Context, hook configmanager.We
 | 
			
		|||
	trace.Step("Request completed")
 | 
			
		||||
 | 
			
		||||
	var res *webhook.ResponseAttributes
 | 
			
		||||
	res, err = webhook.VerifyExploreReview(uid, attributes.Operation, response)
 | 
			
		||||
	res, err = webhook.VerifyResourceInterpreterContext(uid, attributes.Operation, response)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, &webhookutil.ErrCallingWebhook{
 | 
			
		||||
			WebhookName: hook.GetUID(),
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ import (
 | 
			
		|||
 | 
			
		||||
// RequestAttributes contains the attributes that call webhook.
 | 
			
		||||
type RequestAttributes struct {
 | 
			
		||||
	Operation        configv1alpha1.OperationType
 | 
			
		||||
	Operation        configv1alpha1.InterpreterOperation
 | 
			
		||||
	Object           *unstructured.Unstructured
 | 
			
		||||
	ObservedObj      *unstructured.Unstructured
 | 
			
		||||
	ReplicasSet      int32
 | 
			
		||||
| 
						 | 
				
			
			@ -11,26 +11,26 @@ import (
 | 
			
		|||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateExploreReview returns the unique request uid, the ExploreReview object to send the webhook,
 | 
			
		||||
// CreateResourceInterpreterContext returns the unique request uid, the ResourceInterpreterContext object to send the webhook,
 | 
			
		||||
// or an error if the webhook does not support receiving any of the versions we know to send.
 | 
			
		||||
func CreateExploreReview(versions []string, attributes *RequestAttributes) (uid types.UID, request runtime.Object, err error) {
 | 
			
		||||
func CreateResourceInterpreterContext(versions []string, attributes *RequestAttributes) (uid types.UID, request runtime.Object, err error) {
 | 
			
		||||
	for _, version := range versions {
 | 
			
		||||
		switch version {
 | 
			
		||||
		case configv1alpha1.GroupVersion.Version:
 | 
			
		||||
			uid = uuid.NewUUID()
 | 
			
		||||
			request = CreateV1alpha1ExploreReview(uid, attributes)
 | 
			
		||||
			request = CreateV1alpha1ResourceInterpreterContext(uid, attributes)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = fmt.Errorf("webhook does not accept known ExploreReview versions (v1alpha1)")
 | 
			
		||||
	err = fmt.Errorf("webhook does not accept known ResourceInterpreterContext versions (v1alpha1)")
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateV1alpha1ExploreReview creates an ExploreReview for the provided RequestAttributes.
 | 
			
		||||
func CreateV1alpha1ExploreReview(uid types.UID, attributes *RequestAttributes) *configv1alpha1.ExploreReview {
 | 
			
		||||
	review := &configv1alpha1.ExploreReview{
 | 
			
		||||
		Request: &configv1alpha1.ExploreRequest{
 | 
			
		||||
// CreateV1alpha1ResourceInterpreterContext creates an ResourceInterpreterContext for the provided RequestAttributes.
 | 
			
		||||
func CreateV1alpha1ResourceInterpreterContext(uid types.UID, attributes *RequestAttributes) *configv1alpha1.ResourceInterpreterContext {
 | 
			
		||||
	r := &configv1alpha1.ResourceInterpreterContext{
 | 
			
		||||
		Request: &configv1alpha1.ResourceInterpreterRequest{
 | 
			
		||||
			UID: uid,
 | 
			
		||||
			Kind: metav1.GroupVersionKind{
 | 
			
		||||
				Group:   attributes.Object.GroupVersionKind().Group,
 | 
			
		||||
| 
						 | 
				
			
			@ -49,16 +49,16 @@ func CreateV1alpha1ExploreReview(uid types.UID, attributes *RequestAttributes) *
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if attributes.ObservedObj != nil {
 | 
			
		||||
		review.Request.ObservedObject = &runtime.RawExtension{Object: attributes.ObservedObj.DeepCopyObject()}
 | 
			
		||||
		r.Request.ObservedObject = &runtime.RawExtension{Object: attributes.ObservedObj.DeepCopyObject()}
 | 
			
		||||
	}
 | 
			
		||||
	return review
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VerifyExploreReview checks the validity of the provided explore review object, and returns ResponseAttributes,
 | 
			
		||||
// or an error if the provided explore review was not valid.
 | 
			
		||||
func VerifyExploreReview(uid types.UID, operation configv1alpha1.OperationType, review runtime.Object) (response *ResponseAttributes, err error) {
 | 
			
		||||
	switch r := review.(type) {
 | 
			
		||||
	case *configv1alpha1.ExploreReview:
 | 
			
		||||
// VerifyResourceInterpreterContext checks the validity of the provided resourceInterpreterContext, and returns ResponseAttributes,
 | 
			
		||||
// or an error if the provided resourceInterpreterContext was not valid.
 | 
			
		||||
func VerifyResourceInterpreterContext(uid types.UID, operation configv1alpha1.InterpreterOperation, interpreterContext runtime.Object) (response *ResponseAttributes, err error) {
 | 
			
		||||
	switch r := interpreterContext.(type) {
 | 
			
		||||
	case *configv1alpha1.ResourceInterpreterContext:
 | 
			
		||||
		if r.Response == nil {
 | 
			
		||||
			return nil, fmt.Errorf("webhook resonse was absent")
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -67,17 +67,17 @@ func VerifyExploreReview(uid types.UID, operation configv1alpha1.OperationType,
 | 
			
		|||
			return nil, fmt.Errorf("expected response.uid %q, got %q", uid, r.Response.UID)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res, err := verifyExploreResponse(operation, r.Response)
 | 
			
		||||
		res, err := verifyResourceInterpreterContext(operation, r.Response)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return res, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("unexpected response type %T", review)
 | 
			
		||||
		return nil, fmt.Errorf("unexpected response type %T", interpreterContext)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func verifyExploreResponse(operation configv1alpha1.OperationType, response *configv1alpha1.ExploreResponse) (*ResponseAttributes, error) {
 | 
			
		||||
func verifyResourceInterpreterContext(operation configv1alpha1.InterpreterOperation, response *configv1alpha1.ResourceInterpreterResponse) (*ResponseAttributes, error) {
 | 
			
		||||
	res := &ResponseAttributes{}
 | 
			
		||||
 | 
			
		||||
	res.Successful = response.Successful
 | 
			
		||||
| 
						 | 
				
			
			@ -90,29 +90,29 @@ func verifyExploreResponse(operation configv1alpha1.OperationType, response *con
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	switch operation {
 | 
			
		||||
	case configv1alpha1.ExploreReplica:
 | 
			
		||||
	case configv1alpha1.InterpreterOperationInterpretReplica:
 | 
			
		||||
		if response.Replicas == nil {
 | 
			
		||||
			return nil, fmt.Errorf("webhook returned nil response.replicas")
 | 
			
		||||
		}
 | 
			
		||||
		res.Replicas = *response.Replicas
 | 
			
		||||
		res.ReplicaRequirements = response.ReplicaRequirements
 | 
			
		||||
		return res, nil
 | 
			
		||||
	case configv1alpha1.ExploreDependencies:
 | 
			
		||||
	case configv1alpha1.InterpreterOperationInterpretDependency:
 | 
			
		||||
		res.Dependencies = response.Dependencies
 | 
			
		||||
		return res, nil
 | 
			
		||||
	case configv1alpha1.ExplorePacking, configv1alpha1.ExploreReplicaRevising,
 | 
			
		||||
		configv1alpha1.ExploreRetaining, configv1alpha1.ExploreStatusAggregating:
 | 
			
		||||
		err := verifyExploreResponseWithPatch(response)
 | 
			
		||||
	case configv1alpha1.InterpreterOperationPrune, configv1alpha1.InterpreterOperationReviseReplica,
 | 
			
		||||
		configv1alpha1.InterpreterOperationRetain, configv1alpha1.InterpreterOperationAggregateStatus:
 | 
			
		||||
		err := verifyResourceInterpreterContextWithPatch(response)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		res.Patch = response.Patch
 | 
			
		||||
		res.PatchType = *response.PatchType
 | 
			
		||||
		return res, nil
 | 
			
		||||
	case configv1alpha1.ExploreStatus:
 | 
			
		||||
	case configv1alpha1.InterpreterOperationInterpretStatus:
 | 
			
		||||
		res.RawStatus = *response.RawStatus
 | 
			
		||||
		return res, nil
 | 
			
		||||
	case configv1alpha1.ExploreHealthy:
 | 
			
		||||
	case configv1alpha1.InterpreterOperationInterpretHealthy:
 | 
			
		||||
		if response.Healthy == nil {
 | 
			
		||||
			return nil, fmt.Errorf("webhook returned nil response.healthy")
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ func verifyExploreResponse(operation configv1alpha1.OperationType, response *con
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func verifyExploreResponseWithPatch(response *configv1alpha1.ExploreResponse) error {
 | 
			
		||||
func verifyResourceInterpreterContextWithPatch(response *configv1alpha1.ResourceInterpreterResponse) error {
 | 
			
		||||
	if len(response.Patch) == 0 && response.PatchType == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
package defaultinterpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultInterpreter contains all default operation interpreter factory
 | 
			
		||||
// for interpreting common resource.
 | 
			
		||||
type DefaultInterpreter struct {
 | 
			
		||||
	replicaHandlers   map[schema.GroupVersionKind]replicaInterpreter
 | 
			
		||||
	retentionHandlers map[schema.GroupVersionKind]retentionInterpreter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultInterpreter return a new DefaultInterpreter.
 | 
			
		||||
func NewDefaultInterpreter() *DefaultInterpreter {
 | 
			
		||||
	return &DefaultInterpreter{
 | 
			
		||||
		replicaHandlers:   getAllDefaultReplicaInterpreter(),
 | 
			
		||||
		retentionHandlers: getAllDefaultRetentionInterpreter(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookEnabled tells if any hook exist for specific resource type and operation type.
 | 
			
		||||
func (e *DefaultInterpreter) HookEnabled(kind schema.GroupVersionKind, operationType configv1alpha1.InterpreterOperation) bool {
 | 
			
		||||
	switch operationType {
 | 
			
		||||
	case configv1alpha1.InterpreterOperationInterpretReplica:
 | 
			
		||||
		if _, exist := e.replicaHandlers[kind]; exist {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	case configv1alpha1.InterpreterOperationRetain:
 | 
			
		||||
		if _, exist := e.retentionHandlers[kind]; exist {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO(RainbowMango): more cases should be added here
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	klog.V(4).Infof("Default interpreter is not enabled for kind %q with operation %q.", kind, operationType)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | 
			
		||||
func (e *DefaultInterpreter) GetReplicas(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
	handler, exist := e.replicaHandlers[object.GroupVersionKind()]
 | 
			
		||||
	if !exist {
 | 
			
		||||
		return 0, &workv1alpha2.ReplicaRequirements{}, fmt.Errorf("defalut interpreter for operation %s not found", configv1alpha1.InterpreterOperationInterpretReplica)
 | 
			
		||||
	}
 | 
			
		||||
	return handler(object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
 | 
			
		||||
func (e *DefaultInterpreter) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
 | 
			
		||||
	handler, exist := e.retentionHandlers[desired.GroupVersionKind()]
 | 
			
		||||
	if !exist {
 | 
			
		||||
		return nil, fmt.Errorf("default retain interpreter for %q not found", desired.GroupVersionKind())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return handler(desired, observed)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package defaultexplorer
 | 
			
		||||
package defaultinterpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	appsv1 "k8s.io/api/apps/v1"
 | 
			
		||||
| 
						 | 
				
			
			@ -12,17 +12,17 @@ import (
 | 
			
		|||
	"github.com/karmada-io/karmada/pkg/util/helper"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// replicaExplorer is the function that used to parse replica and requirements from object.
 | 
			
		||||
type replicaExplorer func(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error)
 | 
			
		||||
// replicaInterpreter is the function that used to parse replica and requirements from object.
 | 
			
		||||
type replicaInterpreter func(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error)
 | 
			
		||||
 | 
			
		||||
func getAllDefaultReplicaExplorer() map[schema.GroupVersionKind]replicaExplorer {
 | 
			
		||||
	explorers := make(map[schema.GroupVersionKind]replicaExplorer)
 | 
			
		||||
	explorers[appsv1.SchemeGroupVersion.WithKind(util.DeploymentKind)] = deployReplicaExplorer
 | 
			
		||||
	explorers[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = jobReplicaExplorer
 | 
			
		||||
	return explorers
 | 
			
		||||
func getAllDefaultReplicaInterpreter() map[schema.GroupVersionKind]replicaInterpreter {
 | 
			
		||||
	s := make(map[schema.GroupVersionKind]replicaInterpreter)
 | 
			
		||||
	s[appsv1.SchemeGroupVersion.WithKind(util.DeploymentKind)] = deployReplica
 | 
			
		||||
	s[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = jobReplica
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deployReplicaExplorer(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
func deployReplica(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
	deploy, err := helper.ConvertToDeployment(object)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		klog.Errorf("Failed to convert object(%s), err", object.GroupVersionKind().String(), err)
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ func deployReplicaExplorer(object *unstructured.Unstructured) (int32, *workv1alp
 | 
			
		|||
	return replica, requirement, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func jobReplicaExplorer(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
func jobReplica(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
 | 
			
		||||
	job, err := helper.ConvertToJob(object)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		klog.Errorf("Failed to convert object(%s), err", object.GroupVersionKind().String(), err)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package defaultexplorer
 | 
			
		||||
package defaultinterpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,17 +13,17 @@ import (
 | 
			
		|||
	"github.com/karmada-io/karmada/pkg/util/helper"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// retentionExplorer is the function that retains values from "observed" object.
 | 
			
		||||
type retentionExplorer func(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error)
 | 
			
		||||
// retentionInterpreter is the function that retains values from "observed" object.
 | 
			
		||||
type retentionInterpreter func(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error)
 | 
			
		||||
 | 
			
		||||
func getAllDefaultRetentionExplorer() map[schema.GroupVersionKind]retentionExplorer {
 | 
			
		||||
	explorers := make(map[schema.GroupVersionKind]retentionExplorer)
 | 
			
		||||
	explorers[corev1.SchemeGroupVersion.WithKind(util.PodKind)] = retainPodFields
 | 
			
		||||
	explorers[corev1.SchemeGroupVersion.WithKind(util.ServiceKind)] = retainServiceFields
 | 
			
		||||
	explorers[corev1.SchemeGroupVersion.WithKind(util.ServiceAccountKind)] = retainServiceAccountFields
 | 
			
		||||
	explorers[corev1.SchemeGroupVersion.WithKind(util.PersistentVolumeClaimKind)] = retainPersistentVolumeClaimFields
 | 
			
		||||
	explorers[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = retainJobSelectorFields
 | 
			
		||||
	return explorers
 | 
			
		||||
func getAllDefaultRetentionInterpreter() map[schema.GroupVersionKind]retentionInterpreter {
 | 
			
		||||
	s := make(map[schema.GroupVersionKind]retentionInterpreter)
 | 
			
		||||
	s[corev1.SchemeGroupVersion.WithKind(util.PodKind)] = retainPodFields
 | 
			
		||||
	s[corev1.SchemeGroupVersion.WithKind(util.ServiceKind)] = retainServiceFields
 | 
			
		||||
	s[corev1.SchemeGroupVersion.WithKind(util.ServiceAccountKind)] = retainServiceAccountFields
 | 
			
		||||
	s[corev1.SchemeGroupVersion.WithKind(util.PersistentVolumeClaimKind)] = retainPersistentVolumeClaimFields
 | 
			
		||||
	s[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = retainJobSelectorFields
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package resourceinterpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -10,19 +10,19 @@ import (
 | 
			
		|||
 | 
			
		||||
	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/crdexplorer/customizedexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer/customizedexplorer/webhook"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer/defaultexplorer"
 | 
			
		||||
	"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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CustomResourceExplorer manages both default and customized webhooks to explore custom resource structure.
 | 
			
		||||
type CustomResourceExplorer interface {
 | 
			
		||||
// 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 type.
 | 
			
		||||
	HookEnabled(object *unstructured.Unstructured, operationType configv1alpha1.OperationType) bool
 | 
			
		||||
	// HookEnabled tells if any hook exist for specific resource type and operation.
 | 
			
		||||
	HookEnabled(object *unstructured.Unstructured, 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -33,32 +33,32 @@ type CustomResourceExplorer interface {
 | 
			
		|||
	// other common method
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCustomResourceExplorer builds a new CustomResourceExplorer object.
 | 
			
		||||
func NewCustomResourceExplorer(kubeconfig string, informer informermanager.SingleClusterInformerManager) CustomResourceExplorer {
 | 
			
		||||
	return &customResourceExplorerImpl{
 | 
			
		||||
// NewResourceInterpreter builds a new ResourceInterpreter object.
 | 
			
		||||
func NewResourceInterpreter(kubeconfig string, informer informermanager.SingleClusterInformerManager) ResourceInterpreter {
 | 
			
		||||
	return &customResourceInterpreterImpl{
 | 
			
		||||
		kubeconfig: kubeconfig,
 | 
			
		||||
		informer:   informer,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type customResourceExplorerImpl struct {
 | 
			
		||||
type customResourceInterpreterImpl struct {
 | 
			
		||||
	kubeconfig string
 | 
			
		||||
	informer   informermanager.SingleClusterInformerManager
 | 
			
		||||
 | 
			
		||||
	customizedExplorer *customizedexplorer.CustomizedExplorer
 | 
			
		||||
	defaultExplorer    *defaultexplorer.DefaultExplorer
 | 
			
		||||
	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 *customResourceExplorerImpl) Start(ctx context.Context) (err error) {
 | 
			
		||||
	klog.Infof("Starting custom resource explorer.")
 | 
			
		||||
func (i *customResourceInterpreterImpl) Start(ctx context.Context) (err error) {
 | 
			
		||||
	klog.Infof("Starting custom resource interpreter.")
 | 
			
		||||
 | 
			
		||||
	i.customizedExplorer, err = customizedexplorer.NewCustomizedExplorer(i.kubeconfig, i.informer)
 | 
			
		||||
	i.customizedInterpreter, err = customizedinterpreter.NewCustomizedInterpreter(i.kubeconfig, i.informer)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i.defaultExplorer = defaultexplorer.NewDefaultExplorer()
 | 
			
		||||
	i.defaultInterpreter = defaultinterpreter.NewDefaultInterpreter()
 | 
			
		||||
 | 
			
		||||
	i.informer.Start()
 | 
			
		||||
	<-ctx.Done()
 | 
			
		||||
| 
						 | 
				
			
			@ -66,22 +66,22 @@ func (i *customResourceExplorerImpl) Start(ctx context.Context) (err error) {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HookEnabled tells if any hook exist for specific resource type and operation type.
 | 
			
		||||
func (i *customResourceExplorerImpl) HookEnabled(object *unstructured.Unstructured, operationType configv1alpha1.OperationType) bool {
 | 
			
		||||
// HookEnabled tells if any hook exist for specific resource type and operation.
 | 
			
		||||
func (i *customResourceInterpreterImpl) HookEnabled(object *unstructured.Unstructured, operation configv1alpha1.InterpreterOperation) bool {
 | 
			
		||||
	attributes := &webhook.RequestAttributes{
 | 
			
		||||
		Operation: operationType,
 | 
			
		||||
		Operation: operation,
 | 
			
		||||
		Object:    object,
 | 
			
		||||
	}
 | 
			
		||||
	return i.customizedExplorer.HookEnabled(attributes) || i.defaultExplorer.HookEnabled(object.GroupVersionKind(), operationType)
 | 
			
		||||
	return i.customizedInterpreter.HookEnabled(attributes) || i.defaultInterpreter.HookEnabled(object.GroupVersionKind(), operation)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
 | 
			
		||||
func (i *customResourceExplorerImpl) GetReplicas(object *unstructured.Unstructured) (replica int32, requires *workv1alpha2.ReplicaRequirements, err error) {
 | 
			
		||||
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.customizedExplorer.GetReplicas(context.TODO(), &webhook.RequestAttributes{
 | 
			
		||||
		Operation: configv1alpha1.ExploreReplica,
 | 
			
		||||
	replica, requires, hookEnabled, err = i.customizedInterpreter.GetReplicas(context.TODO(), &webhook.RequestAttributes{
 | 
			
		||||
		Operation: configv1alpha1.InterpreterOperationInterpretReplica,
 | 
			
		||||
		Object:    object,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -91,19 +91,19 @@ func (i *customResourceExplorerImpl) GetReplicas(object *unstructured.Unstructur
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replica, requires, err = i.defaultExplorer.GetReplicas(object)
 | 
			
		||||
	replica, requires, err = i.defaultInterpreter.GetReplicas(object)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
 | 
			
		||||
func (i *customResourceExplorerImpl) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
 | 
			
		||||
func (i *customResourceInterpreterImpl) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
 | 
			
		||||
	klog.V(4).Infof("Begin to retain object: %v %s/%s.", desired.GroupVersionKind(), desired.GetNamespace(), desired.GetName())
 | 
			
		||||
 | 
			
		||||
	var hookEnabled bool
 | 
			
		||||
	var patch []byte
 | 
			
		||||
	var patchType configv1alpha1.PatchType
 | 
			
		||||
	patch, patchType, hookEnabled, err = i.customizedExplorer.Retain(context.TODO(), &webhook.RequestAttributes{
 | 
			
		||||
		Operation:   configv1alpha1.ExploreRetaining,
 | 
			
		||||
	patch, patchType, hookEnabled, err = i.customizedInterpreter.Retain(context.TODO(), &webhook.RequestAttributes{
 | 
			
		||||
		Operation:   configv1alpha1.InterpreterOperationRetain,
 | 
			
		||||
		Object:      desired,
 | 
			
		||||
		ObservedObj: observed,
 | 
			
		||||
	})
 | 
			
		||||
| 
						 | 
				
			
			@ -114,10 +114,11 @@ func (i *customResourceExplorerImpl) Retain(desired *unstructured.Unstructured,
 | 
			
		|||
		return applyPatch(desired, patch, patchType)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i.defaultExplorer.Retain(desired, observed)
 | 
			
		||||
	return i.defaultInterpreter.Retain(desired, observed)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func applyPatch(desired *unstructured.Unstructured, patch []byte, patchType configv1alpha1.PatchType) (*unstructured.Unstructured, error) {
 | 
			
		||||
// applyPatch uses patchType mode to patch object.
 | 
			
		||||
func applyPatch(object *unstructured.Unstructured, patch []byte, patchType configv1alpha1.PatchType) (*unstructured.Unstructured, error) {
 | 
			
		||||
	switch patchType {
 | 
			
		||||
	case configv1alpha1.PatchTypeJSONPatch:
 | 
			
		||||
		patchObj, err := jsonpatch.DecodePatch(patch)
 | 
			
		||||
| 
						 | 
				
			
			@ -125,10 +126,10 @@ func applyPatch(desired *unstructured.Unstructured, patch []byte, patchType conf
 | 
			
		|||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if len(patchObj) == 0 {
 | 
			
		||||
			return desired, nil
 | 
			
		||||
			return object, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		objectJSONBytes, err := desired.MarshalJSON()
 | 
			
		||||
		objectJSONBytes, err := object.MarshalJSON()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -137,8 +138,8 @@ func applyPatch(desired *unstructured.Unstructured, patch []byte, patchType conf
 | 
			
		|||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = desired.UnmarshalJSON(patchedObjectJSONBytes)
 | 
			
		||||
		return desired, err
 | 
			
		||||
		err = object.UnmarshalJSON(patchedObjectJSONBytes)
 | 
			
		||||
		return object, err
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("return patch type %s is not support", patchType)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -123,9 +123,9 @@ func ConvertToEndpointSlice(obj *unstructured.Unstructured) (*discoveryv1beta1.E
 | 
			
		|||
	return typedObj, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConvertToResourceExploringWebhookConfiguration converts a ResourceExploringWebhookConfiguration object from unstructured to typed.
 | 
			
		||||
func ConvertToResourceExploringWebhookConfiguration(obj *unstructured.Unstructured) (*configv1alpha1.ResourceExploringWebhookConfiguration, error) {
 | 
			
		||||
	typedObj := &configv1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
// ConvertToResourceExploringWebhookConfiguration converts a ResourceInterpreterWebhookConfiguration object from unstructured to typed.
 | 
			
		||||
func ConvertToResourceExploringWebhookConfiguration(obj *unstructured.Unstructured) (*configv1alpha1.ResourceInterpreterWebhookConfiguration, error) {
 | 
			
		||||
	typedObj := &configv1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ const (
 | 
			
		|||
 | 
			
		||||
// Matcher determines if the Object matches the Rule.
 | 
			
		||||
type Matcher struct {
 | 
			
		||||
	Operation configv1alpha1.OperationType
 | 
			
		||||
	Operation configv1alpha1.InterpreterOperation
 | 
			
		||||
	Rule      configv1alpha1.RuleWithOperations
 | 
			
		||||
	Object    *unstructured.Unstructured
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ func (m *Matcher) Matches() bool {
 | 
			
		|||
 | 
			
		||||
func (m *Matcher) operation() bool {
 | 
			
		||||
	for _, op := range m.Rule.Operations {
 | 
			
		||||
		if op == configv1alpha1.OperationAll || op == m.Operation {
 | 
			
		||||
		if op == configv1alpha1.InterpreterOperationAll || op == m.Operation {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
	workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/crdexplorer"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/resourceinterpreter"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util"
 | 
			
		||||
	"github.com/karmada-io/karmada/pkg/util/restmapper"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -43,17 +43,17 @@ type objectWatcherImpl struct {
 | 
			
		|||
	KubeClientSet        client.Client
 | 
			
		||||
	VersionRecord        map[string]map[string]string
 | 
			
		||||
	ClusterClientSetFunc ClientSetFunc
 | 
			
		||||
	resourceExplorer     crdexplorer.CustomResourceExplorer
 | 
			
		||||
	resourceInterpreter  resourceinterpreter.ResourceInterpreter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewObjectWatcher returns an instance of ObjectWatcher
 | 
			
		||||
func NewObjectWatcher(kubeClientSet client.Client, restMapper meta.RESTMapper, clusterClientSetFunc ClientSetFunc, explorer crdexplorer.CustomResourceExplorer) ObjectWatcher {
 | 
			
		||||
func NewObjectWatcher(kubeClientSet client.Client, restMapper meta.RESTMapper, clusterClientSetFunc ClientSetFunc, interpreter resourceinterpreter.ResourceInterpreter) ObjectWatcher {
 | 
			
		||||
	return &objectWatcherImpl{
 | 
			
		||||
		KubeClientSet:        kubeClientSet,
 | 
			
		||||
		VersionRecord:        make(map[string]map[string]string),
 | 
			
		||||
		RESTMapper:           restMapper,
 | 
			
		||||
		ClusterClientSetFunc: clusterClientSetFunc,
 | 
			
		||||
		resourceExplorer:     explorer,
 | 
			
		||||
		resourceInterpreter:  interpreter,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +113,8 @@ func (o *objectWatcherImpl) retainClusterFields(desired, observed *unstructured.
 | 
			
		|||
	// and be set by user in karmada-controller-plane.
 | 
			
		||||
	util.MergeAnnotations(desired, observed)
 | 
			
		||||
 | 
			
		||||
	if o.resourceExplorer.HookEnabled(desired, configv1alpha1.ExploreRetaining) {
 | 
			
		||||
		return o.resourceExplorer.Retain(desired, observed)
 | 
			
		||||
	if o.resourceInterpreter.HookEnabled(desired, configv1alpha1.InterpreterOperationRetain) {
 | 
			
		||||
		return o.resourceInterpreter.Retain(desired, observed)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return desired, nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,11 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package configuration
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
			
		||||
 | 
			
		||||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var supportedFailurePolicies = sets.NewString(
 | 
			
		||||
	string(admissionregistrationv1.Ignore),
 | 
			
		||||
	string(admissionregistrationv1.Fail),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func hasWildcard(slice []string) bool {
 | 
			
		||||
	for _, s := range slice {
 | 
			
		||||
		if s == "*" {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package configuration
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package configuration
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ import (
 | 
			
		|||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ValidatingAdmission validates ResourceExploringWebhookConfiguration object when creating/updating.
 | 
			
		||||
// ValidatingAdmission validates ResourceInterpreterWebhookConfiguration object when creating/updating.
 | 
			
		||||
type ValidatingAdmission struct {
 | 
			
		||||
	decoder *admission.Decoder
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,13 +28,13 @@ var _ admission.DecoderInjector = &ValidatingAdmission{}
 | 
			
		|||
// Handle implements admission.Handler interface.
 | 
			
		||||
// It yields a response to an AdmissionRequest.
 | 
			
		||||
func (v *ValidatingAdmission) Handle(ctx context.Context, req admission.Request) admission.Response {
 | 
			
		||||
	configuration := &configv1alpha1.ResourceExploringWebhookConfiguration{}
 | 
			
		||||
	configuration := &configv1alpha1.ResourceInterpreterWebhookConfiguration{}
 | 
			
		||||
 | 
			
		||||
	err := v.decoder.Decode(req, configuration)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return admission.Errored(http.StatusBadRequest, err)
 | 
			
		||||
	}
 | 
			
		||||
	klog.V(2).Infof("Validating ResourceExploringWebhookConfiguration(%s) for request: %s", configuration.Name, req.Operation)
 | 
			
		||||
	klog.V(2).Infof("Validating ResourceInterpreterWebhookConfiguration(%s) for request: %s", configuration.Name, req.Operation)
 | 
			
		||||
 | 
			
		||||
	var allErrors field.ErrorList
 | 
			
		||||
	hookNames := sets.NewString()
 | 
			
		||||
| 
						 | 
				
			
			@ -62,21 +62,15 @@ func (v *ValidatingAdmission) InjectDecoder(d *admission.Decoder) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var supportedOperationType = sets.NewString(
 | 
			
		||||
	string(configv1alpha1.OperationAll),
 | 
			
		||||
	string(configv1alpha1.ExploreReplica),
 | 
			
		||||
	string(configv1alpha1.ExploreStatus),
 | 
			
		||||
	string(configv1alpha1.ExplorePacking),
 | 
			
		||||
	string(configv1alpha1.ExploreReplicaRevising),
 | 
			
		||||
	string(configv1alpha1.ExploreRetaining),
 | 
			
		||||
	string(configv1alpha1.ExploreStatusAggregating),
 | 
			
		||||
	string(configv1alpha1.ExploreHealthy),
 | 
			
		||||
	string(configv1alpha1.ExploreDependencies),
 | 
			
		||||
var supportedInterpreterOperation = sets.NewString(
 | 
			
		||||
	string(configv1alpha1.InterpreterOperationAll),
 | 
			
		||||
	string(configv1alpha1.InterpreterOperationInterpretReplica),
 | 
			
		||||
	string(configv1alpha1.InterpreterOperationRetain),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var acceptedExploreReviewVersions = []string{configv1alpha1.GroupVersion.Version}
 | 
			
		||||
var acceptedInterpreterContextVersions = []string{configv1alpha1.GroupVersion.Version}
 | 
			
		||||
 | 
			
		||||
func validateWebhook(hook *configv1alpha1.ResourceExploringWebhook, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
func validateWebhook(hook *configv1alpha1.ResourceInterpreterWebhook, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
	var allErrors field.ErrorList
 | 
			
		||||
	// hook.Name must be fully qualified
 | 
			
		||||
	allErrors = append(allErrors, validation.IsFullyQualifiedDomainName(fldPath.Child("name"), hook.Name)...)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,10 +79,6 @@ func validateWebhook(hook *configv1alpha1.ResourceExploringWebhook, fldPath *fie
 | 
			
		|||
		allErrors = append(allErrors, validateRuleWithOperations(&hook.Rules[i], fldPath.Child("rules").Index(i))...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hook.FailurePolicy != nil && !supportedFailurePolicies.Has(string(*hook.FailurePolicy)) {
 | 
			
		||||
		allErrors = append(allErrors, field.NotSupported(fldPath.Child("matchPolicy"), *hook.FailurePolicy, supportedFailurePolicies.List()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hook.TimeoutSeconds != nil && (*hook.TimeoutSeconds > 30 || *hook.TimeoutSeconds < 1) {
 | 
			
		||||
		allErrors = append(allErrors, field.Invalid(fldPath.Child("timeoutSeconds"), *hook.TimeoutSeconds, "the timeout value must be between 1 and 30 seconds"))
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -103,13 +93,13 @@ func validateWebhook(hook *configv1alpha1.ResourceExploringWebhook, fldPath *fie
 | 
			
		|||
		allErrors = append(allErrors, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, *cc.Service.Port)...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	allErrors = append(allErrors, validateExploreReviewVersions(hook.ExploreReviewVersions, fldPath.Child("exploreReviewVersions"))...)
 | 
			
		||||
	allErrors = append(allErrors, validateInterpreterContextVersions(hook.InterpreterContextVersions, fldPath.Child("interpreterContextVersions"))...)
 | 
			
		||||
	return allErrors
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasWildcardOperation(operations []configv1alpha1.OperationType) bool {
 | 
			
		||||
func hasWildcardOperation(operations []configv1alpha1.InterpreterOperation) bool {
 | 
			
		||||
	for _, o := range operations {
 | 
			
		||||
		if o == configv1alpha1.OperationAll {
 | 
			
		||||
		if o == configv1alpha1.InterpreterOperationAll {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -125,20 +115,20 @@ func validateRuleWithOperations(ruleWithOperations *configv1alpha1.RuleWithOpera
 | 
			
		|||
		allErrors = append(allErrors, field.Invalid(fldPath.Child("operations"), ruleWithOperations.Operations, "if '*' is present, must not specify other operations"))
 | 
			
		||||
	}
 | 
			
		||||
	for i, operation := range ruleWithOperations.Operations {
 | 
			
		||||
		if !supportedOperationType.Has(string(operation)) {
 | 
			
		||||
			allErrors = append(allErrors, field.NotSupported(fldPath.Child("operations").Index(i), operation, supportedOperationType.List()))
 | 
			
		||||
		if !supportedInterpreterOperation.Has(string(operation)) {
 | 
			
		||||
			allErrors = append(allErrors, field.NotSupported(fldPath.Child("operations").Index(i), operation, supportedInterpreterOperation.List()))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	allErrors = append(allErrors, validateRule(&ruleWithOperations.Rule, fldPath)...)
 | 
			
		||||
	return allErrors
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateExploreReviewVersions(versions []string, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
func validateInterpreterContextVersions(versions []string, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
	allErrors := field.ErrorList{}
 | 
			
		||||
 | 
			
		||||
	// Currently, only v1alpha1 accepted in ExploreReviewVersions
 | 
			
		||||
	// Currently, only v1alpha1 accepted in InterpreterContextVersions
 | 
			
		||||
	if len(versions) < 1 {
 | 
			
		||||
		allErrors = append(allErrors, field.Required(fldPath, fmt.Sprintf("must specify one of %v", strings.Join(acceptedExploreReviewVersions, ", "))))
 | 
			
		||||
		allErrors = append(allErrors, field.Required(fldPath, fmt.Sprintf("must specify one of %v", strings.Join(acceptedInterpreterContextVersions, ", "))))
 | 
			
		||||
	} else {
 | 
			
		||||
		visited := map[string]bool{}
 | 
			
		||||
		hasAcceptedVersion := false
 | 
			
		||||
| 
						 | 
				
			
			@ -158,14 +148,14 @@ func validateExploreReviewVersions(versions []string, fldPath *field.Path) field
 | 
			
		|||
		if !hasAcceptedVersion {
 | 
			
		||||
			allErrors = append(allErrors, field.Invalid(
 | 
			
		||||
				fldPath, versions,
 | 
			
		||||
				fmt.Sprintf("must include at least one of %v", strings.Join(acceptedExploreReviewVersions, ", "))))
 | 
			
		||||
				fmt.Sprintf("must include at least one of %v", strings.Join(acceptedInterpreterContextVersions, ", "))))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return allErrors
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isAcceptedExploreReviewVersions(v string) bool {
 | 
			
		||||
	for _, version := range acceptedExploreReviewVersions {
 | 
			
		||||
	for _, version := range acceptedInterpreterContextVersions {
 | 
			
		||||
		if v == version {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package crdexplorer
 | 
			
		||||
package configuration
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ func int32Ptr(i int32) *int32 { return &i }
 | 
			
		|||
func TestHasWildcardOperation(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		operations []configv1alpha1.OperationType
 | 
			
		||||
		operations []configv1alpha1.InterpreterOperation
 | 
			
		||||
		expected   bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -28,15 +28,15 @@ func TestHasWildcardOperation(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "has wildcard operation",
 | 
			
		||||
			operations: []configv1alpha1.OperationType{
 | 
			
		||||
				configv1alpha1.OperationAll,
 | 
			
		||||
			operations: []configv1alpha1.InterpreterOperation{
 | 
			
		||||
				configv1alpha1.InterpreterOperationAll,
 | 
			
		||||
			},
 | 
			
		||||
			expected: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "no have wildcard operation",
 | 
			
		||||
			operations: []configv1alpha1.OperationType{
 | 
			
		||||
				configv1alpha1.ExploreReplica,
 | 
			
		||||
			operations: []configv1alpha1.InterpreterOperation{
 | 
			
		||||
				configv1alpha1.InterpreterOperationInterpretReplica,
 | 
			
		||||
			},
 | 
			
		||||
			expected: false,
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -59,12 +59,12 @@ func TestIsAcceptedExploreReviewVersions(t *testing.T) {
 | 
			
		|||
		expected bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:     "is accepted explore review versions",
 | 
			
		||||
			version:  acceptedExploreReviewVersions[0],
 | 
			
		||||
			name:     "is accepted interpreter context versions",
 | 
			
		||||
			version:  acceptedInterpreterContextVersions[0],
 | 
			
		||||
			expected: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "is not accepted explore review versions",
 | 
			
		||||
			name:     "is not accepted interpreter context versions",
 | 
			
		||||
			version:  "",
 | 
			
		||||
			expected: false,
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ func TestIsAcceptedExploreReviewVersions(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func TestValidateRuleWithOperations(t *testing.T) {
 | 
			
		||||
	fldPath := field.NewPath("webhooks").Child("rules")
 | 
			
		||||
	notSupportedOperation := []configv1alpha1.OperationType{(configv1alpha1.OperationType)("notsupported")}
 | 
			
		||||
	notSupportedOperation := []configv1alpha1.InterpreterOperation{(configv1alpha1.InterpreterOperation)("notsupported")}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name               string
 | 
			
		||||
| 
						 | 
				
			
			@ -97,9 +97,9 @@ func TestValidateRuleWithOperations(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			name: "2 operations with wildcard",
 | 
			
		||||
			ruleWithOperations: &configv1alpha1.RuleWithOperations{
 | 
			
		||||
				Operations: []configv1alpha1.OperationType{
 | 
			
		||||
					configv1alpha1.OperationAll,
 | 
			
		||||
					configv1alpha1.ExploreReplica,
 | 
			
		||||
				Operations: []configv1alpha1.InterpreterOperation{
 | 
			
		||||
					configv1alpha1.InterpreterOperationAll,
 | 
			
		||||
					configv1alpha1.InterpreterOperationInterpretReplica,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "if '*' is present, must not specify other operations",
 | 
			
		||||
| 
						 | 
				
			
			@ -112,8 +112,8 @@ func TestValidateRuleWithOperations(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			name: "not validated rule",
 | 
			
		||||
			ruleWithOperations: &configv1alpha1.RuleWithOperations{
 | 
			
		||||
				Operations: []configv1alpha1.OperationType{
 | 
			
		||||
					configv1alpha1.OperationAll,
 | 
			
		||||
				Operations: []configv1alpha1.InterpreterOperation{
 | 
			
		||||
					configv1alpha1.InterpreterOperationAll,
 | 
			
		||||
				},
 | 
			
		||||
				Rule: configv1alpha1.Rule{
 | 
			
		||||
					APIGroups: []string{""},
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,7 @@ func TestValidateRuleWithOperations(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestValidateExploreReviewVersions(t *testing.T) {
 | 
			
		||||
	fldPath := field.NewPath("webhooks").Child("exploreReviewVersions")
 | 
			
		||||
	fldPath := field.NewPath("webhooks").Child("interpreterContextVersions")
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name          string
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +150,7 @@ func TestValidateExploreReviewVersions(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			name:          "no versions",
 | 
			
		||||
			versions:      nil,
 | 
			
		||||
			expectedError: fmt.Sprintf("must specify one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
 | 
			
		||||
			expectedError: fmt.Sprintf("must specify one of %v", strings.Join(acceptedInterpreterContextVersions, ", ")),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:          "duplicate versions",
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +160,7 @@ func TestValidateExploreReviewVersions(t *testing.T) {
 | 
			
		|||
		{
 | 
			
		||||
			name:          "invalid versions",
 | 
			
		||||
			versions:      []string{"test", "test"},
 | 
			
		||||
			expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
 | 
			
		||||
			expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedInterpreterContextVersions, ", ")),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:          "invalid DNS (RFC 1035) label",
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +171,7 @@ func TestValidateExploreReviewVersions(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			errs := validateExploreReviewVersions(test.versions, fldPath)
 | 
			
		||||
			errs := validateInterpreterContextVersions(test.versions, fldPath)
 | 
			
		||||
			err := errs.ToAggregate()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if e, a := test.expectedError, err.Error(); !strings.Contains(a, e) || e == "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -188,55 +188,47 @@ func TestValidateExploreReviewVersions(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func TestValidateWebhook(t *testing.T) {
 | 
			
		||||
	fldPath := field.NewPath("webhooks")
 | 
			
		||||
	policy := admissionregistrationv1.FailurePolicyType("fake policy")
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name          string
 | 
			
		||||
		hook          *configv1alpha1.ResourceExploringWebhook
 | 
			
		||||
		hook          *configv1alpha1.ResourceInterpreterWebhook
 | 
			
		||||
		expectedError string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "not qualified domain name",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				Name: "",
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "webhooks.name: Required value",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid rules",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				Rules: []configv1alpha1.RuleWithOperations{
 | 
			
		||||
					{
 | 
			
		||||
						Operations: []configv1alpha1.OperationType{},
 | 
			
		||||
						Operations: []configv1alpha1.InterpreterOperation{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "operations: Required value",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid policy",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
				FailurePolicy: &policy,
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "matchPolicy",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid timeout",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				TimeoutSeconds: int32Ptr(60),
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "the timeout value must be between 1 and 30 seconds",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "ClientConfig: exactly one of url or service is required",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				ClientConfig: admissionregistrationv1.WebhookClientConfig{},
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "exactly one of url or service is required",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "ClientConfig: invalid URL",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				ClientConfig: admissionregistrationv1.WebhookClientConfig{
 | 
			
		||||
					URL: strPtr(""),
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +237,7 @@ func TestValidateWebhook(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "ClientConfig: invalid service",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				ClientConfig: admissionregistrationv1.WebhookClientConfig{
 | 
			
		||||
					Service: &admissionregistrationv1.ServiceReference{
 | 
			
		||||
						Name: "",
 | 
			
		||||
| 
						 | 
				
			
			@ -257,11 +249,11 @@ func TestValidateWebhook(t *testing.T) {
 | 
			
		|||
			expectedError: "service name is required",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid explore review versions",
 | 
			
		||||
			hook: &configv1alpha1.ResourceExploringWebhook{
 | 
			
		||||
				ExploreReviewVersions: []string{""},
 | 
			
		||||
			name: "invalid interpreter context versions",
 | 
			
		||||
			hook: &configv1alpha1.ResourceInterpreterWebhook{
 | 
			
		||||
				InterpreterContextVersions: []string{""},
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
 | 
			
		||||
			expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedInterpreterContextVersions, ", ")),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package explorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ import (
 | 
			
		|||
	"k8s.io/apimachinery/pkg/util/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Decoder knows how to decode the contents of an explorer
 | 
			
		||||
// Decoder knows how to decode the contents of an resource interpreter
 | 
			
		||||
// request into a concrete object.
 | 
			
		||||
type Decoder struct {
 | 
			
		||||
	codecs serializer.CodecFactory
 | 
			
		||||
| 
						 | 
				
			
			@ -22,8 +22,8 @@ func NewDecoder(scheme *runtime.Scheme) *Decoder {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode decodes the inlined object in the ExploreRequest into the passed-in runtime.Object.
 | 
			
		||||
// If you want to decode the ObservedObject in the ExploreRequest, use DecodeRaw.
 | 
			
		||||
// Decode decodes the inlined object in the ResourceInterpreterRequest into the passed-in runtime.Object.
 | 
			
		||||
// If you want to decode the ObservedObject in the ResourceInterpreterRequest, use DecodeRaw.
 | 
			
		||||
// It errors out if req.Object.Raw is empty i.e. containing 0 raw bytes.
 | 
			
		||||
func (d *Decoder) Decode(req Request, into runtime.Object) error {
 | 
			
		||||
	if len(req.Object.Raw) == 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package explorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,20 +24,20 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	var err error
 | 
			
		||||
	ctx := r.Context()
 | 
			
		||||
 | 
			
		||||
	var reviewResponse Response
 | 
			
		||||
	var res Response
 | 
			
		||||
	if r.Body == nil {
 | 
			
		||||
		err = errors.New("request body is empty")
 | 
			
		||||
		klog.Errorf("bad request: %w", err)
 | 
			
		||||
		reviewResponse = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, reviewResponse)
 | 
			
		||||
		res = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, res)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer r.Body.Close()
 | 
			
		||||
	if body, err = ioutil.ReadAll(r.Body); err != nil {
 | 
			
		||||
		klog.Errorf("unable to read the body from the incoming request: %w", err)
 | 
			
		||||
		reviewResponse = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, reviewResponse)
 | 
			
		||||
		res = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, res)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,42 +45,42 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	if contentType := r.Header.Get("Content-Type"); contentType != "application/json" {
 | 
			
		||||
		err = fmt.Errorf("contentType=%s, expected application/json", contentType)
 | 
			
		||||
		klog.Errorf("unable to process a request with an unknown content type: %w", err)
 | 
			
		||||
		reviewResponse = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, reviewResponse)
 | 
			
		||||
		res = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, res)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	request := Request{}
 | 
			
		||||
	er := configv1alpha1.ExploreReview{}
 | 
			
		||||
	interpreterContext := configv1alpha1.ResourceInterpreterContext{}
 | 
			
		||||
	// avoid an extra copy
 | 
			
		||||
	er.Request = &request.ExploreRequest
 | 
			
		||||
	_, _, err = admissionCodecs.UniversalDeserializer().Decode(body, nil, &er)
 | 
			
		||||
	interpreterContext.Request = &request.ResourceInterpreterRequest
 | 
			
		||||
	_, _, err = admissionCodecs.UniversalDeserializer().Decode(body, nil, &interpreterContext)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		klog.Errorf("unable to decode the request: %w", err)
 | 
			
		||||
		reviewResponse = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, reviewResponse)
 | 
			
		||||
		res = Errored(http.StatusBadRequest, err)
 | 
			
		||||
		wh.writeResponse(w, res)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	klog.V(1).Infof("received request UID: %q, kind: %s", request.UID, request.Kind)
 | 
			
		||||
 | 
			
		||||
	reviewResponse = wh.Handle(ctx, request)
 | 
			
		||||
	wh.writeResponse(w, reviewResponse)
 | 
			
		||||
	res = wh.Handle(ctx, request)
 | 
			
		||||
	wh.writeResponse(w, res)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeResponse writes response to w generically, i.e. without encoding GVK information.
 | 
			
		||||
func (wh *Webhook) writeResponse(w io.Writer, response Response) {
 | 
			
		||||
	wh.writeExploreResponse(w, configv1alpha1.ExploreReview{
 | 
			
		||||
		Response: &response.ExploreResponse,
 | 
			
		||||
	wh.writeResourceInterpreterResponse(w, configv1alpha1.ResourceInterpreterContext{
 | 
			
		||||
		Response: &response.ResourceInterpreterResponse,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeExploreResponse writes ar to w.
 | 
			
		||||
func (wh *Webhook) writeExploreResponse(w io.Writer, review configv1alpha1.ExploreReview) {
 | 
			
		||||
	if err := json.NewEncoder(w).Encode(review); err != nil {
 | 
			
		||||
// writeResourceInterpreterResponse writes ar to w.
 | 
			
		||||
func (wh *Webhook) writeResourceInterpreterResponse(w io.Writer, interpreterContext configv1alpha1.ResourceInterpreterContext) {
 | 
			
		||||
	if err := json.NewEncoder(w).Encode(interpreterContext); err != nil {
 | 
			
		||||
		klog.Errorf("unable to encode the response: %w", err)
 | 
			
		||||
		wh.writeResponse(w, Errored(http.StatusInternalServerError, err))
 | 
			
		||||
	} else {
 | 
			
		||||
		response := review.Response
 | 
			
		||||
		response := interpreterContext.Response
 | 
			
		||||
		if response.Successful {
 | 
			
		||||
			klog.V(4).Infof("wrote response UID: %q, successful: %t", response.UID, response.Successful)
 | 
			
		||||
		} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package explorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
// DecoderInjector is used by the ControllerManager to inject decoder into webhook handlers.
 | 
			
		||||
type DecoderInjector interface {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package explorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ import (
 | 
			
		|||
// Errored creates a new Response for error-handling a request.
 | 
			
		||||
func Errored(code int32, err error) Response {
 | 
			
		||||
	return Response{
 | 
			
		||||
		ExploreResponse: configv1alpha1.ExploreResponse{
 | 
			
		||||
		ResourceInterpreterResponse: configv1alpha1.ResourceInterpreterResponse{
 | 
			
		||||
			Successful: false,
 | 
			
		||||
			Status: &configv1alpha1.RequestStatus{
 | 
			
		||||
				Code:    code,
 | 
			
		||||
| 
						 | 
				
			
			@ -27,14 +27,14 @@ func Succeeded(msg string) Response {
 | 
			
		|||
	return ValidationResponse(true, msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidationResponse returns a response for handle a explore request.
 | 
			
		||||
// ValidationResponse returns a response for handle a interpret request.
 | 
			
		||||
func ValidationResponse(successful bool, msg string) Response {
 | 
			
		||||
	code := http.StatusForbidden
 | 
			
		||||
	if successful {
 | 
			
		||||
		code = http.StatusOK
 | 
			
		||||
	}
 | 
			
		||||
	return Response{
 | 
			
		||||
		ExploreResponse: configv1alpha1.ExploreResponse{
 | 
			
		||||
		ResourceInterpreterResponse: configv1alpha1.ResourceInterpreterResponse{
 | 
			
		||||
			Successful: successful,
 | 
			
		||||
			Status: &configv1alpha1.RequestStatus{
 | 
			
		||||
				Code:    int32(code),
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ func PatchResponseFromRaw(original, current []byte) Response {
 | 
			
		|||
 | 
			
		||||
	patchType := configv1alpha1.PatchTypeJSONPatch
 | 
			
		||||
	return Response{
 | 
			
		||||
		ExploreResponse: configv1alpha1.ExploreResponse{
 | 
			
		||||
		ResourceInterpreterResponse: configv1alpha1.ResourceInterpreterResponse{
 | 
			
		||||
			Successful: true,
 | 
			
		||||
			Patch:      patch,
 | 
			
		||||
			PatchType:  &patchType,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package explorer
 | 
			
		||||
package interpreter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -9,22 +9,22 @@ import (
 | 
			
		|||
	configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Request defines the input for an explorer handler.
 | 
			
		||||
// Request defines the input for an interpreter handler.
 | 
			
		||||
// It contains information to identify the object in
 | 
			
		||||
// question (kind, name, namespace), as well as the
 | 
			
		||||
// operation in request(e.g. ExploreReplica, ExplorePacking,
 | 
			
		||||
// operation in request(e.g. InterpreterOperationInterpretReplica, InterpreterOperationPrune,
 | 
			
		||||
// etc), and the object itself.
 | 
			
		||||
type Request struct {
 | 
			
		||||
	configv1alpha1.ExploreRequest
 | 
			
		||||
	configv1alpha1.ResourceInterpreterRequest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Response is the output of an explorer handler.
 | 
			
		||||
// Response is the output of an interpreter handler.
 | 
			
		||||
type Response struct {
 | 
			
		||||
	configv1alpha1.ExploreResponse
 | 
			
		||||
	configv1alpha1.ResourceInterpreterResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Complete populates any fields that are yet to be set in
 | 
			
		||||
// the underlying ExploreResponse, It mutates the response.
 | 
			
		||||
// the underlying ResourceInterpreterResponse, It mutates the response.
 | 
			
		||||
func (r *Response) Complete(req Request) {
 | 
			
		||||
	r.UID = req.UID
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,9 +37,9 @@ func (r *Response) Complete(req Request) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handler can handle an ExploreRequest.
 | 
			
		||||
// Handler can handle an ResourceInterpreterRequest.
 | 
			
		||||
type Handler interface {
 | 
			
		||||
	// Handle yields a response to an ExploreRequest.
 | 
			
		||||
	// Handle yields a response to an ResourceInterpreterRequest.
 | 
			
		||||
	//
 | 
			
		||||
	// The supplied context is extracted from the received http.Request, allowing wrapping
 | 
			
		||||
	// http.Handlers to inject values into and control cancellation of downstream request processing.
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ func NewWebhook(handler Handler, decoder *Decoder) *Webhook {
 | 
			
		|||
	return &Webhook{handler: handler}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handle processes ExploreRequest.
 | 
			
		||||
// Handle processes ResourceInterpreterRequest.
 | 
			
		||||
func (wh *Webhook) Handle(ctx context.Context, req Request) Response {
 | 
			
		||||
	resp := wh.handler.Handle(ctx, req)
 | 
			
		||||
	resp.Complete(req)
 | 
			
		||||
		Loading…
	
		Reference in New Issue