diff --git a/pkg/karmadactl/get.go b/pkg/karmadactl/get.go index 7ba78987d..a8d471f1c 100644 --- a/pkg/karmadactl/get.go +++ b/pkg/karmadactl/get.go @@ -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) diff --git a/pkg/karmadactl/karmadactl.go b/pkg/karmadactl/karmadactl.go index a636be367..1db4309cb 100644 --- a/pkg/karmadactl/karmadactl.go +++ b/pkg/karmadactl/karmadactl.go @@ -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), }, }, } diff --git a/pkg/karmadactl/promote.go b/pkg/karmadactl/promote.go index bb5a42491..841722188 100644 --- a/pkg/karmadactl/promote.go +++ b/pkg/karmadactl/promote.go @@ -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}, }, }, }, diff --git a/test/e2e/karmadactl_test.go b/test/e2e/karmadactl_test.go index b29a0a1bc..70a93f72f 100644 --- a/test/e2e/karmadactl_test.go +++ b/test/e2e/karmadactl_test.go @@ -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()) })