Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/api/app/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,17 @@ func run(ctx context.Context, opts *options.Options) error {
client.WithUserAgent(environment.UserAgent()),
client.WithKubeconfig(opts.KarmadaKubeConfig),
client.WithKubeContext(opts.KarmadaContext),
client.WithMasterURL(opts.KarmadaAPIServerURL),
client.WithToken(opts.KarmadaToken),
client.WithInsecureTLSSkipVerify(opts.SkipKarmadaApiserverTLSVerify),
)

client.InitKubeConfig(
client.WithUserAgent(environment.UserAgent()),
client.WithKubeconfig(opts.KubeConfig),
client.WithKubeContext(opts.KubeContext),
client.WithMasterURL(opts.KubeAPIServerURL),
client.WithToken(opts.KubeToken),
client.WithInsecureTLSSkipVerify(opts.SkipKubeApiserverTLSVerify),
)
ensureAPIServerConnectionOrDie()
Expand Down
14 changes: 14 additions & 0 deletions cmd/api/app/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ type Options struct {
DisableCSRFProtection bool
OpenAPIEnabled bool

// KubeAPIServerURL is the URL of the host cluster APIServer.
KubeAPIServerURL string
// KubeToken is the bearer token for accessing the host cluster APIServer.
KubeToken string
// KarmadaAPIServerURL is the URL of the Karmada APIServer.
KarmadaAPIServerURL string
// KarmadaToken is the bearer token for accessing the Karmada APIServer.
KarmadaToken string

// MCP related options
EnableMCP bool
MCPTransportMode string
Expand Down Expand Up @@ -76,6 +85,11 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.DisableCSRFProtection, "disable-csrf-protection", false, "allows disabling CSRF protection")
fs.BoolVar(&o.OpenAPIEnabled, "openapi-enabled", false, "enables OpenAPI v2 endpoint under '/apidocs.json'")

fs.StringVar(&o.KubeAPIServerURL, "kube-apiserver-url", "", "URL of the host cluster APIServer.")
fs.StringVar(&o.KubeToken, "kube-token", "", "Bearer token for accessing the host cluster APIServer.")
fs.StringVar(&o.KarmadaAPIServerURL, "karmada-apiserver-url", "", "URL of the Karmada APIServer.")
fs.StringVar(&o.KarmadaToken, "karmada-token", "", "Bearer token for accessing the Karmada APIServer.")

// MCP related flags
fs.BoolVar(&o.EnableMCP, "enable-mcp", false, "Enable MCP (Model Context Protocol) integration")
fs.StringVar(&o.MCPTransportMode, "mcp-transport-mode", "stdio", "MCP transport mode: stdio or sse")
Expand Down
80 changes: 72 additions & 8 deletions pkg/client/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ var (
type configBuilder struct {
kubeconfigPath string
kubeContext string
masterURL string
token string
insecure bool
userAgent string
}
Expand Down Expand Up @@ -75,6 +77,20 @@ func WithKubeContext(kubecontext string) Option {
}
}

// WithToken is an option to set the bearer token.
func WithToken(token string) Option {
return func(c *configBuilder) {
c.token = token
}
}

// WithMasterURL is an option to set the master URL.
func WithMasterURL(url string) Option {
return func(c *configBuilder) {
c.masterURL = url
}
}

// WithInsecureTLSSkipVerify is an option to set the insecure tls skip verify.
func WithInsecureTLSSkipVerify(insecure bool) Option {
return func(c *configBuilder) {
Expand All @@ -92,17 +108,41 @@ func newConfigBuilder(options ...Option) *configBuilder {
return builder
}

func (in *configBuilder) buildRestConfig() (*rest.Config, error) {
if len(in.kubeconfigPath) == 0 {
return nil, errors.New("must specify kubeconfig")
func (in *configBuilder) validate() error {
if len(in.kubeconfigPath) == 0 && !in.hasMasterURLAndToken() {
return errors.New("must specify kubeconfig or masterURL and token")
}
klog.InfoS("Using kubeconfig", "kubeconfig", in.kubeconfigPath)
return nil
}

restConfig, err := LoadRestConfig(in.kubeconfigPath, in.kubeContext)
if err != nil {
func (in *configBuilder) hasMasterURLAndToken() bool {
return len(in.masterURL) > 0 && len(in.token) > 0
}

func (in *configBuilder) buildRestConfig() (*rest.Config, error) {
if err := in.validate(); err != nil {
return nil, err
}

var restConfig *rest.Config
var err error
if in.hasMasterURLAndToken() {
klog.InfoS("Using masterURL and token")
restConfig = &rest.Config{
Host: in.masterURL,
BearerToken: in.token,
TLSClientConfig: rest.TLSClientConfig{
Insecure: in.insecure,
},
}
} else {
klog.InfoS("Using kubeconfig", "kubeconfig", in.kubeconfigPath)
restConfig, err = LoadRestConfig(in.kubeconfigPath, in.kubeContext)
if err != nil {
return nil, err
}
}

restConfig.QPS = DefaultQPS
restConfig.Burst = DefaultBurst
// TODO: make clear that why karmada apiserver seems only can use application/json, however kubernetest apiserver can use "application/vnd.kubernetes.protobuf"
Expand All @@ -113,9 +153,33 @@ func (in *configBuilder) buildRestConfig() (*rest.Config, error) {
}

func (in *configBuilder) buildAPIConfig() (*clientcmdapi.Config, error) {
if len(in.kubeconfigPath) == 0 {
return nil, errors.New("must specify kubeconfig")
if err := in.validate(); err != nil {
return nil, err
}

if in.hasMasterURLAndToken() {
return &clientcmdapi.Config{
Clusters: map[string]*clientcmdapi.Cluster{
ClusterName: {
Server: in.masterURL,
InsecureSkipTLSVerify: in.insecure,
},
},
AuthInfos: map[string]*clientcmdapi.AuthInfo{
AuthInfoName: {
Token: in.token,
},
},
Contexts: map[string]*clientcmdapi.Context{
ContextName: {
Cluster: ClusterName,
AuthInfo: AuthInfoName,
},
},
CurrentContext: ContextName,
}, nil
Comment on lines +161 to +180
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The strings "cluster", "user", and "context" are hardcoded here. This can make the code harder to maintain and can lead to typos.

It's recommended to define these as constants, similar to how DefaultCmdConfigName is used in pkg/client/auth.go. Using constants would also improve consistency within the package.

}

klog.InfoS("Using kubeconfig", "kubeconfig", in.kubeconfigPath)
apiConfig, err := LoadAPIConfig(in.kubeconfigPath, in.kubeContext)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pkg/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ const (
DefaultUserAgent = "dashboard"
// DefaultCmdConfigName is the default cluster/context/auth name to be set in clientcmd config
DefaultCmdConfigName = "kubernetes"
// ContextName is the name of the context.
ContextName = "context"
// ClusterName is the name of the cluster.
ClusterName = "cluster"
// AuthInfoName is the name of the auth info.
AuthInfoName = "user"
// ImpersonateUserHeader is the header name to identify username to act as.
ImpersonateUserHeader = "Impersonate-User"
// ImpersonateGroupHeader is the header name to identify group name to act as.
Expand Down