Merge pull request #2752 from lonelyCZ/pr-join-factory
karmadactl join/unjoin use factory to access control plane
This commit is contained in:
commit
abad935461
|
@ -12,7 +12,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/dynamic"
|
||||
kubeclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/term"
|
||||
"k8s.io/klog/v2"
|
||||
|
@ -30,7 +29,7 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/controllers/mcs"
|
||||
"github.com/karmada-io/karmada/pkg/controllers/status"
|
||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter"
|
||||
"github.com/karmada-io/karmada/pkg/sharedcli"
|
||||
"github.com/karmada-io/karmada/pkg/sharedcli/klogflag"
|
||||
|
@ -51,7 +50,6 @@ import (
|
|||
// NewAgentCommand creates a *cobra.Command object with default parameters
|
||||
func NewAgentCommand(ctx context.Context) *cobra.Command {
|
||||
opts := options.NewOptions()
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "karmada-agent",
|
||||
|
@ -63,7 +61,7 @@ cluster and manifests to the Karmada control plane.`,
|
|||
if errs := opts.Validate(); len(errs) != 0 {
|
||||
return errs.ToAggregate()
|
||||
}
|
||||
if err := run(ctx, karmadaConfig, opts); err != nil {
|
||||
if err := run(ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -111,12 +109,12 @@ func init() {
|
|||
controllers["certRotation"] = startCertRotationController
|
||||
}
|
||||
|
||||
func run(ctx context.Context, karmadaConfig karmadactl.KarmadaConfig, opts *options.Options) error {
|
||||
func run(ctx context.Context, opts *options.Options) error {
|
||||
klog.Infof("karmada-agent version: %s", version.Get())
|
||||
|
||||
profileflag.ListenAndServe(opts.ProfileOpts)
|
||||
|
||||
controlPlaneRestConfig, err := karmadaConfig.GetRestConfig(opts.KarmadaContext, opts.KarmadaKubeConfig)
|
||||
controlPlaneRestConfig, err := apiclient.RestConfig(opts.KarmadaContext, opts.KarmadaKubeConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error building kubeconfig of karmada control plane: %w", err)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
kubeclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/term"
|
||||
"k8s.io/klog/v2"
|
||||
|
@ -43,7 +42,7 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/dependenciesdistributor"
|
||||
"github.com/karmada-io/karmada/pkg/detector"
|
||||
"github.com/karmada-io/karmada/pkg/features"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter"
|
||||
"github.com/karmada-io/karmada/pkg/sharedcli"
|
||||
"github.com/karmada-io/karmada/pkg/sharedcli/klogflag"
|
||||
|
@ -603,8 +602,7 @@ func setupClusterAPIClusterDetector(mgr controllerruntime.Manager, opts *options
|
|||
|
||||
klog.Infof("Begin to setup cluster-api cluster detector")
|
||||
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
clusterAPIRestConfig, err := karmadaConfig.GetRestConfig(opts.ClusterAPIContext, opts.ClusterAPIKubeconfig)
|
||||
clusterAPIRestConfig, err := apiclient.RestConfig(opts.ClusterAPIContext, opts.ClusterAPIKubeconfig)
|
||||
if err != nil {
|
||||
klog.Fatalf("Failed to get cluster-api management cluster rest config. context: %s, kubeconfig: %s, err: %v", opts.ClusterAPIContext, opts.ClusterAPIKubeconfig, err)
|
||||
}
|
||||
|
@ -615,7 +613,6 @@ func setupClusterAPIClusterDetector(mgr controllerruntime.Manager, opts *options
|
|||
}
|
||||
|
||||
clusterAPIClusterDetector := &clusterapi.ClusterDetector{
|
||||
KarmadaConfig: karmadaConfig,
|
||||
ControllerPlaneConfig: mgr.GetConfig(),
|
||||
ClusterAPIConfig: clusterAPIRestConfig,
|
||||
ClusterAPIClient: clusterAPIClient,
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/pkg/util/fedinformer"
|
||||
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
|
||||
|
@ -41,7 +42,6 @@ var (
|
|||
|
||||
// ClusterDetector is a cluster watcher which watched cluster object in cluster-api management cluster and reconcile the events.
|
||||
type ClusterDetector struct {
|
||||
KarmadaConfig karmadactl.KarmadaConfig
|
||||
ControllerPlaneConfig *rest.Config
|
||||
ClusterAPIConfig *rest.Config
|
||||
ClusterAPIClient client.Client
|
||||
|
@ -183,7 +183,7 @@ func (d *ClusterDetector) joinClusterAPICluster(clusterWideKey keys.ClusterWideK
|
|||
return err
|
||||
}
|
||||
|
||||
clusterRestConfig, err := d.KarmadaConfig.GetRestConfig("", kubeconfigPath)
|
||||
clusterRestConfig, err := apiclient.RestConfig("", kubeconfigPath)
|
||||
if err != nil {
|
||||
klog.Fatalf("Failed to get cluster-api management cluster rest config. kubeconfig: %s, err: %v", kubeconfigPath, err)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
)
|
||||
|
||||
// CommandAddonsDisableOption options for addons list.
|
||||
|
@ -26,7 +26,7 @@ func (o *CommandAddonsDisableOption) Complete() error {
|
|||
return err
|
||||
}
|
||||
|
||||
o.KarmadaKubeClientSet, err = utils.NewClientSet(o.KarmadaRestConfig)
|
||||
o.KarmadaKubeClientSet, err = apiclient.NewClientSet(o.KarmadaRestConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"k8s.io/utils/strings/slices"
|
||||
|
||||
cmdinit "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/kubernetes"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
)
|
||||
|
||||
// CommandAddonsEnableOption options for addons list.
|
||||
|
@ -48,7 +48,7 @@ func (o *CommandAddonsEnableOption) Complete() error {
|
|||
return err
|
||||
}
|
||||
|
||||
o.KarmadaKubeClientSet, err = utils.NewClientSet(o.KarmadaRestConfig)
|
||||
o.KarmadaKubeClientSet, err = apiclient.NewClientSet(o.KarmadaRestConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func (o *CommandAddonsEnableOption) Validate(args []string) error {
|
|||
}
|
||||
|
||||
// Check member kubeconfig and context is valid
|
||||
memberConfig, err := utils.RestConfig(o.MemberContext, o.MemberKubeConfig)
|
||||
memberConfig, err := apiclient.RestConfig(o.MemberContext, o.MemberKubeConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get member cluster config. error: %v", err)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
)
|
||||
|
||||
// GlobalCommandOptions holds the configuration shared by the all sub-commands of `karmadactl`.
|
||||
|
@ -48,31 +44,22 @@ func (o *GlobalCommandOptions) AddFlags(flags *pflag.FlagSet) {
|
|||
|
||||
// Complete the conditions required to be able to run list.
|
||||
func (o *GlobalCommandOptions) Complete() error {
|
||||
if o.KubeConfig == "" {
|
||||
env := os.Getenv("KUBECONFIG")
|
||||
if env != "" {
|
||||
o.KubeConfig = env
|
||||
} else {
|
||||
o.KubeConfig = filepath.Join(homedir.HomeDir(), ".kube", "config")
|
||||
}
|
||||
}
|
||||
|
||||
restConfig, err := utils.RestConfig(o.Context, o.KubeConfig)
|
||||
restConfig, err := apiclient.RestConfig(o.Context, o.KubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.KubeClientSet, err = utils.NewClientSet(restConfig)
|
||||
o.KubeClientSet, err = apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.KarmadaRestConfig, err = utils.RestConfig(o.KarmadaContext, o.KarmadaConfig)
|
||||
o.KarmadaRestConfig, err = apiclient.RestConfig(o.KarmadaContext, o.KarmadaConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.KarmadaAggregatorClientSet, err = utils.NewAPIRegistrationClient(o.KarmadaRestConfig)
|
||||
o.KarmadaAggregatorClientSet, err = apiclient.NewAPIRegistrationClient(o.KarmadaRestConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/options"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
tokenutil "github.com/karmada-io/karmada/pkg/karmadactl/util/bootstraptoken"
|
||||
)
|
||||
|
||||
|
@ -36,12 +37,12 @@ const (
|
|||
|
||||
// InitKarmadaResources Initialize karmada resource
|
||||
func InitKarmadaResources(dir, caBase64, systemNamespace string) error {
|
||||
restConfig, err := utils.RestConfig("", filepath.Join(dir, options.KarmadaKubeConfigName))
|
||||
restConfig, err := apiclient.RestConfig("", filepath.Join(dir, options.KarmadaKubeConfigName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientSet, err := utils.NewClientSet(restConfig)
|
||||
clientSet, err := apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ func InitKarmadaResources(dir, caBase64, systemNamespace string) error {
|
|||
}
|
||||
|
||||
// New CRDsClient
|
||||
crdClient, err := utils.NewCRDsClient(restConfig)
|
||||
crdClient, err := apiclient.NewCRDsClient(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -110,12 +111,12 @@ func InitKarmadaResources(dir, caBase64, systemNamespace string) error {
|
|||
|
||||
// InitKarmadaBootstrapToken create initial bootstrap token
|
||||
func InitKarmadaBootstrapToken(dir string) (string, error) {
|
||||
restConfig, err := utils.RestConfig("", filepath.Join(dir, options.KarmadaKubeConfigName))
|
||||
restConfig, err := apiclient.RestConfig("", filepath.Join(dir, options.KarmadaKubeConfigName))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
clientSet, err := utils.NewClientSet(restConfig)
|
||||
clientSet, err := apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -260,7 +261,7 @@ func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, sy
|
|||
return err
|
||||
}
|
||||
// new apiRegistrationClient
|
||||
apiRegistrationClient, err := utils.NewAPIRegistrationClient(restConfig)
|
||||
apiRegistrationClient, err := apiclient.NewAPIRegistrationClient(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -17,7 +16,6 @@ import (
|
|||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
"k8s.io/klog/v2"
|
||||
netutils "k8s.io/utils/net"
|
||||
|
||||
|
@ -25,6 +23,7 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/karmada"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/options"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -44,8 +43,6 @@ var (
|
|||
options.FrontProxyClientCertAndKeyName,
|
||||
}
|
||||
|
||||
defaultKubeConfig = filepath.Join(homedir.HomeDir(), ".kube", "config")
|
||||
|
||||
defaultEtcdImage = "etcd:3.5.3-0"
|
||||
defaultKubeAPIServerImage = "kube-apiserver:v1.25.2"
|
||||
defaultKubeControllerManagerImage = "kube-controller-manager:v1.25.2"
|
||||
|
@ -135,24 +132,14 @@ func (i *CommandInitOption) Validate(parentCommand string) error {
|
|||
|
||||
// Complete Initialize k8s client
|
||||
func (i *CommandInitOption) Complete() error {
|
||||
// check config path of host kubernetes cluster
|
||||
if i.KubeConfig == "" {
|
||||
env := os.Getenv("KUBECONFIG")
|
||||
if env != "" {
|
||||
i.KubeConfig = env
|
||||
} else {
|
||||
i.KubeConfig = defaultKubeConfig
|
||||
}
|
||||
}
|
||||
|
||||
restConfig, err := utils.RestConfig(i.Context, i.KubeConfig)
|
||||
restConfig, err := apiclient.RestConfig(i.Context, i.KubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.RestConfig = restConfig
|
||||
|
||||
klog.Infof("kubeconfig file: %s, kubernetes: %s", i.KubeConfig, restConfig.Host)
|
||||
clientSet, err := utils.NewClientSet(restConfig)
|
||||
clientSet, err := apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
)
|
||||
|
||||
// RestConfig Kubernetes kubeconfig
|
||||
func RestConfig(context, kubeconfigPath string) (*rest.Config, error) {
|
||||
pathOptions := clientcmd.NewDefaultPathOptions()
|
||||
|
||||
loadingRules := *pathOptions.LoadingRules
|
||||
loadingRules.ExplicitPath = kubeconfigPath
|
||||
loadingRules.Precedence = pathOptions.GetLoadingPrecedence()
|
||||
overrides := &clientcmd.ConfigOverrides{
|
||||
CurrentContext: context,
|
||||
}
|
||||
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, overrides)
|
||||
|
||||
restConfig, err := clientConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return restConfig, err
|
||||
}
|
||||
|
||||
// NewClientSet Kubernetes ClientSet
|
||||
func NewClientSet(c *rest.Config) (*kubernetes.Clientset, error) {
|
||||
return kubernetes.NewForConfig(c)
|
||||
}
|
||||
|
||||
// NewCRDsClient clientset ClientSet
|
||||
func NewCRDsClient(c *rest.Config) (*clientset.Clientset, error) {
|
||||
return clientset.NewForConfig(c)
|
||||
}
|
||||
|
||||
// NewAPIRegistrationClient apiregistration ClientSet
|
||||
func NewAPIRegistrationClient(c *rest.Config) (*aggregator.Clientset, error) {
|
||||
return aggregator.NewForConfig(c)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package karmadactl
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// KarmadaConfig provides a rest config based on the filesystem kubeconfig (via
|
||||
// pathOptions) and context in order to talk to the control plane
|
||||
// and the joining kubernetes cluster.
|
||||
type KarmadaConfig interface {
|
||||
// GetRestConfig used to get a cluster's rest config.
|
||||
GetRestConfig(context, kubeconfigPath string) (*rest.Config, error)
|
||||
|
||||
// GetClientConfig returns a ClientConfig from kubeconfigPath.
|
||||
// If kubeconfigPath is empty, will search KUBECONFIG from default path.
|
||||
// If context is not empty, the returned ClientConfig's current-context is the input context.
|
||||
GetClientConfig(context, kubeconfigPath string) clientcmd.ClientConfig
|
||||
}
|
||||
|
||||
// karmadaConfig implements the KarmadaConfig interface.
|
||||
type karmadaConfig struct {
|
||||
pathOptions *clientcmd.PathOptions
|
||||
}
|
||||
|
||||
// NewKarmadaConfig creates a karmadaConfig for `karmadactl` commands.
|
||||
func NewKarmadaConfig(pathOptions *clientcmd.PathOptions) KarmadaConfig {
|
||||
return &karmadaConfig{
|
||||
pathOptions: pathOptions,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *karmadaConfig) GetRestConfig(context, kubeconfigPath string) (*rest.Config, error) {
|
||||
clientConfig := a.GetClientConfig(context, kubeconfigPath)
|
||||
restConfig, err := clientConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return restConfig, nil
|
||||
}
|
||||
|
||||
// GetClientConfig is a helper method to create a client config from the
|
||||
// context and kubeconfig passed as arguments.
|
||||
func (a *karmadaConfig) GetClientConfig(context, kubeconfigPath string) clientcmd.ClientConfig {
|
||||
loadingRules := *a.pathOptions.LoadingRules
|
||||
loadingRules.ExplicitPath = kubeconfigPath
|
||||
loadingRules.Precedence = a.pathOptions.GetLoadingPrecedence()
|
||||
overrides := &clientcmd.ConfigOverrides{
|
||||
CurrentContext: context,
|
||||
}
|
||||
|
||||
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, overrides)
|
||||
}
|
|
@ -12,8 +12,8 @@ import (
|
|||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubectl/pkg/util/templates"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -84,25 +84,12 @@ func NewCmdDeInit(parentCommand string) *cobra.Command {
|
|||
|
||||
// Complete the conditions required to be able to run deinit.
|
||||
func (o *CommandDeInitOption) Complete() error {
|
||||
if o.KubeConfig == "" {
|
||||
env := os.Getenv("KUBECONFIG")
|
||||
if env != "" {
|
||||
o.KubeConfig = env
|
||||
} else {
|
||||
o.KubeConfig = defaultKubeConfig
|
||||
}
|
||||
}
|
||||
|
||||
if !Exists(o.KubeConfig) {
|
||||
return ErrEmptyConfig
|
||||
}
|
||||
|
||||
restConfig, err := utils.RestConfig(o.Context, o.KubeConfig)
|
||||
restConfig, err := apiclient.RestConfig(o.Context, o.KubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.KubeClientSet, err = utils.NewClientSet(restConfig)
|
||||
o.KubeClientSet, err = apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -973,14 +972,6 @@ func (g *CommandGetOptions) setColumnDefinition(table *metav1.Table) {
|
|||
}
|
||||
}
|
||||
|
||||
// Exists determine if path exists
|
||||
func Exists(path string) bool {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return os.IsExist(err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// skipPrinter allows conditionally suppressing object output via the output field.
|
||||
// table objects are suppressed by setting their Rows to nil (allowing column definitions to propagate to the delegate).
|
||||
// non-table objects are suppressed by not calling the delegate at all.
|
||||
|
|
|
@ -1,350 +0,0 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
Copy From: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kubectl/pkg/cmd/get/get_flags.go
|
||||
Change: ConfigFlags struct add CaBundle fields, toRawKubeConfigLoader method modify new loadRules and overrides, remove AddFlags function.
|
||||
*/
|
||||
|
||||
package karmadactl
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/client-go/discovery"
|
||||
diskcached "k8s.io/client-go/discovery/cached/disk"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/restmapper"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultKubeConfig = filepath.Join(homedir.HomeDir(), ".kube", "config")
|
||||
defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "cache")
|
||||
// ErrEmptyConfig is the error message to be displayed if the configuration info is missing or incomplete
|
||||
ErrEmptyConfig = clientcmd.NewEmptyConfigError(
|
||||
`Missing or incomplete configuration info. Please point to an existing, complete config file:
|
||||
1. Via the command-line flag --kubeconfig
|
||||
2. Via the KUBECONFIG environment variable
|
||||
3. In your home directory as ~/.kube/config
|
||||
|
||||
To view or setup config directly use the 'config' command.`)
|
||||
)
|
||||
|
||||
// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands
|
||||
// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages
|
||||
// as per the golang type overlapping.
|
||||
type RESTClientGetter interface {
|
||||
// ToRESTConfig returns restconfig
|
||||
ToRESTConfig() (*rest.Config, error)
|
||||
// ToDiscoveryClient returns discovery client
|
||||
ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error)
|
||||
// ToRESTMapper returns a restmapper
|
||||
ToRESTMapper() (meta.RESTMapper, error)
|
||||
// ToRawKubeConfigLoader return kubeconfig loader as-is
|
||||
ToRawKubeConfigLoader() clientcmd.ClientConfig
|
||||
}
|
||||
|
||||
type clientConfig struct {
|
||||
defaultClientConfig clientcmd.ClientConfig
|
||||
}
|
||||
|
||||
func (c *clientConfig) RawConfig() (clientcmdapi.Config, error) {
|
||||
config, err := c.defaultClientConfig.RawConfig()
|
||||
// replace client-go's ErrEmptyConfig error with our custom, more verbose version
|
||||
if clientcmd.IsEmptyConfig(err) {
|
||||
return config, ErrEmptyConfig
|
||||
}
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (c *clientConfig) ClientConfig() (*rest.Config, error) {
|
||||
config, err := c.defaultClientConfig.ClientConfig()
|
||||
// replace client-go's ErrEmptyConfig error with our custom, more verbose version
|
||||
if clientcmd.IsEmptyConfig(err) {
|
||||
return config, ErrEmptyConfig
|
||||
}
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (c *clientConfig) Namespace() (string, bool, error) {
|
||||
namespace, ok, err := c.defaultClientConfig.Namespace()
|
||||
// replace client-go's ErrEmptyConfig error with our custom, more verbose version
|
||||
if clientcmd.IsEmptyConfig(err) {
|
||||
return namespace, ok, ErrEmptyConfig
|
||||
}
|
||||
return namespace, ok, err
|
||||
}
|
||||
|
||||
func (c *clientConfig) ConfigAccess() clientcmd.ConfigAccess {
|
||||
return c.defaultClientConfig.ConfigAccess()
|
||||
}
|
||||
|
||||
var _ RESTClientGetter = &ConfigFlags{}
|
||||
|
||||
// ConfigFlags composes the set of values necessary
|
||||
// for obtaining a REST client config
|
||||
type ConfigFlags struct {
|
||||
CaBundle *string
|
||||
|
||||
// Default cache director
|
||||
CacheDir *string
|
||||
// Path to the kubeconfig file to use for CLI requests.
|
||||
KubeConfig *string
|
||||
|
||||
// The name of the kubeconfig cluster to use
|
||||
ClusterName *string
|
||||
// The name of the kubeconfig user to use
|
||||
AuthInfoName *string
|
||||
// The name of the kubeconfig context to use
|
||||
Context *string
|
||||
// If present, the namespace scope for this CLI request
|
||||
Namespace *string
|
||||
// The address and port of the Kubernetes API server
|
||||
APIServer *string
|
||||
// Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
|
||||
TLSServerName *string
|
||||
// If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
||||
Insecure *bool
|
||||
// Path to a client certificate file for TLS
|
||||
CertFile *string
|
||||
// Path to a client key file for TLS
|
||||
KeyFile *string
|
||||
// Path to a cert file for the certificate authority
|
||||
CAFile *string
|
||||
// Bearer token for authentication to the API server
|
||||
BearerToken *string
|
||||
Impersonate *string
|
||||
ImpersonateGroup *[]string
|
||||
Username *string
|
||||
Password *string
|
||||
// The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.
|
||||
Timeout *string
|
||||
// If non-nil, wrap config function can transform the Config
|
||||
// before it is returned in ToRESTConfig function.
|
||||
WrapConfigFn func(*rest.Config) *rest.Config
|
||||
|
||||
clientConfig clientcmd.ClientConfig
|
||||
lock sync.Mutex
|
||||
// If set to true, will use persistent client config and
|
||||
// propagate the config to the places that need it, rather than
|
||||
// loading the config multiple times
|
||||
usePersistentConfig bool
|
||||
// Allows increasing burst used for discovery, this is useful
|
||||
// in clusters with many registered resources
|
||||
discoveryBurst int
|
||||
}
|
||||
|
||||
// ToRESTConfig implements RESTClientGetter.
|
||||
// Returns a REST client configuration based on a provided path
|
||||
// to a .kubeconfig file, loading rules, and config flag overrides.
|
||||
// Expects the AddFlags method to have been called. If WrapConfigFn
|
||||
// is non-nil this function can transform config before return.
|
||||
func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) {
|
||||
c, err := f.ToRawKubeConfigLoader().ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.WrapConfigFn != nil {
|
||||
return f.WrapConfigFn(c), nil
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ToRawKubeConfigLoader binds config flag values to config overrides
|
||||
// Returns an interactive clientConfig if the password flag is enabled,
|
||||
// or a non-interactive clientConfig otherwise.
|
||||
func (f *ConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig {
|
||||
if f.usePersistentConfig {
|
||||
return f.toRawKubePersistentConfigLoader()
|
||||
}
|
||||
return f.toRawKubeConfigLoader()
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (f *ConfigFlags) toRawKubeConfigLoader() clientcmd.ClientConfig {
|
||||
//loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
loadingRules := &clientcmd.ClientConfigLoadingRules{}
|
||||
// use the standard defaults for this client command
|
||||
// DEPRECATED: remove and replace with something more accurate
|
||||
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
|
||||
|
||||
if f.KubeConfig != nil {
|
||||
loadingRules.ExplicitPath = *f.KubeConfig
|
||||
}
|
||||
|
||||
clusterOverrides := clientcmd.ClusterDefaults
|
||||
if f.CaBundle != nil {
|
||||
clusterOverrides.CertificateAuthorityData = []byte(*f.CaBundle)
|
||||
}
|
||||
|
||||
overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clusterOverrides}
|
||||
|
||||
// bind auth info flag values to overrides
|
||||
if f.CertFile != nil {
|
||||
overrides.AuthInfo.ClientCertificate = *f.CertFile
|
||||
}
|
||||
if f.KeyFile != nil {
|
||||
overrides.AuthInfo.ClientKey = *f.KeyFile
|
||||
}
|
||||
if f.BearerToken != nil {
|
||||
overrides.AuthInfo.Token = *f.BearerToken
|
||||
}
|
||||
|
||||
// bind cluster flags
|
||||
if f.APIServer != nil {
|
||||
overrides.ClusterInfo.Server = *f.APIServer
|
||||
}
|
||||
if f.TLSServerName != nil {
|
||||
overrides.ClusterInfo.TLSServerName = *f.TLSServerName
|
||||
}
|
||||
if f.CAFile != nil {
|
||||
overrides.ClusterInfo.CertificateAuthority = *f.CAFile
|
||||
}
|
||||
if f.Insecure != nil {
|
||||
overrides.ClusterInfo.InsecureSkipTLSVerify = *f.Insecure
|
||||
}
|
||||
|
||||
// bind context flags
|
||||
if f.Context != nil {
|
||||
overrides.CurrentContext = *f.Context
|
||||
}
|
||||
if f.ClusterName != nil {
|
||||
overrides.Context.Cluster = *f.ClusterName
|
||||
}
|
||||
if f.AuthInfoName != nil {
|
||||
overrides.Context.AuthInfo = *f.AuthInfoName
|
||||
}
|
||||
if f.Namespace != nil {
|
||||
overrides.Context.Namespace = *f.Namespace
|
||||
}
|
||||
|
||||
if f.Timeout != nil {
|
||||
overrides.Timeout = *f.Timeout
|
||||
}
|
||||
|
||||
// we only have an interactive prompt when a password is allowed
|
||||
if f.Password == nil {
|
||||
return &clientConfig{clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)}
|
||||
}
|
||||
return &clientConfig{clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)}
|
||||
}
|
||||
|
||||
// toRawKubePersistentConfigLoader binds config flag values to config overrides
|
||||
// Returns a persistent clientConfig for propagation.
|
||||
func (f *ConfigFlags) toRawKubePersistentConfigLoader() clientcmd.ClientConfig {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.clientConfig == nil {
|
||||
f.clientConfig = f.toRawKubeConfigLoader()
|
||||
}
|
||||
|
||||
return f.clientConfig
|
||||
}
|
||||
|
||||
// ToDiscoveryClient implements RESTClientGetter.
|
||||
// Expects the AddFlags method to have been called.
|
||||
// Returns a CachedDiscoveryInterface using a computed RESTConfig.
|
||||
func (f *ConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
|
||||
config, err := f.ToRESTConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The more groups you have, the more discovery requests you need to make.
|
||||
// given 25 groups (our groups + a few custom resources) with one-ish version each, discovery needs to make 50 requests
|
||||
// double it just so we don't end up here again for a while. This config is only used for discovery.
|
||||
config.Burst = f.discoveryBurst
|
||||
|
||||
cacheDir := defaultCacheDir
|
||||
|
||||
// retrieve a user-provided value for the "cache-dir"
|
||||
// override httpCacheDir and discoveryCacheDir if user-value is given.
|
||||
if f.CacheDir != nil {
|
||||
cacheDir = *f.CacheDir
|
||||
}
|
||||
httpCacheDir := filepath.Join(cacheDir, "http")
|
||||
discoveryCacheDir := computeDiscoverCacheDir(filepath.Join(cacheDir, "discovery"), config.Host)
|
||||
|
||||
return diskcached.NewCachedDiscoveryClientForConfig(config, discoveryCacheDir, httpCacheDir, time.Duration(10*time.Minute))
|
||||
}
|
||||
|
||||
// ToRESTMapper returns a mapper.
|
||||
func (f *ConfigFlags) ToRESTMapper() (meta.RESTMapper, error) {
|
||||
discoveryClient, err := f.ToDiscoveryClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient)
|
||||
expander := restmapper.NewShortcutExpander(mapper, discoveryClient)
|
||||
return expander, nil
|
||||
}
|
||||
|
||||
// WithDeprecatedPasswordFlag enables the username and password config flags
|
||||
func (f *ConfigFlags) WithDeprecatedPasswordFlag() *ConfigFlags {
|
||||
f.Username = stringptr("")
|
||||
f.Password = stringptr("")
|
||||
return f
|
||||
}
|
||||
|
||||
// WithDiscoveryBurst sets the RESTClient burst for discovery.
|
||||
func (f *ConfigFlags) WithDiscoveryBurst(discoveryBurst int) *ConfigFlags {
|
||||
f.discoveryBurst = discoveryBurst
|
||||
return f
|
||||
}
|
||||
|
||||
// NewConfigFlags returns ConfigFlags with default values set
|
||||
func NewConfigFlags(usePersistentConfig bool) *ConfigFlags {
|
||||
impersonateGroup := []string{}
|
||||
insecure := false
|
||||
|
||||
return &ConfigFlags{
|
||||
Insecure: &insecure,
|
||||
Timeout: stringptr("0"),
|
||||
KubeConfig: stringptr(""),
|
||||
|
||||
CacheDir: stringptr(defaultCacheDir),
|
||||
ClusterName: stringptr(""),
|
||||
AuthInfoName: stringptr(""),
|
||||
Context: stringptr(""),
|
||||
Namespace: stringptr(""),
|
||||
APIServer: stringptr(""),
|
||||
TLSServerName: stringptr(""),
|
||||
CertFile: stringptr(""),
|
||||
KeyFile: stringptr(""),
|
||||
CAFile: stringptr(""),
|
||||
BearerToken: stringptr(""),
|
||||
Impersonate: stringptr(""),
|
||||
ImpersonateGroup: &impersonateGroup,
|
||||
|
||||
usePersistentConfig: usePersistentConfig,
|
||||
// The more groups you have, the more discovery requests you need to make.
|
||||
// given 25 groups (our groups + a few custom resources) with one-ish version each, discovery needs to make 50 requests
|
||||
// double it just so we don't end up here again for a while. This config is only used for discovery.
|
||||
discoveryBurst: 100,
|
||||
}
|
||||
}
|
||||
|
||||
func stringptr(val string) *string {
|
||||
return &val
|
||||
}
|
||||
|
||||
// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive
|
||||
var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`)
|
||||
|
||||
// computeDiscoverCacheDir takes the parentDir and the host and comes up with a "usually non-colliding" name.
|
||||
func computeDiscoverCacheDir(parentDir, host string) string {
|
||||
// strip the optional scheme from host if its there:
|
||||
schemelessHost := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1)
|
||||
// now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived
|
||||
safeHost := overlyCautiousIllegalFileCharacters.ReplaceAllString(schemelessHost, "_")
|
||||
return filepath.Join(parentDir, safeHost)
|
||||
}
|
|
@ -15,7 +15,8 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/apis/cluster/validation"
|
||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
karmadactlutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -29,7 +30,7 @@ var (
|
|||
)
|
||||
|
||||
// NewCmdJoin defines the `join` command that registers a cluster.
|
||||
func NewCmdJoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command {
|
||||
func NewCmdJoin(f cmdutil.Factory, parentCommand string) *cobra.Command {
|
||||
opts := CommandJoinOption{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -46,26 +47,27 @@ func NewCmdJoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman
|
|||
if err := opts.Validate(args); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := RunJoin(karmadaConfig, opts); err != nil {
|
||||
if err := RunJoin(f, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
karmadactlutil.TagCommandGroup: karmadactlutil.GroupClusterRegistration,
|
||||
cmdutil.TagCommandGroup: cmdutil.GroupClusterRegistration,
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
opts.AddFlags(flags)
|
||||
|
||||
flags.StringVar(defaultConfigFlags.KubeConfig, "kubeconfig", *defaultConfigFlags.KubeConfig, "Path to the kubeconfig file to use for CLI requests.")
|
||||
flags.StringVar(defaultConfigFlags.Context, "karmada-context", *defaultConfigFlags.Context, "The name of the kubeconfig context to use")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// CommandJoinOption holds all command options.
|
||||
type CommandJoinOption struct {
|
||||
options.GlobalCommandOptions
|
||||
|
||||
// ClusterNamespace holds the namespace name where the member cluster secrets are stored.
|
||||
ClusterNamespace string
|
||||
|
||||
|
@ -126,8 +128,6 @@ func (j *CommandJoinOption) Validate(args []string) error {
|
|||
|
||||
// AddFlags adds flags to the specified FlagSet.
|
||||
func (j *CommandJoinOption) AddFlags(flags *pflag.FlagSet) {
|
||||
j.GlobalCommandOptions.AddFlags(flags)
|
||||
|
||||
flags.StringVar(&j.ClusterNamespace, "cluster-namespace", options.DefaultKarmadaClusterNamespace, "Namespace in the control plane where member cluster secrets are stored.")
|
||||
|
||||
flags.StringVar(&j.ClusterContext, "cluster-context", "",
|
||||
|
@ -141,19 +141,19 @@ func (j *CommandJoinOption) AddFlags(flags *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
// RunJoin is the implementation of the 'join' command.
|
||||
func RunJoin(karmadaConfig KarmadaConfig, opts CommandJoinOption) error {
|
||||
func RunJoin(f cmdutil.Factory, opts CommandJoinOption) error {
|
||||
klog.V(1).Infof("joining cluster. cluster name: %s", opts.ClusterName)
|
||||
klog.V(1).Infof("joining cluster. cluster namespace: %s", opts.ClusterNamespace)
|
||||
|
||||
// Get control plane karmada-apiserver client
|
||||
controlPlaneRestConfig, err := karmadaConfig.GetRestConfig(opts.KarmadaContext, opts.KubeConfig)
|
||||
controlPlaneRestConfig, err := f.ToRawKubeConfigLoader().ClientConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get control plane rest config. context: %s, kube-config: %s, error: %v",
|
||||
opts.KarmadaContext, opts.KubeConfig, err)
|
||||
*defaultConfigFlags.Context, *defaultConfigFlags.KubeConfig, err)
|
||||
}
|
||||
|
||||
// Get cluster config
|
||||
clusterConfig, err := karmadaConfig.GetRestConfig(opts.ClusterContext, opts.ClusterKubeConfig)
|
||||
clusterConfig, err := apiclient.RestConfig(opts.ClusterContext, opts.ClusterKubeConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get joining cluster config. error: %v", err)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
apiserverflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubectl/pkg/util/templates"
|
||||
|
@ -54,7 +53,6 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
|||
// Prevent klog errors about logging before parsing.
|
||||
_ = flag.CommandLine.Parse(nil)
|
||||
|
||||
karmadaConfig := NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
f := util.NewFactory(defaultConfigFlags)
|
||||
ioStreams := genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
|
||||
groups := templates.CommandGroups{
|
||||
|
@ -70,8 +68,8 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
|||
cmdinit.NewCmdInit(parentCommand),
|
||||
NewCmdDeInit(parentCommand),
|
||||
addons.NewCommandAddons(parentCommand),
|
||||
NewCmdJoin(karmadaConfig, parentCommand),
|
||||
NewCmdUnjoin(karmadaConfig, parentCommand),
|
||||
NewCmdJoin(f, parentCommand),
|
||||
NewCmdUnjoin(f, parentCommand),
|
||||
NewCmdToken(f, parentCommand, ioStreams),
|
||||
NewCmdRegister(parentCommand),
|
||||
},
|
||||
|
|
|
@ -1,29 +1,9 @@
|
|||
package options
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
import "time"
|
||||
|
||||
// DefaultKarmadaClusterNamespace defines the default namespace where the member cluster secrets are stored.
|
||||
const DefaultKarmadaClusterNamespace = "karmada-cluster"
|
||||
|
||||
// DefaultKarmadactlCommandDuration defines the default timeout for karmadactl execute
|
||||
const DefaultKarmadactlCommandDuration = 60 * time.Second
|
||||
|
||||
// GlobalCommandOptions holds the configuration shared by the all sub-commands of `karmadactl`.
|
||||
type GlobalCommandOptions struct {
|
||||
// KubeConfig holds the control plane KUBECONFIG file path.
|
||||
KubeConfig string
|
||||
|
||||
// ClusterContext is the name of the cluster context in control plane KUBECONFIG file.
|
||||
// Default value is the current-context.
|
||||
KarmadaContext string
|
||||
}
|
||||
|
||||
// AddFlags adds flags to the specified FlagSet.
|
||||
func (o *GlobalCommandOptions) AddFlags(flags *pflag.FlagSet) {
|
||||
flags.StringVar(&o.KubeConfig, "kubeconfig", "", "Path to the control plane kubeconfig file.")
|
||||
flags.StringVar(&o.KarmadaContext, "karmada-context", "", "Name of the cluster context in control plane kubeconfig file.")
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
tokenutil "github.com/karmada-io/karmada/pkg/karmadactl/util/bootstraptoken"
|
||||
karmadautil "github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/pkg/util/lifted/pubkeypin"
|
||||
|
@ -242,20 +243,7 @@ func (o *CommandRegisterOption) Complete(args []string) error {
|
|||
}
|
||||
o.BootstrapToken.APIServerEndpoint = args[0]
|
||||
|
||||
if o.KubeConfig == "" {
|
||||
env := os.Getenv("KUBECONFIG")
|
||||
if env != "" {
|
||||
o.KubeConfig = env
|
||||
} else {
|
||||
o.KubeConfig = defaultKubeConfig
|
||||
}
|
||||
}
|
||||
|
||||
if !Exists(o.KubeConfig) {
|
||||
return ErrEmptyConfig
|
||||
}
|
||||
|
||||
restConfig, err := utils.RestConfig(o.Context, o.KubeConfig)
|
||||
restConfig, err := apiclient.RestConfig(o.Context, o.KubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -276,7 +264,7 @@ func (o *CommandRegisterOption) Complete(args []string) error {
|
|||
|
||||
o.memberClusterEndpoint = restConfig.Host
|
||||
|
||||
o.memberClusterClient, err = utils.NewClientSet(restConfig)
|
||||
o.memberClusterClient, err = apiclient.NewClientSet(restConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ import (
|
|||
|
||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
karmadactlutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/pkg/util/names"
|
||||
)
|
||||
|
@ -37,7 +38,7 @@ var (
|
|||
)
|
||||
|
||||
// NewCmdUnjoin defines the `unjoin` command that removes registration of a cluster from control plane.
|
||||
func NewCmdUnjoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command {
|
||||
func NewCmdUnjoin(f cmdutil.Factory, parentCommand string) *cobra.Command {
|
||||
opts := CommandUnjoinOption{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -54,26 +55,27 @@ func NewCmdUnjoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comm
|
|||
if err := opts.Validate(args); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := RunUnjoin(karmadaConfig, opts); err != nil {
|
||||
if err := RunUnjoin(f, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
karmadactlutil.TagCommandGroup: karmadactlutil.GroupClusterRegistration,
|
||||
cmdutil.TagCommandGroup: cmdutil.GroupClusterRegistration,
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
opts.AddFlags(flags)
|
||||
|
||||
flags.StringVar(defaultConfigFlags.KubeConfig, "kubeconfig", *defaultConfigFlags.KubeConfig, "Path to the kubeconfig file to use for CLI requests.")
|
||||
flags.StringVar(defaultConfigFlags.Context, "karmada-context", *defaultConfigFlags.Context, "The name of the kubeconfig context to use")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// CommandUnjoinOption holds all command options.
|
||||
type CommandUnjoinOption struct {
|
||||
options.GlobalCommandOptions
|
||||
|
||||
// ClusterNamespace holds namespace where the member cluster secrets are stored
|
||||
ClusterNamespace string
|
||||
|
||||
|
@ -126,8 +128,6 @@ func (j *CommandUnjoinOption) Validate(args []string) error {
|
|||
|
||||
// AddFlags adds flags to the specified FlagSet.
|
||||
func (j *CommandUnjoinOption) AddFlags(flags *pflag.FlagSet) {
|
||||
j.GlobalCommandOptions.AddFlags(flags)
|
||||
|
||||
flags.StringVar(&j.ClusterNamespace, "cluster-namespace", options.DefaultKarmadaClusterNamespace, "Namespace in the control plane where member cluster secrets are stored.")
|
||||
flags.StringVar(&j.ClusterContext, "cluster-context", "",
|
||||
"Context name of cluster in kubeconfig. Only works when there are multiple contexts in the kubeconfig.")
|
||||
|
@ -140,22 +140,22 @@ func (j *CommandUnjoinOption) AddFlags(flags *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
// RunUnjoin is the implementation of the 'unjoin' command.
|
||||
func RunUnjoin(karmadaConfig KarmadaConfig, opts CommandUnjoinOption) error {
|
||||
func RunUnjoin(f cmdutil.Factory, opts CommandUnjoinOption) error {
|
||||
klog.V(1).Infof("unjoining cluster. cluster name: %s", opts.ClusterName)
|
||||
klog.V(1).Infof("unjoining cluster. cluster namespace: %s", opts.ClusterNamespace)
|
||||
|
||||
// Get control plane kube-apiserver client
|
||||
controlPlaneRestConfig, err := karmadaConfig.GetRestConfig(opts.KarmadaContext, opts.KubeConfig)
|
||||
controlPlaneRestConfig, err := f.ToRawKubeConfigLoader().ClientConfig()
|
||||
if err != nil {
|
||||
klog.Errorf("failed to get control plane rest config. context: %s, kube-config: %s, error: %v",
|
||||
opts.KarmadaContext, opts.KubeConfig, err)
|
||||
defaultConfigFlags.Context, defaultConfigFlags.KubeConfig, err)
|
||||
return err
|
||||
}
|
||||
|
||||
var clusterConfig *rest.Config
|
||||
if opts.ClusterKubeConfig != "" {
|
||||
// Get cluster config
|
||||
clusterConfig, err = karmadaConfig.GetRestConfig(opts.ClusterContext, opts.ClusterKubeConfig)
|
||||
clusterConfig, err = apiclient.RestConfig(opts.ClusterContext, opts.ClusterKubeConfig)
|
||||
if err != nil {
|
||||
klog.V(1).Infof("failed to get unjoining cluster config. error: %v", err)
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package apiclient
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultKubeConfig = filepath.Join(homedir.HomeDir(), ".kube", "config")
|
||||
|
||||
// ErrEmptyConfig is the error message to be displayed if the configuration info is missing or incomplete
|
||||
ErrEmptyConfig = clientcmd.NewEmptyConfigError(
|
||||
`Missing or incomplete configuration info. Please point to an existing, complete config file:
|
||||
1. Via the command-line flag --kubeconfig
|
||||
2. Via the KUBECONFIG environment variable
|
||||
3. In your home directory as ~/.kube/config
|
||||
`)
|
||||
)
|
||||
|
||||
// RestConfig is to create a rest config from the context and kubeconfig passed as arguments.
|
||||
func RestConfig(context, kubeconfigPath string) (*rest.Config, error) {
|
||||
if kubeconfigPath == "" {
|
||||
env := os.Getenv("KUBECONFIG")
|
||||
if env != "" {
|
||||
kubeconfigPath = env
|
||||
} else {
|
||||
kubeconfigPath = defaultKubeConfig
|
||||
}
|
||||
}
|
||||
|
||||
if !Exists(kubeconfigPath) {
|
||||
return nil, ErrEmptyConfig
|
||||
}
|
||||
|
||||
pathOptions := clientcmd.NewDefaultPathOptions()
|
||||
|
||||
loadingRules := *pathOptions.LoadingRules
|
||||
loadingRules.ExplicitPath = kubeconfigPath
|
||||
loadingRules.Precedence = pathOptions.GetLoadingPrecedence()
|
||||
overrides := &clientcmd.ConfigOverrides{
|
||||
CurrentContext: context,
|
||||
}
|
||||
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, overrides)
|
||||
|
||||
restConfig, err := clientConfig.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return restConfig, err
|
||||
}
|
||||
|
||||
// NewClientSet is to create a kubernetes ClientSet
|
||||
func NewClientSet(c *rest.Config) (*kubernetes.Clientset, error) {
|
||||
return kubernetes.NewForConfig(c)
|
||||
}
|
||||
|
||||
// NewCRDsClient is to create a clientset ClientSet
|
||||
func NewCRDsClient(c *rest.Config) (*clientset.Clientset, error) {
|
||||
return clientset.NewForConfig(c)
|
||||
}
|
||||
|
||||
// NewAPIRegistrationClient is to create an apiregistration ClientSet
|
||||
func NewAPIRegistrationClient(c *rest.Config) (*aggregator.Clientset, error) {
|
||||
return aggregator.NewForConfig(c)
|
||||
}
|
||||
|
||||
// Exists determine if path exists
|
||||
func Exists(path string) bool {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return os.IsExist(err)
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -11,12 +11,14 @@ import (
|
|||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/test/e2e/framework"
|
||||
"github.com/karmada-io/karmada/test/helper"
|
||||
)
|
||||
|
@ -34,6 +36,7 @@ var _ = framework.SerialDescribe("Aggregated Kubernetes API Endpoint testing", f
|
|||
var tomClusterRoleBinding *rbacv1.ClusterRoleBinding
|
||||
var tomClusterRoleOnMember *rbacv1.ClusterRole
|
||||
var tomClusterRoleBindingOnMember *rbacv1.ClusterRoleBinding
|
||||
var f cmdutil.Factory
|
||||
|
||||
var (
|
||||
clusterName string
|
||||
|
@ -41,7 +44,6 @@ var _ = framework.SerialDescribe("Aggregated Kubernetes API Endpoint testing", f
|
|||
kubeConfigPath string
|
||||
clusterContext string
|
||||
controlPlane string
|
||||
karmadaConfig karmadactl.KarmadaConfig
|
||||
|
||||
secretStoreNamespace string
|
||||
)
|
||||
|
@ -52,9 +54,11 @@ var _ = framework.SerialDescribe("Aggregated Kubernetes API Endpoint testing", f
|
|||
kubeConfigPath = fmt.Sprintf("%s/.kube/%s.config", homeDir, clusterName)
|
||||
clusterContext = fmt.Sprintf("kind-%s", clusterName)
|
||||
controlPlane = fmt.Sprintf("%s-control-plane", clusterName)
|
||||
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
|
||||
secretStoreNamespace = "test-" + rand.String(RandomStrLength)
|
||||
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
|
@ -74,27 +78,20 @@ var _ = framework.SerialDescribe("Aggregated Kubernetes API Endpoint testing", f
|
|||
ginkgo.BeforeEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: secretStoreNamespace,
|
||||
ClusterName: clusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
ginkgo.AfterEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: secretStoreNamespace,
|
||||
ClusterName: clusterName,
|
||||
|
@ -102,7 +99,7 @@ var _ = framework.SerialDescribe("Aggregated Kubernetes API Endpoint testing", f
|
|||
ClusterKubeConfig: kubeConfigPath,
|
||||
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10,11 +10,12 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/test/e2e/framework"
|
||||
"github.com/karmada-io/karmada/test/helper"
|
||||
|
@ -23,11 +24,16 @@ import (
|
|||
var _ = ginkgo.Describe("FederatedResourceQuota auto-provision testing", func() {
|
||||
var frqNamespace, frqName string
|
||||
var federatedResourceQuota *policyv1alpha1.FederatedResourceQuota
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
frqNamespace = testNamespace
|
||||
frqName = federatedResourceQuotaPrefix + rand.String(RandomStrLength)
|
||||
federatedResourceQuota = helper.NewFederatedResourceQuota(frqNamespace, frqName)
|
||||
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.Context("create a federatedResourceQuota", func() {
|
||||
|
@ -81,11 +87,7 @@ var _ = ginkgo.Describe("FederatedResourceQuota auto-provision testing", func()
|
|||
|
||||
ginkgo.AfterEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
|
@ -93,7 +95,7 @@ var _ = ginkgo.Describe("FederatedResourceQuota auto-provision testing", func()
|
|||
ClusterKubeConfig: kubeConfigPath,
|
||||
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
@ -112,18 +114,14 @@ var _ = ginkgo.Describe("FederatedResourceQuota auto-provision testing", func()
|
|||
|
||||
ginkgo.It("federatedResourceQuota should be propagated to new joined clusters", func() {
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
|
||||
|
|
|
@ -311,7 +311,7 @@ var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels
|
|||
var policyName, policyNamespace string
|
||||
var deployment *appsv1.Deployment
|
||||
var policy *policyv1alpha1.PropagationPolicy
|
||||
var karmadaConfig karmadactl.KarmadaConfig
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
clusterName = "member-e2e-" + rand.String(3)
|
||||
|
@ -336,7 +336,9 @@ var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels
|
|||
ClusterNames: []string{clusterName},
|
||||
},
|
||||
})
|
||||
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
|
@ -356,16 +358,13 @@ var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels
|
|||
ginkgo.BeforeEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
@ -425,9 +424,6 @@ var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels
|
|||
|
||||
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
|
@ -435,7 +431,7 @@ var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels
|
|||
ClusterKubeConfig: kubeConfigPath,
|
||||
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
@ -448,7 +444,6 @@ var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.La
|
|||
var homeDir string
|
||||
var kubeConfigPath string
|
||||
var clusterContext string
|
||||
var karmadaConfig karmadactl.KarmadaConfig
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
|
@ -458,7 +453,6 @@ var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.La
|
|||
controlPlane = fmt.Sprintf("%s-control-plane", clusterName)
|
||||
clusterContext = fmt.Sprintf("kind-%s", clusterName)
|
||||
|
||||
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
|
@ -470,18 +464,14 @@ var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.La
|
|||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
// When a newly joined cluster is unready at the beginning, the scheduler will ignore it.
|
||||
|
@ -493,9 +483,6 @@ var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.La
|
|||
ginkgo.DeferCleanup(func() {
|
||||
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
|
@ -503,7 +490,7 @@ var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.La
|
|||
ClusterKubeConfig: kubeConfigPath,
|
||||
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.By(fmt.Sprintf("Deleting clusters: %s", clusterName), func() {
|
||||
|
|
|
@ -12,10 +12,11 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/test/e2e/framework"
|
||||
"github.com/karmada-io/karmada/test/helper"
|
||||
|
@ -24,10 +25,15 @@ import (
|
|||
var _ = ginkgo.Describe("[namespace auto-provision] namespace auto-provision testing", func() {
|
||||
var namespaceName string
|
||||
var namespace *corev1.Namespace
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
namespaceName = "karmada-e2e-ns-" + rand.String(3)
|
||||
namespace = helper.NewNamespace(namespaceName)
|
||||
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.When("create a namespace in karmada-apiserver", func() {
|
||||
|
@ -83,29 +89,21 @@ var _ = ginkgo.Describe("[namespace auto-provision] namespace auto-provision tes
|
|||
|
||||
ginkgo.BeforeEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
ginkgo.AfterEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: clusterName,
|
||||
|
@ -113,7 +111,7 @@ var _ = ginkgo.Describe("[namespace auto-provision] namespace auto-provision tes
|
|||
ClusterKubeConfig: kubeConfigPath,
|
||||
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
|
@ -18,7 +18,7 @@ import (
|
|||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl"
|
||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||
"github.com/karmada-io/karmada/test/e2e/framework"
|
||||
testhelper "github.com/karmada-io/karmada/test/helper"
|
||||
)
|
||||
|
@ -31,6 +31,7 @@ var _ = ginkgo.Describe("[cluster unjoined] reschedule testing", func() {
|
|||
var kubeConfigPath string
|
||||
var controlPlane string
|
||||
var clusterContext string
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
newClusterName = "member-e2e-" + rand.String(3)
|
||||
|
@ -38,6 +39,10 @@ var _ = ginkgo.Describe("[cluster unjoined] reschedule testing", func() {
|
|||
kubeConfigPath = fmt.Sprintf("%s/.kube/%s.config", homeDir, newClusterName)
|
||||
controlPlane = fmt.Sprintf("%s-control-plane", newClusterName)
|
||||
clusterContext = fmt.Sprintf("kind-%s", newClusterName)
|
||||
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
|
@ -84,18 +89,14 @@ var _ = ginkgo.Describe("[cluster unjoined] reschedule testing", func() {
|
|||
|
||||
ginkgo.It("deployment reschedule testing", func() {
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", newClusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: newClusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
|
||||
// wait for the current cluster status changing to true
|
||||
|
@ -115,16 +116,11 @@ var _ = ginkgo.Describe("[cluster unjoined] reschedule testing", func() {
|
|||
|
||||
ginkgo.By("unjoin target cluster", func() {
|
||||
klog.Infof("Unjoining cluster %q.", newClusterName)
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KubeConfig: fmt.Sprintf("%s/.kube/karmada.config", os.Getenv("HOME")),
|
||||
KarmadaContext: "karmada-apiserver",
|
||||
},
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: newClusterName,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
|
||||
|
@ -155,6 +151,7 @@ var _ = ginkgo.Describe("[cluster joined] reschedule testing", func() {
|
|||
var controlPlane string
|
||||
var clusterContext string
|
||||
var initClusterNames []string
|
||||
var f cmdutil.Factory
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
newClusterName = "member-e2e-" + rand.String(3)
|
||||
|
@ -162,6 +159,10 @@ var _ = ginkgo.Describe("[cluster joined] reschedule testing", func() {
|
|||
kubeConfigPath = fmt.Sprintf("%s/.kube/%s.config", homeDir, newClusterName)
|
||||
controlPlane = fmt.Sprintf("%s-control-plane", newClusterName)
|
||||
clusterContext = fmt.Sprintf("kind-%s", newClusterName)
|
||||
|
||||
defaultConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag().WithDiscoveryBurst(300).WithDiscoveryQPS(50.0)
|
||||
defaultConfigFlags.Context = &karmadaContext
|
||||
f = cmdutil.NewFactory(defaultConfigFlags)
|
||||
})
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
|
@ -173,16 +174,11 @@ var _ = ginkgo.Describe("[cluster joined] reschedule testing", func() {
|
|||
|
||||
ginkgo.AfterEach(func() {
|
||||
ginkgo.By(fmt.Sprintf("Unjoin clsters: %s", newClusterName), func() {
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandUnjoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KubeConfig: fmt.Sprintf("%s/.kube/karmada.config", os.Getenv("HOME")),
|
||||
KarmadaContext: "karmada-apiserver",
|
||||
},
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: newClusterName,
|
||||
}
|
||||
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunUnjoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.By(fmt.Sprintf("Deleting clusters: %s", newClusterName), func() {
|
||||
|
@ -228,18 +224,14 @@ var _ = ginkgo.Describe("[cluster joined] reschedule testing", func() {
|
|||
})
|
||||
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", newClusterName))
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: newClusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
|
||||
// wait for the current cluster status changing to true
|
||||
|
@ -291,18 +283,14 @@ var _ = ginkgo.Describe("[cluster joined] reschedule testing", func() {
|
|||
}, pollTimeout, pollInterval).Should(gomega.BeTrue())
|
||||
|
||||
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", newClusterName))
|
||||
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
||||
opts := karmadactl.CommandJoinOption{
|
||||
GlobalCommandOptions: options.GlobalCommandOptions{
|
||||
KarmadaContext: karmadaContext,
|
||||
},
|
||||
DryRun: false,
|
||||
ClusterNamespace: "karmada-cluster",
|
||||
ClusterName: newClusterName,
|
||||
ClusterContext: clusterContext,
|
||||
ClusterKubeConfig: kubeConfigPath,
|
||||
}
|
||||
err := karmadactl.RunJoin(karmadaConfig, opts)
|
||||
err := karmadactl.RunJoin(f, opts)
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
|
||||
// wait for the current cluster status changing to true
|
||||
|
|
Loading…
Reference in New Issue