feat: support promote dependent resources automatically

Signed-off-by: zhy76 <958474674@qq.com>
This commit is contained in:
zhy76 2023-11-21 15:56:05 +08:00
parent 1b2c6edfba
commit 682adff651
1 changed files with 264 additions and 14 deletions

View File

@ -16,17 +16,29 @@ import (
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/informers"
kubeclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/klog/v2"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/templates" "k8s.io/kubectl/pkg/util/templates"
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/get" "github.com/karmada-io/karmada/pkg/karmadactl/get"
"github.com/karmada-io/karmada/pkg/karmadactl/options" "github.com/karmada-io/karmada/pkg/karmadactl/options"
"github.com/karmada-io/karmada/pkg/karmadactl/util" "github.com/karmada-io/karmada/pkg/karmadactl/util"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/declarative"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook/request"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native/prune" "github.com/karmada-io/karmada/pkg/resourceinterpreter/default/native/prune"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/default/thirdparty"
u "github.com/karmada-io/karmada/pkg/util"
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
"github.com/karmada-io/karmada/pkg/util/gclient" "github.com/karmada-io/karmada/pkg/util/gclient"
"github.com/karmada-io/karmada/pkg/util/names" "github.com/karmada-io/karmada/pkg/util/names"
"github.com/karmada-io/karmada/pkg/util/restmapper" "github.com/karmada-io/karmada/pkg/util/restmapper"
@ -54,6 +66,9 @@ var (
# Promote secret(default/default-token) from cluster1 to Karmada # Promote secret(default/default-token) from cluster1 to Karmada
%[1]s promote secret default-token -n default -C cluster1 %[1]s promote secret default-token -n default -C cluster1
# Support to use '--dependencies=true' or '-d=true' to promote resource with its dependencies automatically, default to false
%[1]s promote deployment nginx -n default -C cluster1 -d=true
# Support to use '--cluster-kubeconfig' to specify the configuration of member cluster # Support to use '--cluster-kubeconfig' to specify the configuration of member cluster
%[1]s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig=<CLUSTER_KUBECONFIG_PATH> %[1]s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig=<CLUSTER_KUBECONFIG_PATH>
@ -111,6 +126,9 @@ type CommandPromoteOption struct {
// ClusterKubeConfig is the cluster's kubeconfig path. // ClusterKubeConfig is the cluster's kubeconfig path.
ClusterKubeConfig string ClusterKubeConfig string
// Deps tells if promote resource with its dependencies automatically, default to false
Deps bool
// DryRun tells if run the command in dry-run mode, without making any server requests. // DryRun tells if run the command in dry-run mode, without making any server requests.
DryRun bool DryRun bool
@ -149,6 +167,7 @@ func (o *CommandPromoteOption) AddFlags(flags *pflag.FlagSet) {
"Context name of legacy cluster in kubeconfig. Only works when there are multiple contexts in the kubeconfig.") "Context name of legacy cluster in kubeconfig. Only works when there are multiple contexts in the kubeconfig.")
flags.StringVar(&o.ClusterKubeConfig, "cluster-kubeconfig", "", flags.StringVar(&o.ClusterKubeConfig, "cluster-kubeconfig", "",
"Path of the legacy cluster's kubeconfig.") "Path of the legacy cluster's kubeconfig.")
flags.BoolVarP(&o.Deps, "dependencies", "d", false, "Promote resource with its dependencies automatically, default to false")
flags.BoolVar(&o.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.") flags.BoolVar(&o.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
} }
@ -249,10 +268,239 @@ func (o *CommandPromoteOption) Run(f util.Factory, args []string) error {
return fmt.Errorf("failed to get gvr from %q: %v", o.gvk, err) return fmt.Errorf("failed to get gvr from %q: %v", o.gvk, err)
} }
return o.promote(controlPlaneRestConfig, obj, gvr) if o.Deps {
err := o.promoteDeps(memberClusterFactory, obj, mapper, gvr, controlPlaneRestConfig)
if err != nil {
return fmt.Errorf("failed to promote dependencies of resource %q(%s/%s) automatically: %v", gvr, o.Namespace, o.name, err)
}
}
return o.promote(controlPlaneRestConfig, obj, gvr, o.Deps)
} }
func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured, gvr schema.GroupVersionResource) error { // revertPromotedDeps reverts promoted dependencies of the resource
func (o *CommandPromoteOption) revertPromotedDeps(memberClusterFactory cmdutil.Factory, dependencies []configv1alpha1.DependentObjectReference, mapper meta.RESTMapper, controlPlaneDynamicClient *dynamic.DynamicClient, index int) {
memberDynamicClient, err := memberClusterFactory.DynamicClient()
if err != nil {
klog.Errorf("revertPromotedDeps failed to get dynamic client of member cluster: %v", err)
return
}
for i := 0; i < index; i++ {
dep := dependencies[i]
depInfo, err := o.getObjInfo(memberClusterFactory, o.Cluster, []string{dep.Kind, dep.Name})
if err != nil {
klog.Errorf("revertPromotedDeps failed to get dependency %q(%s/%s) in cluster(%s): %v", dep.Kind, dep.Namespace, dep.Name, o.Cluster, err)
return
}
depObj := depInfo.Info.Object.(*unstructured.Unstructured)
depGvk := depObj.GetObjectKind().GroupVersionKind()
depGvr, err := restmapper.GetGroupVersionResource(mapper, depGvk)
if err != nil {
klog.Errorf("revertPromotedDeps failed to get dependency gvr from %q: %v", depGvk, err)
return
}
// remove the karmada label of dependency resource in member cluster to avoid deleting it when deleting the resource in control plane
u.RemoveLabels(depObj, workv1alpha1.WorkNamespaceLabel)
u.RemoveLabels(depObj, workv1alpha1.WorkNameLabel)
if len(depObj.GetNamespace()) != 0 {
// update the dependency resource in member cluster
_, err := memberDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Update(context.Background(), depObj, metav1.UpdateOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to update dependency resource %q(%s/%s) in member cluster: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
return
}
_, err = controlPlaneDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Get(context.Background(), depObj.GetName(), metav1.GetOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to get dependency resource %q(%s/%s) in control plane: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
return
}
// delete the dependency resource in control plane
err = controlPlaneDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Delete(context.Background(), depObj.GetName(), metav1.DeleteOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to delete dependency resource %q(%s/%s) in control plane: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
return
}
} else {
// update the dependency resource in member cluster
_, err := memberDynamicClient.Resource(depGvr).Update(context.Background(), depObj, metav1.UpdateOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to update dependency resource %q(%s) in member cluster: %v", depGvr, depObj.GetName(), err)
return
}
_, err = controlPlaneDynamicClient.Resource(depGvr).Get(context.TODO(), depObj.GetName(), metav1.GetOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to get dependency resource %q(%s) in control plane: %v", depGvr, depObj.GetName(), err)
return
}
// delete the dependency resource in control plane
err = controlPlaneDynamicClient.Resource(depGvr).Delete(context.Background(), depObj.GetName(), metav1.DeleteOptions{})
if err != nil {
klog.Errorf("revertPromotedDeps failed to delete dependency resource %q(%s) in control plane: %v", depGvr, depObj.GetName(), err)
return
}
}
fmt.Printf("Dependency resource %q(%s/%s) is reverted successfully\n", depGvr, depObj.GetNamespace(), depObj.GetName())
}
}
// doPromoteDeps promotes dependencies of the resource
func (o *CommandPromoteOption) doPromoteDeps(memberClusterFactory cmdutil.Factory, dependencies []configv1alpha1.DependentObjectReference, mapper meta.RESTMapper, config *rest.Config) error {
controlPlaneDynamicClient := dynamic.NewForConfigOrDie(config)
for i, dep := range dependencies {
depInfo, err := o.getObjInfo(memberClusterFactory, o.Cluster, []string{dep.Kind, dep.Name})
if err != nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to get dependency %q(%s/%s) in cluster(%s): %v", dep.Kind, dep.Namespace, dep.Name, o.Cluster, err)
}
depObj := depInfo.Info.Object.(*unstructured.Unstructured)
depGvk := depObj.GetObjectKind().GroupVersionKind()
depGvr, err := restmapper.GetGroupVersionResource(mapper, depGvk)
if err != nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to get dependency gvr from %q: %v", depGvk, err)
}
if err := preprocessResource(depObj); err != nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to preprocess resource %q(%s/%s) in control plane: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
}
if len(depObj.GetNamespace()) != 0 {
_, err := controlPlaneDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Get(context.TODO(), depObj.GetName(), metav1.GetOptions{})
if err == nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
// if dependency already exist in control plane, abort this dependency promotion
klog.Warningf("Dependency resource %q(%s/%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n",
depGvr, depObj.GetNamespace(), depObj.GetName())
return nil
}
if !apierrors.IsNotFound(err) {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to get dependency resource %q(%s/%s) in control plane: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
}
_, err = controlPlaneDynamicClient.Resource(depGvr).Namespace(depObj.GetNamespace()).Create(context.TODO(), depObj, metav1.CreateOptions{})
if err != nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to create dependency resource %q(%s/%s) in control plane: %v", depGvr, depObj.GetNamespace(), depObj.GetName(), err)
}
fmt.Printf("Dependency resource %q(%s/%s) is promoted successfully\n", depGvr, depObj.GetNamespace(), depObj.GetName())
} else {
_, err := controlPlaneDynamicClient.Resource(depGvr).Get(context.TODO(), depObj.GetName(), metav1.GetOptions{})
if err == nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
// if dependency already exist in control plane, abort this dependency promotion
fmt.Printf("Dependency resource %q(%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n",
depGvr, depObj.GetName())
return nil
}
if !apierrors.IsNotFound(err) {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to get dependency resource %q(%s) in control plane: %v", depGvr, depObj.GetName(), err)
}
_, err = controlPlaneDynamicClient.Resource(depGvr).Create(context.TODO(), depObj, metav1.CreateOptions{})
if err != nil {
o.revertPromotedDeps(memberClusterFactory, dependencies, mapper, controlPlaneDynamicClient, i)
return fmt.Errorf("failed to create dependency resource %q(%s) in control plane: %v", depGvr, depObj.GetName(), err)
}
fmt.Printf("Dependency resource %q(%s) is promoted successfully\n", depGvr, depObj.GetName())
}
}
return nil
}
func (o *CommandPromoteOption) promoteDeps(memberClusterFactory cmdutil.Factory, obj *unstructured.Unstructured, mapper meta.RESTMapper, gvr schema.GroupVersionResource, config *rest.Config) error {
if o.DryRun {
return nil
}
// create resource interpreter
stopCh := make(chan struct{})
defer close(stopCh)
dynamicClientSet := dynamic.NewForConfigOrDie(config)
controlPlaneInformerManager := genericmanager.NewSingleClusterInformerManager(dynamicClientSet, 0, stopCh)
controlPlaneKubeClientSet := kubeclientset.NewForConfigOrDie(config)
sharedFactory := informers.NewSharedInformerFactory(controlPlaneKubeClientSet, 0)
serviceLister := sharedFactory.Core().V1().Services().Lister()
sharedFactory.Start(stopCh)
sharedFactory.WaitForCacheSync(stopCh)
controlPlaneInformerManager.Start()
if sync := controlPlaneInformerManager.WaitForCacheSync(); sync == nil {
return fmt.Errorf("informer factory for cluster does not exist")
}
defaultInterpreter := native.NewDefaultInterpreter()
thirdpartyInterpreter := thirdparty.NewConfigurableInterpreter()
configurableInterpreter := declarative.NewConfigurableInterpreter(controlPlaneInformerManager)
customizedInterpreter, err := webhook.NewCustomizedInterpreter(controlPlaneInformerManager, serviceLister)
if err != nil {
return fmt.Errorf("failed to create customized interpreter: %v", err)
}
// check if the resource interpreter supports to interpret dependencies
if !defaultInterpreter.HookEnabled(obj.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretDependency) &&
!thirdpartyInterpreter.HookEnabled(obj.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretDependency) &&
!configurableInterpreter.HookEnabled(obj.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretDependency) &&
!customizedInterpreter.HookEnabled(obj.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretDependency) {
// if there is no interpreter configured, abort this dependency promotion but continue to promote the resource
klog.Warningf("there is no interpreter configured support to interpret dependencies")
return nil
}
// configurable interpreter has higher priority than customized interpreter
dependencies, hookEnabled, err := configurableInterpreter.GetDependencies(obj)
if err != nil {
return fmt.Errorf("configurable interpreter failed to get dependencies of resource %q(%s/%s): %v", gvr, obj.GetNamespace(), obj.GetName(), err)
}
if hookEnabled {
fmt.Printf("use configurable interpreter\n")
err := o.doPromoteDeps(memberClusterFactory, dependencies, mapper, config)
return err
}
// customized interpreter has higher priority than thirdparty interpreter
dependencies, hookEnabled, err = customizedInterpreter.GetDependencies(context.TODO(), &request.Attributes{
Operation: configv1alpha1.InterpreterOperationInterpretDependency,
Object: obj,
})
if err != nil {
return fmt.Errorf("customized interpreter failed to get dependencies of resource %q(%s/%s): %v", gvr, obj.GetNamespace(), obj.GetName(), err)
}
if hookEnabled {
fmt.Printf("use customized interpreter\n")
err := o.doPromoteDeps(memberClusterFactory, dependencies, mapper, config)
return err
}
// thirdparty interpreter has higher priority than default interpreter
dependencies, hookEnabled, err = thirdpartyInterpreter.GetDependencies(obj)
if err != nil {
return fmt.Errorf("thirdparty interpreter failed to get dependencies of resource %q(%s/%s): %v", gvr, obj.GetNamespace(), obj.GetName(), err)
}
if hookEnabled {
fmt.Printf("use thirdparty interpreter\n")
err := o.doPromoteDeps(memberClusterFactory, dependencies, mapper, config)
return err
}
// default interpreter
dependencies, err = defaultInterpreter.GetDependencies(obj)
if err != nil {
return fmt.Errorf("default interpreter failed to get dependencies of resource %q(%s/%s): %v", gvr, obj.GetNamespace(), obj.GetName(), err)
}
fmt.Printf("use default interpreter\n")
err = o.doPromoteDeps(memberClusterFactory, dependencies, mapper, config)
return err
}
func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured, gvr schema.GroupVersionResource, isDep bool) error {
if err := preprocessResource(obj); err != nil { if err := preprocessResource(obj); err != nil {
return fmt.Errorf("failed to preprocess resource %q(%s/%s) in control plane: %v", gvr, o.Namespace, o.name, err) return fmt.Errorf("failed to preprocess resource %q(%s/%s) in control plane: %v", gvr, o.Namespace, o.name, err)
} }
@ -275,7 +523,7 @@ func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj
if len(obj.GetNamespace()) == 0 { if len(obj.GetNamespace()) == 0 {
_, err := controlPlaneDynamicClient.Resource(gvr).Get(context.TODO(), o.name, metav1.GetOptions{}) _, err := controlPlaneDynamicClient.Resource(gvr).Get(context.TODO(), o.name, metav1.GetOptions{})
if err == nil { if err == nil {
fmt.Printf("Resource %q(%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n", klog.Warningf("Resource %q(%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n",
gvr, o.name) gvr, o.name)
return nil return nil
} }
@ -290,7 +538,7 @@ func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj
} }
if o.AutoCreatePolicy { if o.AutoCreatePolicy {
err = o.createClusterPropagationPolicy(karmadaClient, gvr) err = o.createClusterPropagationPolicy(karmadaClient, obj, gvr, isDep)
if err != nil { if err != nil {
return err return err
} }
@ -300,7 +548,7 @@ func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj
} else { } else {
_, err := controlPlaneDynamicClient.Resource(gvr).Namespace(o.Namespace).Get(context.TODO(), o.name, metav1.GetOptions{}) _, err := controlPlaneDynamicClient.Resource(gvr).Namespace(o.Namespace).Get(context.TODO(), o.name, metav1.GetOptions{})
if err == nil { if err == nil {
fmt.Printf("Resource %q(%s/%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n", klog.Warningf("Resource %q(%s/%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n",
gvr, o.Namespace, o.name) gvr, o.Namespace, o.name)
return nil return nil
} }
@ -315,7 +563,7 @@ func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj
} }
if o.AutoCreatePolicy { if o.AutoCreatePolicy {
err = o.createPropagationPolicy(karmadaClient, gvr) err = o.createPropagationPolicy(karmadaClient, gvr, isDep)
if err != nil { if err != nil {
return err return err
} }
@ -377,12 +625,12 @@ func (o *CommandPromoteOption) printObjectAndPolicy(obj *unstructured.Unstructur
policyName = o.PolicyName policyName = o.PolicyName
} }
if len(obj.GetNamespace()) == 0 { if len(obj.GetNamespace()) == 0 {
cpp := buildClusterPropagationPolicy(o.name, policyName, o.Cluster, gvr, o.gvk) cpp := buildClusterPropagationPolicy(o.name, policyName, o.Cluster, gvr, o.gvk, o.Deps)
if err = printer.PrintObj(cpp, os.Stdout); err != nil { if err = printer.PrintObj(cpp, os.Stdout); err != nil {
return fmt.Errorf("failed to print the ClusterPropagationPolicy. err: %v", err) return fmt.Errorf("failed to print the ClusterPropagationPolicy. err: %v", err)
} }
} else { } else {
pp := buildPropagationPolicy(o.name, policyName, o.Namespace, o.Cluster, gvr, o.gvk) pp := buildPropagationPolicy(o.name, policyName, o.Namespace, o.Cluster, gvr, o.gvk, o.Deps)
if err = printer.PrintObj(pp, os.Stdout); err != nil { if err = printer.PrintObj(pp, os.Stdout); err != nil {
return fmt.Errorf("failed to print the PropagationPolicy. err: %v", err) return fmt.Errorf("failed to print the PropagationPolicy. err: %v", err)
} }
@ -393,7 +641,7 @@ func (o *CommandPromoteOption) printObjectAndPolicy(obj *unstructured.Unstructur
} }
// createPropagationPolicy create PropagationPolicy in karmada control plane // createPropagationPolicy create PropagationPolicy in karmada control plane
func (o *CommandPromoteOption) createPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource) error { func (o *CommandPromoteOption) createPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource, isDep bool) error {
var policyName string var policyName string
if o.PolicyName == "" { if o.PolicyName == "" {
policyName = names.GeneratePolicyName(o.Namespace, o.name, o.gvk.String()) policyName = names.GeneratePolicyName(o.Namespace, o.name, o.gvk.String())
@ -403,7 +651,7 @@ func (o *CommandPromoteOption) createPropagationPolicy(karmadaClient *karmadacli
_, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Get(context.TODO(), policyName, metav1.GetOptions{}) _, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Get(context.TODO(), policyName, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) { if err != nil && apierrors.IsNotFound(err) {
pp := buildPropagationPolicy(o.name, policyName, o.Namespace, o.Cluster, gvr, o.gvk) pp := buildPropagationPolicy(o.name, policyName, o.Namespace, o.Cluster, gvr, o.gvk, isDep)
_, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Create(context.TODO(), pp, metav1.CreateOptions{}) _, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Create(context.TODO(), pp, metav1.CreateOptions{})
return err return err
@ -417,7 +665,7 @@ func (o *CommandPromoteOption) createPropagationPolicy(karmadaClient *karmadacli
} }
// createClusterPropagationPolicy create ClusterPropagationPolicy in karmada control plane // createClusterPropagationPolicy create ClusterPropagationPolicy in karmada control plane
func (o *CommandPromoteOption) createClusterPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource) error { func (o *CommandPromoteOption) createClusterPropagationPolicy(karmadaClient *karmadaclientset.Clientset, obj *unstructured.Unstructured, gvr schema.GroupVersionResource, isDep bool) error {
var policyName string var policyName string
if o.PolicyName == "" { if o.PolicyName == "" {
policyName = names.GeneratePolicyName("", o.name, o.gvk.String()) policyName = names.GeneratePolicyName("", o.name, o.gvk.String())
@ -427,7 +675,7 @@ func (o *CommandPromoteOption) createClusterPropagationPolicy(karmadaClient *kar
_, err := karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Get(context.TODO(), policyName, metav1.GetOptions{}) _, err := karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Get(context.TODO(), policyName, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) { if err != nil && apierrors.IsNotFound(err) {
cpp := buildClusterPropagationPolicy(o.name, policyName, o.Cluster, gvr, o.gvk) cpp := buildClusterPropagationPolicy(o.name, policyName, o.Cluster, gvr, o.gvk, isDep)
_, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Create(context.TODO(), cpp, metav1.CreateOptions{}) _, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Create(context.TODO(), cpp, metav1.CreateOptions{})
return err return err
@ -465,13 +713,14 @@ func addOverwriteAnnotation(obj *unstructured.Unstructured) {
} }
// buildPropagationPolicy build PropagationPolicy according to resource and cluster // buildPropagationPolicy build PropagationPolicy according to resource and cluster
func buildPropagationPolicy(resourceName, policyName, namespace, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind) *policyv1alpha1.PropagationPolicy { func buildPropagationPolicy(resourceName, policyName, namespace, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, deps bool) *policyv1alpha1.PropagationPolicy {
pp := &policyv1alpha1.PropagationPolicy{ pp := &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: policyName, Name: policyName,
Namespace: namespace, Namespace: namespace,
}, },
Spec: policyv1alpha1.PropagationSpec{ Spec: policyv1alpha1.PropagationSpec{
PropagateDeps: deps,
ResourceSelectors: []policyv1alpha1.ResourceSelector{ ResourceSelectors: []policyv1alpha1.ResourceSelector{
{ {
APIVersion: gvr.GroupVersion().String(), APIVersion: gvr.GroupVersion().String(),
@ -490,12 +739,13 @@ func buildPropagationPolicy(resourceName, policyName, namespace, cluster string,
} }
// buildClusterPropagationPolicy build ClusterPropagationPolicy according to resource and cluster // buildClusterPropagationPolicy build ClusterPropagationPolicy according to resource and cluster
func buildClusterPropagationPolicy(resourceName, policyName, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind) *policyv1alpha1.ClusterPropagationPolicy { func buildClusterPropagationPolicy(resourceName, policyName, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, deps bool) *policyv1alpha1.ClusterPropagationPolicy {
cpp := &policyv1alpha1.ClusterPropagationPolicy{ cpp := &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: policyName, Name: policyName,
}, },
Spec: policyv1alpha1.PropagationSpec{ Spec: policyv1alpha1.PropagationSpec{
PropagateDeps: deps,
ResourceSelectors: []policyv1alpha1.ResourceSelector{ ResourceSelectors: []policyv1alpha1.ResourceSelector{
{ {
APIVersion: gvr.GroupVersion().String(), APIVersion: gvr.GroupVersion().String(),