feat: support promote dependent resources automatically
Signed-off-by: zhy76 <958474674@qq.com>
This commit is contained in:
parent
1b2c6edfba
commit
682adff651
|
@ -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(),
|
||||||
|
|
Loading…
Reference in New Issue