Merge pull request #2694 from lonelyCZ/pr-promote-factory

karmadactl promote uses factory to access cluster
This commit is contained in:
karmada-bot 2022-11-07 09:56:48 +08:00 committed by GitHub
commit 052de02155
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 143 additions and 243 deletions

View File

@ -33,7 +33,6 @@ import (
"k8s.io/kubectl/pkg/util/templates"
utilpointer "k8s.io/utils/pointer"
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/util"
@ -295,18 +294,18 @@ func (g *CommandGetOptions) Run(f util.Factory, cmd *cobra.Command, args []strin
return err
}
clusterInfos, err := getClusterInKarmadaForClient(gclient)
if err != nil {
return fmt.Errorf("method getClusterInKarmadaForClient get cluster info in karmada failed, err is: %w", err)
}
if err := g.getRBInKarmada(gclient); err != nil {
return err
}
if len(g.Clusters) <= 0 {
for c := range clusterInfos {
g.Clusters = append(g.Clusters, c)
clusterList, err := gclient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to list all member clusters in control plane, err: %w", err)
}
for i := range clusterList.Items {
g.Clusters = append(g.Clusters, clusterList.Items[i].Name)
}
}
@ -877,33 +876,6 @@ func shouldGetNewPrinterForMapping(printer printers.ResourcePrinter, lastMapping
return printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource
}
// ClusterInfo Information about the member in the karmada cluster.
type ClusterInfo struct {
KubeConfig string
Context string
APIEndpoint string
ClusterSyncMode clusterv1alpha1.ClusterSyncMode
}
func getFactory(clusterName string, clusterInfos map[string]*ClusterInfo, namespace string) cmdutil.Factory {
kubeConfigFlags := NewConfigFlags(true).WithDeprecatedPasswordFlag()
// Build member cluster kubeConfigFlags
kubeConfigFlags.APIServer = stringptr(clusterInfos[clusterName].APIEndpoint)
// Use kubeconfig to access member cluster
kubeConfigFlags.KubeConfig = stringptr(clusterInfos[clusterName].KubeConfig)
kubeConfigFlags.Context = stringptr(clusterInfos[clusterName].Context)
kubeConfigFlags.usePersistentConfig = true
if namespace != "" {
kubeConfigFlags.Namespace = stringptr(namespace)
}
matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
return cmdutil.NewFactory(matchVersionKubeConfigFlags)
}
func (g *CommandGetOptions) transformRequests(req *rest.Request) {
if !g.ServerPrint || !g.IsHumanReadablePrinter {
return
@ -961,44 +933,6 @@ func (g *CommandGetOptions) getRBInKarmada(gclient karmadaclientset.Interface) e
return nil
}
// getClusterInKarmadaForClient get cluster info in karmada cluster
func getClusterInKarmadaForClient(gclient karmadaclientset.Interface) (map[string]*ClusterInfo, error) {
clusterList, err := gclient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
clusterInfos := make(map[string]*ClusterInfo, len(clusterList.Items))
for i := range clusterList.Items {
cluster := &ClusterInfo{
APIEndpoint: clusterList.Items[i].Spec.APIEndpoint,
ClusterSyncMode: clusterList.Items[i].Spec.SyncMode,
}
clusterInfos[clusterList.Items[i].GetName()] = cluster
}
return clusterInfos, nil
}
// getClusterInKarmada get cluster info in karmada cluster
func getClusterInKarmada(client *rest.Config, clusterInfos map[string]*ClusterInfo) error {
clusterList := &clusterv1alpha1.ClusterList{}
gClient, err := gclient.NewForConfig(client)
if err != nil {
return err
}
if err = gClient.List(context.TODO(), clusterList); err != nil {
return err
}
for i := range clusterList.Items {
cluster := &ClusterInfo{
APIEndpoint: clusterList.Items[i].Spec.APIEndpoint,
ClusterSyncMode: clusterList.Items[i].Spec.SyncMode,
}
clusterInfos[clusterList.Items[i].GetName()] = cluster
}
return nil
}
func getRBKey(gvk schema.GroupVersionKind, row metav1.TableRow, cluster string) string {
resourceName, _ := row.Cells[0].(string)
rbKey := names.GenerateBindingName(gvk.Kind, resourceName)

View File

@ -96,7 +96,7 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
Message: "Advanced Commands:",
Commands: []*cobra.Command{
NewCmdApply(f, parentCommand, ioStreams),
NewCmdPromote(karmadaConfig, parentCommand),
NewCmdPromote(f, parentCommand),
},
},
}

View File

@ -23,7 +23,6 @@ import (
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
"github.com/karmada-io/karmada/pkg/karmadactl/options"
"github.com/karmada-io/karmada/pkg/karmadactl/util"
"github.com/karmada-io/karmada/pkg/resourceinterpreter/defaultinterpreter/prune"
"github.com/karmada-io/karmada/pkg/util/gclient"
@ -55,7 +54,7 @@ var (
)
// NewCmdPromote defines the `promote` command that promote resources from legacy clusters
func NewCmdPromote(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command {
func NewCmdPromote(f util.Factory, parentCommand string) *cobra.Command {
opts := CommandPromoteOption{}
opts.JSONYamlPrintFlags = genericclioptions.NewJSONYamlPrintFlags()
@ -67,13 +66,13 @@ func NewCmdPromote(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Com
SilenceUsage: true,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error {
if err := opts.Complete(args); err != nil {
if err := opts.Complete(f, args); err != nil {
return err
}
if err := opts.Validate(); err != nil {
return err
}
if err := RunPromote(karmadaConfig, opts, args); err != nil {
if err := opts.Run(f, args); err != nil {
return err
}
return nil
@ -86,13 +85,14 @@ func NewCmdPromote(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Com
flag := cmd.Flags()
opts.AddFlags(flag)
flag.StringVar(defaultConfigFlags.KubeConfig, "kubeconfig", *defaultConfigFlags.KubeConfig, "Path to the kubeconfig file to use for CLI requests.")
flag.StringVar(defaultConfigFlags.Context, "karmada-context", *defaultConfigFlags.Context, "The name of the kubeconfig context to use")
return cmd
}
// CommandPromoteOption holds all command options for promote
type CommandPromoteOption struct {
options.GlobalCommandOptions
// Cluster is the name of legacy cluster
Cluster string
@ -121,11 +121,9 @@ type CommandPromoteOption struct {
// AddFlags adds flags to the specified FlagSet.
func (o *CommandPromoteOption) AddFlags(flags *pflag.FlagSet) {
o.GlobalCommandOptions.AddFlags(flags)
flags.StringVarP(&o.OutputFormat, "output", "o", "", "Output format. One of: json|yaml")
flags.StringVarP(&o.Namespace, "namespace", "n", "default", "-n=namespace or -n namespace")
flags.StringVarP(&o.Namespace, "namespace", "n", o.Namespace, "If present, the namespace scope for this CLI request")
flags.StringVarP(&o.Cluster, "cluster", "C", "", "the name of legacy cluster (eg -C=member1)")
flags.StringVar(&o.ClusterContext, "cluster-context", "",
"Context name of legacy cluster in kubeconfig. Only works when there are multiple contexts in the kubeconfig.")
@ -135,7 +133,9 @@ func (o *CommandPromoteOption) AddFlags(flags *pflag.FlagSet) {
}
// Complete ensures that options are valid and marshals them if necessary
func (o *CommandPromoteOption) Complete(args []string) error {
func (o *CommandPromoteOption) Complete(f util.Factory, args []string) error {
var err error
if len(args) != 2 {
return fmt.Errorf("incorrect command format, please use correct command format")
}
@ -159,6 +159,18 @@ func (o *CommandPromoteOption) Complete(args []string) error {
}
}
if o.Namespace == "" {
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return fmt.Errorf("failed to get namespace from Factory. error: %w", err)
}
}
// If '--cluster-context' not specified, take the cluster name as the context.
if len(o.ClusterContext) == 0 {
o.ClusterContext = o.Cluster
}
return nil
}
@ -172,81 +184,67 @@ func (o *CommandPromoteOption) Validate() error {
return fmt.Errorf("output format is only one of json and yaml")
}
// If '--cluster-context' not specified, take the cluster name as the context.
if len(o.ClusterContext) == 0 {
o.ClusterContext = o.Cluster
}
return nil
}
// RunPromote promote resources from legacy clusters
func RunPromote(karmadaConfig KarmadaConfig, opts CommandPromoteOption, args []string) error {
// Get control plane karmada-apiserver client
controlPlaneRestConfig, err := karmadaConfig.GetRestConfig(opts.KarmadaContext, opts.KubeConfig)
if err != nil {
return fmt.Errorf("failed to get control plane rest config. context: %s, kubeconfig: %s, error: %v",
opts.KarmadaContext, opts.KubeConfig, err)
}
// Run promote resources from legacy clusters
func (o *CommandPromoteOption) Run(f util.Factory, args []string) error {
var memberClusterFactory cmdutil.Factory
var err error
clusterInfos := make(map[string]*ClusterInfo)
if err := getClusterInKarmada(controlPlaneRestConfig, clusterInfos); err != nil {
return fmt.Errorf("failed to get cluster info in karmada control plane. err: %v", err)
}
if _, exist := clusterInfos[opts.Cluster]; !exist {
return fmt.Errorf("cluster(%s) does't exist in karmada control plane", opts.Cluster)
}
var f cmdutil.Factory
if opts.ClusterKubeConfig != "" {
if o.ClusterKubeConfig != "" {
kubeConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
kubeConfigFlags.KubeConfig = &opts.ClusterKubeConfig
kubeConfigFlags.Context = &opts.ClusterContext
kubeConfigFlags.KubeConfig = &o.ClusterKubeConfig
kubeConfigFlags.Context = &o.ClusterContext
f = cmdutil.NewFactory(kubeConfigFlags)
memberClusterFactory = cmdutil.NewFactory(kubeConfigFlags)
} else {
opts.setClusterProxyInfo(controlPlaneRestConfig, opts.Cluster, clusterInfos)
f = getFactory(opts.Cluster, clusterInfos, "")
memberClusterFactory, err = f.FactoryForMemberCluster(o.Cluster)
if err != nil {
return fmt.Errorf("failed to get Factory of the member cluster. err: %w", err)
}
}
objInfo, err := opts.getObjInfo(f, opts.Cluster, args)
objInfo, err := o.getObjInfo(memberClusterFactory, o.Cluster, args)
if err != nil {
return fmt.Errorf("failed to get resource in cluster(%s). err: %v", opts.Cluster, err)
return fmt.Errorf("failed to get resource in cluster(%s). err: %w", o.Cluster, err)
}
obj := objInfo.Info.Object.(*unstructured.Unstructured)
opts.gvk = obj.GetObjectKind().GroupVersionKind()
o.gvk = obj.GetObjectKind().GroupVersionKind()
controlPlaneRestConfig, err := f.ToRESTConfig()
if err != nil {
return fmt.Errorf("failed to get control plane rest config. err: %w", err)
}
mapper, err := restmapper.MapperProvider(controlPlaneRestConfig)
if err != nil {
return fmt.Errorf("failed to create restmapper: %v", err)
}
gvr, err := restmapper.GetGroupVersionResource(mapper, opts.gvk)
gvr, err := restmapper.GetGroupVersionResource(mapper, o.gvk)
if err != nil {
return fmt.Errorf("failed to get gvr from %q: %v", opts.gvk, err)
return fmt.Errorf("failed to get gvr from %q: %v", o.gvk, err)
}
return promote(controlPlaneRestConfig, obj, gvr, opts)
return o.promote(controlPlaneRestConfig, obj, gvr)
}
func promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured, gvr schema.GroupVersionResource, opts CommandPromoteOption) error {
func (o *CommandPromoteOption) promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured, gvr schema.GroupVersionResource) error {
if err := preprocessResource(obj); err != nil {
return fmt.Errorf("failed to preprocess resource %q(%s/%s) in control plane: %v", gvr, opts.Namespace, opts.name, err)
return fmt.Errorf("failed to preprocess resource %q(%s/%s) in control plane: %v", gvr, o.Namespace, o.name, err)
}
if opts.OutputFormat != "" {
if o.OutputFormat != "" {
// only print the resource template and Policy
err := printObjectAndPolicy(obj, gvr, opts)
err := o.printObjectAndPolicy(obj, gvr)
return err
}
if opts.DryRun {
if o.DryRun {
return nil
}
@ -255,51 +253,51 @@ func promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured
karmadaClient := karmadaclientset.NewForConfigOrDie(controlPlaneRestConfig)
if len(obj.GetNamespace()) == 0 {
_, err := controlPlaneDynamicClient.Resource(gvr).Get(context.TODO(), opts.name, metav1.GetOptions{})
_, err := controlPlaneDynamicClient.Resource(gvr).Get(context.TODO(), o.name, metav1.GetOptions{})
if err == nil {
fmt.Printf("Resource %q(%s) already exist in karmada control plane, you can edit PropagationPolicy and OverridePolicy to propagate it\n",
gvr, opts.name)
gvr, o.name)
return nil
}
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get resource %q(%s) in control plane: %v", gvr, opts.name, err)
return fmt.Errorf("failed to get resource %q(%s) in control plane: %v", gvr, o.name, err)
}
_, err = controlPlaneDynamicClient.Resource(gvr).Create(context.TODO(), obj, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("failed to create resource %q(%s) in control plane: %v", gvr, opts.name, err)
return fmt.Errorf("failed to create resource %q(%s) in control plane: %v", gvr, o.name, err)
}
err = createOrUpdateClusterPropagationPolicy(karmadaClient, gvr, opts)
err = o.createClusterPropagationPolicy(karmadaClient, gvr)
if err != nil {
return err
}
fmt.Printf("Resource %q(%s) is promoted successfully\n", gvr, opts.name)
fmt.Printf("Resource %q(%s) is promoted successfully\n", gvr, o.name)
} else {
_, err := controlPlaneDynamicClient.Resource(gvr).Namespace(opts.Namespace).Get(context.TODO(), opts.name, metav1.GetOptions{})
_, err := controlPlaneDynamicClient.Resource(gvr).Namespace(o.Namespace).Get(context.TODO(), o.name, metav1.GetOptions{})
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",
gvr, opts.Namespace, opts.name)
gvr, o.Namespace, o.name)
return nil
}
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get resource %q(%s/%s) in control plane: %v", gvr, opts.Namespace, opts.name, err)
return fmt.Errorf("failed to get resource %q(%s/%s) in control plane: %v", gvr, o.Namespace, o.name, err)
}
_, err = controlPlaneDynamicClient.Resource(gvr).Namespace(opts.Namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
_, err = controlPlaneDynamicClient.Resource(gvr).Namespace(o.Namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("failed to create resource %q(%s/%s) in control plane: %v", gvr, opts.Namespace, opts.name, err)
return fmt.Errorf("failed to create resource %q(%s/%s) in control plane: %v", gvr, o.Namespace, o.name, err)
}
err = createOrUpdatePropagationPolicy(karmadaClient, gvr, opts)
err = o.createPropagationPolicy(karmadaClient, gvr)
if err != nil {
return err
}
fmt.Printf("Resource %q(%s/%s) is promoted successfully\n", gvr, opts.Namespace, opts.name)
fmt.Printf("Resource %q(%s/%s) is promoted successfully\n", gvr, o.Namespace, o.name)
}
return nil
@ -307,12 +305,11 @@ func promote(controlPlaneRestConfig *rest.Config, obj *unstructured.Unstructured
// getObjInfo get obj info in member cluster
func (o *CommandPromoteOption) getObjInfo(f cmdutil.Factory, cluster string, args []string) (*Obj, error) {
chunkSize := int64(500)
r := f.NewBuilder().
Unstructured().
NamespaceParam(o.Namespace).
FilenameParam(false, &o.FilenameOptions).
RequestChunksOf(chunkSize).
RequestChunksOf(500).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().
Latest().
@ -338,24 +335,9 @@ func (o *CommandPromoteOption) getObjInfo(f cmdutil.Factory, cluster string, arg
return obj, nil
}
// setClusterProxyInfo set proxy information of cluster
func (o *CommandPromoteOption) setClusterProxyInfo(karmadaRestConfig *rest.Config, name string, clusterInfos map[string]*ClusterInfo) {
clusterInfos[name].APIEndpoint = karmadaRestConfig.Host + fmt.Sprintf(proxyURL, name)
clusterInfos[name].KubeConfig = o.KubeConfig
clusterInfos[name].Context = o.KarmadaContext
if clusterInfos[name].KubeConfig == "" {
env := os.Getenv("KUBECONFIG")
if env != "" {
clusterInfos[name].KubeConfig = env
} else {
clusterInfos[name].KubeConfig = defaultKubeConfig
}
}
}
// printObjectAndPolicy print the converted resource
func printObjectAndPolicy(obj *unstructured.Unstructured, gvr schema.GroupVersionResource, opts CommandPromoteOption) error {
printer, err := opts.Printer(nil, nil, false, false)
func (o *CommandPromoteOption) printObjectAndPolicy(obj *unstructured.Unstructured, gvr schema.GroupVersionResource) error {
printer, err := o.Printer(nil, nil, false, false)
if err != nil {
return fmt.Errorf("failed to initialize k8s printer. err: %v", err)
}
@ -365,12 +347,12 @@ func printObjectAndPolicy(obj *unstructured.Unstructured, gvr schema.GroupVersio
}
if len(obj.GetNamespace()) == 0 {
cpp := buildClusterPropagationPolicy(gvr, opts)
cpp := buildClusterPropagationPolicy(o.name, o.Cluster, gvr, o.gvk)
if err = printer.PrintObj(cpp, os.Stdout); err != nil {
return fmt.Errorf("failed to print the ClusterPropagationPolicy. err: %v", err)
}
} else {
pp := buildPropagationPolicy(gvr, opts)
pp := buildPropagationPolicy(o.name, o.Namespace, o.Cluster, gvr, o.gvk)
if err = printer.PrintObj(pp, os.Stdout); err != nil {
return fmt.Errorf("failed to print the PropagationPolicy. err: %v", err)
}
@ -379,6 +361,44 @@ func printObjectAndPolicy(obj *unstructured.Unstructured, gvr schema.GroupVersio
return nil
}
// createPropagationPolicy create PropagationPolicy in karmada control plane
func (o *CommandPromoteOption) createPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource) error {
name := names.GeneratePolicyName(o.Namespace, o.name, o.gvk.String())
_, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) {
pp := buildPropagationPolicy(o.name, o.Namespace, o.Cluster, gvr, o.gvk)
_, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(o.Namespace).Create(context.TODO(), pp, metav1.CreateOptions{})
return err
}
if err != nil {
return fmt.Errorf("failed to get PropagationPolicy(%s/%s) in control plane: %v", o.Namespace, name, err)
}
// PropagationPolicy already exists, not to create it
return fmt.Errorf("the PropagationPolicy(%s/%s) already exist, please edit it to propagate resource", o.Namespace, name)
}
// createClusterPropagationPolicy create ClusterPropagationPolicy in karmada control plane
func (o *CommandPromoteOption) createClusterPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource) error {
name := names.GeneratePolicyName("", o.name, o.gvk.String())
_, err := karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Get(context.TODO(), name, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) {
cpp := buildClusterPropagationPolicy(o.name, o.Cluster, gvr, o.gvk)
_, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Create(context.TODO(), cpp, metav1.CreateOptions{})
return err
}
if err != nil {
return fmt.Errorf("failed to get ClusterPropagationPolicy(%s) in control plane: %v", name, err)
}
// ClusterPropagationPolicy already exists, not to create it
return fmt.Errorf("the ClusterPropagationPolicy(%s) already exist, please edit it to propagate resource", name)
}
// preprocessResource delete redundant fields to convert resource as template
func preprocessResource(obj *unstructured.Unstructured) error {
// remove fields that generated by kube-apiserver and no need(or can't) propagate to member clusters.
@ -403,64 +423,26 @@ func addOverwriteAnnotation(obj *unstructured.Unstructured) {
}
}
// createOrUpdatePropagationPolicy create PropagationPolicy in karmada control plane
func createOrUpdatePropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource, opts CommandPromoteOption) error {
name := names.GeneratePolicyName(opts.Namespace, opts.name, opts.gvk.String())
_, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(opts.Namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) {
pp := buildPropagationPolicy(gvr, opts)
_, err = karmadaClient.PolicyV1alpha1().PropagationPolicies(opts.Namespace).Create(context.TODO(), pp, metav1.CreateOptions{})
return err
}
if err != nil {
return fmt.Errorf("failed to get PropagationPolicy(%s/%s) in control plane: %v", opts.Namespace, name, err)
}
// PropagationPolicy already exists, not to create it
return fmt.Errorf("the PropagationPolicy(%s/%s) already exist, please edit it to propagate resource", opts.Namespace, name)
}
// createOrUpdateClusterPropagationPolicy create ClusterPropagationPolicy in karmada control plane
func createOrUpdateClusterPropagationPolicy(karmadaClient *karmadaclientset.Clientset, gvr schema.GroupVersionResource, opts CommandPromoteOption) error {
name := names.GeneratePolicyName("", opts.name, opts.gvk.String())
_, err := karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Get(context.TODO(), name, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) {
cpp := buildClusterPropagationPolicy(gvr, opts)
_, err = karmadaClient.PolicyV1alpha1().ClusterPropagationPolicies().Create(context.TODO(), cpp, metav1.CreateOptions{})
return err
}
if err != nil {
return fmt.Errorf("failed to get ClusterPropagationPolicy(%s) in control plane: %v", name, err)
}
// ClusterPropagationPolicy already exists, not to create it
return fmt.Errorf("the ClusterPropagationPolicy(%s) already exist, please edit it to propagate resource", name)
}
// buildPropagationPolicy build PropagationPolicy according to resource and cluster
func buildPropagationPolicy(gvr schema.GroupVersionResource, opts CommandPromoteOption) *policyv1alpha1.PropagationPolicy {
name := names.GeneratePolicyName(opts.Namespace, opts.name, opts.gvk.String())
func buildPropagationPolicy(resourceName, namespace, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind) *policyv1alpha1.PropagationPolicy {
policyName := names.GeneratePolicyName(namespace, resourceName, gvk.String())
pp := &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: opts.Namespace,
Name: policyName,
Namespace: namespace,
},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: gvr.GroupVersion().String(),
Kind: opts.gvk.Kind,
Name: opts.name,
Kind: gvk.Kind,
Name: resourceName,
},
},
Placement: policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{opts.Cluster},
ClusterNames: []string{cluster},
},
},
},
@ -470,24 +452,24 @@ func buildPropagationPolicy(gvr schema.GroupVersionResource, opts CommandPromote
}
// buildClusterPropagationPolicy build ClusterPropagationPolicy according to resource and cluster
func buildClusterPropagationPolicy(gvr schema.GroupVersionResource, opts CommandPromoteOption) *policyv1alpha1.ClusterPropagationPolicy {
name := names.GeneratePolicyName("", opts.name, opts.gvk.String())
func buildClusterPropagationPolicy(resourceName, cluster string, gvr schema.GroupVersionResource, gvk schema.GroupVersionKind) *policyv1alpha1.ClusterPropagationPolicy {
policyName := names.GeneratePolicyName("", resourceName, gvk.String())
cpp := &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Name: policyName,
},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: gvr.GroupVersion().String(),
Kind: opts.gvk.Kind,
Name: opts.name,
Kind: gvk.Kind,
Name: resourceName,
},
},
Placement: policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{opts.Cluster},
ClusterNames: []string{cluster},
},
},
},

View File

@ -33,14 +33,16 @@ import (
)
var _ = ginkgo.Describe("Karmadactl promote testing", func() {
var karmadaConfig karmadactl.KarmadaConfig
var member1 string
var member1Client kubernetes.Interface
var f cmdutil.Factory
ginkgo.BeforeEach(func() {
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
member1 = "member1"
member1Client = framework.GetClusterClient(member1)
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
defaultConfigFlags.Context = &karmadaContext
f = cmdutil.NewFactory(defaultConfigFlags)
})
ginkgo.Context("Test promoting namespaced resource: deployment", func() {
@ -85,18 +87,15 @@ var _ = ginkgo.Describe("Karmadactl promote testing", func() {
// Step 2, promote namespace used by the deployment from member1 to karmada
ginkgo.By(fmt.Sprintf("Promoting namespace %s from member: %s to karmada control plane", deploymentNamespace, member1), func() {
namespaceOpts = karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Cluster: member1,
}
args := []string{"namespace", deploymentNamespace}
// init args: place namespace name to CommandPromoteOption.name
err := namespaceOpts.Complete(args)
err := namespaceOpts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
// use karmadactl to promote a namespace from member1
err = karmadactl.RunPromote(karmadaConfig, namespaceOpts, args)
err = namespaceOpts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
framework.WaitNamespacePresentOnClusterByClient(kubeClient, deploymentNamespace)
@ -105,19 +104,16 @@ var _ = ginkgo.Describe("Karmadactl promote testing", func() {
// Step 3, promote deployment from cluster member1 to karmada
ginkgo.By(fmt.Sprintf("Promoting deployment %s from member: %s to karmada", deploymentName, member1), func() {
deploymentOpts = karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Namespace: deploymentNamespace,
Cluster: member1,
}
args := []string{"deployment", deploymentName}
// init args: place deployment name to CommandPromoteOption.name
err := deploymentOpts.Complete(args)
err := deploymentOpts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
// use karmadactl to promote a deployment from member1
err = karmadactl.RunPromote(karmadaConfig, deploymentOpts, args)
err = deploymentOpts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})
@ -196,35 +192,29 @@ var _ = ginkgo.Describe("Karmadactl promote testing", func() {
// Step2, promote clusterrole and clusterrolebinding from member1
ginkgo.By(fmt.Sprintf("Promoting clusterrole %s and clusterrolebindings %s from member to karmada", clusterRoleName, clusterRoleBindingName), func() {
clusterRoleOpts = karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Cluster: member1,
}
args := []string{"clusterrole", clusterRoleName}
// init args: place clusterrole name to CommandPromoteOption.name
err := clusterRoleOpts.Complete(args)
err := clusterRoleOpts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
// use karmadactl to promote clusterrole from member1
err = karmadactl.RunPromote(karmadaConfig, clusterRoleOpts, args)
err = clusterRoleOpts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
clusterRoleBindingOpts = karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Cluster: member1,
}
args = []string{"clusterrolebinding", clusterRoleBindingName}
// init args: place clusterrolebinding name to CommandPromoteOption.name
err = clusterRoleBindingOpts.Complete(args)
err = clusterRoleBindingOpts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
// use karmadactl to promote clusterrolebinding from member1
err = karmadactl.RunPromote(karmadaConfig, clusterRoleBindingOpts, args)
err = clusterRoleBindingOpts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})
@ -267,16 +257,13 @@ var _ = ginkgo.Describe("Karmadactl promote testing", func() {
ginkgo.By(fmt.Sprintf("Promoting namespace %s from member: %s to karmada control plane", serviceNamespace, member1), func() {
opts := karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Cluster: member1,
}
args := []string{"namespace", serviceNamespace}
err := opts.Complete(args)
err := opts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
err = karmadactl.RunPromote(karmadaConfig, opts, args)
err = opts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
framework.WaitNamespacePresentOnClusterByClient(kubeClient, serviceNamespace)
@ -284,17 +271,14 @@ var _ = ginkgo.Describe("Karmadactl promote testing", func() {
ginkgo.By(fmt.Sprintf("Promoting service %s from member: %s to karmada control plane", serviceName, member1), func() {
opts := karmadactl.CommandPromoteOption{
GlobalCommandOptions: options.GlobalCommandOptions{
KarmadaContext: karmadaContext,
},
Namespace: serviceNamespace,
Cluster: member1,
}
args := []string{"service", serviceName}
err := opts.Complete(args)
err := opts.Complete(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
err = karmadactl.RunPromote(karmadaConfig, opts, args)
err = opts.Run(f, args)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})