Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Fix preflight check when specify kubeconfig in init cmd #413

Merged
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
6 changes: 2 additions & 4 deletions pkg/cmd/init/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,12 @@ func (o *Options) validate() error {
} else {
checks = append(checks,
preflight.HubApiServerCheck{
ClusterCtx: o.ClusteradmFlags.Context,
ConfigPath: "", // TODO(@Promacanthus): user custom kubeconfig path from command line arguments.
Config: o.ClusteradmFlags.KubectlFactory.ToRawKubeConfigLoader(),
},
preflight.ClusterInfoCheck{
Namespace: metav1.NamespacePublic,
ResourceName: preflight.BootstrapConfigMap,
ClusterCtx: o.ClusteradmFlags.Context,
ConfigPath: "", // TODO(@Promacanthus): user custom kubeconfig path from command line arguments.
Config: o.ClusteradmFlags.KubectlFactory.ToRawKubeConfigLoader(),
Client: kubeClient,
})
}
Expand Down
50 changes: 19 additions & 31 deletions pkg/cmd/init/preflight/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ func (c SingletonControlplaneCheck) Name() string {
}

type HubApiServerCheck struct {
ClusterCtx string // current-context in kubeconfig
ConfigPath string // kubeconfig file path
Config clientcmd.ClientConfig
}

func checkServer(server string) (warnings []string, errorList []error) {
Expand All @@ -62,7 +61,11 @@ func checkServer(server string) (warnings []string, errorList []error) {
}

func (c HubApiServerCheck) Check() (warnings []string, errorList []error) {
cluster, err := loadCurrentCluster(c.ClusterCtx, c.ConfigPath)
config, err := c.Config.RawConfig()
if err != nil {
return nil, []error{err}
}
cluster, err := loadCurrentCluster(config)
if err != nil {
return nil, []error{err}
}
Expand All @@ -77,8 +80,7 @@ func (c HubApiServerCheck) Name() string {
type ClusterInfoCheck struct {
Namespace string
ResourceName string
ClusterCtx string // current-context in kubeconfig
ConfigPath string // kubeconfig file path
Config clientcmd.ClientConfig
Client kubernetes.Interface
}

Expand All @@ -87,7 +89,14 @@ func (c ClusterInfoCheck) Check() (warnings []string, errorList []error) {
if err != nil {
if apierrors.IsNotFound(err) {
resourceNotFound := errors.New("no ConfigMap named cluster-info in the kube-public namespace, clusteradm will creates it")
cluster, err := loadCurrentCluster(c.ClusterCtx, c.ConfigPath)
config, err := c.Config.RawConfig()
if err != nil {
return nil, []error{err}
}
cluster, err := loadCurrentCluster(config)
if err != nil {
return nil, []error{err}
}
if err != nil {
return []string{resourceNotFound.Error()}, []error{err}
}
Expand All @@ -110,36 +119,15 @@ func (c ClusterInfoCheck) Name() string {

// loadCurrentCluster will load kubeconfig from file and return the current cluster.
// The default file path is ~/.kube/config.
func loadCurrentCluster(context string, kubeConfigFilePath string) (*api.Cluster, error) {
var (
currentConfig *clientcmdapi.Config
err error
)

if len(kubeConfigFilePath) == 0 {
currentConfig, err = clientcmd.NewDefaultClientConfigLoadingRules().Load()
if err != nil {
return nil, err
}
} else {
currentConfig, err = clientcmd.LoadFromFile(kubeConfigFilePath)
if err != nil {
return nil, errors.Wrapf(err, "failed to load kubeconfig file %s that already exists on disk", kubeConfigFilePath)
}
}
// load kubeconfig from file
// get the hub cluster context
if len(context) == 0 {
// use the current context from the kubeconfig
context = currentConfig.CurrentContext
}
func loadCurrentCluster(currentConfig clientcmdapi.Config) (*api.Cluster, error) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: update the description of this func

context := currentConfig.CurrentContext
currentCtx, exists := currentConfig.Contexts[context]
if !exists {
return nil, errors.Errorf("failed to find the given Current Context in Contexts of the kubeconfig file %s", kubeConfigFilePath)
return nil, errors.Errorf("failed to find the given Current Context in Contexts of the kubeconfig")
}
currentCluster, exists := currentConfig.Clusters[currentCtx.Cluster]
if !exists {
return nil, errors.Errorf("failed to find the given CurrentContext Cluster in Clusters of the kubeconfig file %s", kubeConfigFilePath)
return nil, errors.Errorf("failed to find the given CurrentContext Cluster in Clusters of the kubeconfig")
}
return currentCluster, nil
}
Expand Down
44 changes: 17 additions & 27 deletions pkg/cmd/init/preflight/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,18 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
fakekube "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
testinghelper "open-cluster-management.io/clusteradm/pkg/helpers/testing"
)

var (
currentContext = "ocm-hub"
kubeconfigFilePath = "testdata/kubeconfig"
)

func Test_loadCurrentCluster(t *testing.T) {
type args struct {
context string
kubeConfigFilePath string
}
tests := []struct {
Expand All @@ -33,7 +32,6 @@ func Test_loadCurrentCluster(t *testing.T) {
{
name: "load",
args: args{
context: currentContext,
kubeConfigFilePath: kubeconfigFilePath,
},
want: &api.Cluster{
Expand All @@ -51,7 +49,13 @@ func Test_loadCurrentCluster(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := loadCurrentCluster(tt.args.context, tt.args.kubeConfigFilePath)
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: tt.args.kubeConfigFilePath},
&clientcmd.ConfigOverrides{}).RawConfig()
if err != nil {
t.Error(err)
}
got, err := loadCurrentCluster(config)
if (err != nil) != tt.wantErr {
t.Errorf("loadCurrentCluster() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down Expand Up @@ -148,7 +152,6 @@ func Test_createClusterInfo(t *testing.T) {

func TestHubApiServerCheck_Check(t *testing.T) {
type fields struct {
ClusterCtx string
ConfigPath string
}
tests := []struct {
Expand All @@ -157,30 +160,19 @@ func TestHubApiServerCheck_Check(t *testing.T) {
wantWarnings []string
wantErrorList []error
}{
{
name: "empty context",
fields: fields{
ClusterCtx: "",
ConfigPath: kubeconfigFilePath,
},
wantWarnings: []string{"Hub Api Server is a domain name, maybe you should set HostAlias in klusterlet"},
wantErrorList: nil,
},
{
name: "no kubeconfig file",
fields: fields{
ClusterCtx: currentContext,
ConfigPath: "invalid_path",
},
wantWarnings: nil,
wantErrorList: []error{
errors.New("failed to load kubeconfig file invalid_path that already exists on disk: open invalid_path: no such file or directory"),
errors.New("stat invalid_path: no such file or directory"),
},
},
{
name: "hub api server with domain",
fields: fields{
ClusterCtx: currentContext,
ConfigPath: kubeconfigFilePath,
},
wantWarnings: []string{"Hub Api Server is a domain name, maybe you should set HostAlias in klusterlet"},
Expand All @@ -189,7 +181,6 @@ func TestHubApiServerCheck_Check(t *testing.T) {
{
name: "hub api server with ip",
fields: fields{
ClusterCtx: currentContext,
ConfigPath: "testdata/kubeconfig_ip",
},
wantWarnings: nil,
Expand All @@ -198,9 +189,11 @@ func TestHubApiServerCheck_Check(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: tt.fields.ConfigPath},
&clientcmd.ConfigOverrides{})
c := HubApiServerCheck{
ClusterCtx: tt.fields.ClusterCtx,
ConfigPath: tt.fields.ConfigPath,
Config: config,
}
gotWarnings, gotErrorList := c.Check()
testinghelper.AssertWarnings(t, gotWarnings, tt.wantWarnings)
Expand All @@ -213,7 +206,6 @@ func TestClusterInfoCheck_Check(t *testing.T) {
type fields struct {
Namespace string
ResourceName string
ClusterCtx string
ConfigPath string
Object []runtime.Object
}
Expand All @@ -230,7 +222,6 @@ func TestClusterInfoCheck_Check(t *testing.T) {
fields: fields{
Namespace: metav1.NamespacePublic,
ResourceName: BootstrapConfigMap,
ClusterCtx: currentContext,
ConfigPath: kubeconfigFilePath,
Object: []runtime.Object{newConfigMap(BootstrapConfigMap, metav1.NamespacePublic, newKubeConfig())},
},
Expand All @@ -244,7 +235,6 @@ func TestClusterInfoCheck_Check(t *testing.T) {
fields: fields{
Namespace: metav1.NamespacePublic,
ResourceName: BootstrapConfigMap,
ClusterCtx: currentContext,
ConfigPath: kubeconfigFilePath,
Object: []runtime.Object{newConfigMap(BootstrapConfigMap, metav1.NamespacePublic, nil)},
},
Expand All @@ -258,7 +248,6 @@ func TestClusterInfoCheck_Check(t *testing.T) {
fields: fields{
Namespace: metav1.NamespacePublic,
ResourceName: BootstrapConfigMap,
ClusterCtx: currentContext,
ConfigPath: kubeconfigFilePath,
Object: []runtime.Object{},
},
Expand All @@ -271,12 +260,13 @@ func TestClusterInfoCheck_Check(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := fakekube.NewSimpleClientset(tt.fields.Object...)

config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: tt.fields.ConfigPath},
&clientcmd.ConfigOverrides{})
c := ClusterInfoCheck{
Namespace: tt.fields.Namespace,
ResourceName: tt.fields.ResourceName,
ClusterCtx: tt.fields.ClusterCtx,
ConfigPath: tt.fields.ConfigPath,
Config: config,
Client: client,
}
gotWarnings, gotErrorList := c.Check()
Expand Down
Loading