diff --git a/phase/get_kubeconfig.go b/phase/get_kubeconfig.go index 93853c08..702b1eb5 100644 --- a/phase/get_kubeconfig.go +++ b/phase/get_kubeconfig.go @@ -4,10 +4,9 @@ import ( "fmt" "strings" - "github.com/k0sproject/dig" - "github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster" + "github.com/k0sproject/rig/exec" + log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" - "k8s.io/client-go/tools/clientcmd" ) // GetKubeconfig is a phase to get and dump the admin kubeconfig @@ -16,33 +15,19 @@ type GetKubeconfig struct { APIAddress string } +type kubeconfig struct { + Clusters []struct { + Cluster struct { + Server string `yaml:"server"` + } `yaml:"cluster"` + } `yaml:"clusters"` +} + // Title for the phase func (p *GetKubeconfig) Title() string { return "Get admin kubeconfig" } -var readKubeconfig = func(h *cluster.Host) (string, error) { - return h.Configurer.ReadFile(h, h.Configurer.KubeconfigPath(h, h.K0sDataDir())) -} - -var k0sConfig = func(h *cluster.Host) (dig.Mapping, error) { - cfgContent, err := h.Configurer.ReadFile(h, h.Configurer.K0sConfigPath()) - if err != nil { - return nil, fmt.Errorf("read k0s config from host: %w", err) - } - - var cfg dig.Mapping - if err := yaml.Unmarshal([]byte(cfgContent), &cfg); err != nil { - return nil, fmt.Errorf("unmarshal k0s config: %w", err) - } - - if err != nil { - return nil, fmt.Errorf("parse k0s config: %w", err) - } - - return cfg, nil -} - func (p *GetKubeconfig) DryRun() error { p.DryMsg(p.Config.Spec.Hosts.Controllers()[0], "get admin kubeconfig") return nil @@ -50,74 +35,31 @@ func (p *GetKubeconfig) DryRun() error { // Run the phase func (p *GetKubeconfig) Run() error { - h := p.Config.Spec.Hosts.Controllers()[0] - - cfg, err := k0sConfig(h) - if err != nil { - return err - } + h := p.Config.Spec.K0sLeader() - output, err := readKubeconfig(h) + output, err := h.ExecOutput(h.Configurer.K0sCmdf("kubeconfig admin"), exec.Sudo(h)) if err != nil { return fmt.Errorf("read kubeconfig from host: %w", err) } - if p.APIAddress == "" { - // the controller admin.conf is aways pointing to localhost, thus we need to change the address - // something usable from outside - address := h.Address() - if a, ok := cfg.Dig("spec", "api", "externalAddress").(string); ok && a != "" { - address = a + if p.APIAddress != "" { + log.Debugf("%s: replacing api address with %v", h, p.APIAddress) + kubeconf := kubeconfig{} + if err := yaml.Unmarshal([]byte(output), &kubeconf); err != nil { + return fmt.Errorf("unmarshal kubeconfig: %w", err) } - - port := 6443 - if p, ok := cfg.Dig("spec", "api", "port").(int); ok && p != 0 { - port = p + if len(kubeconf.Clusters) == 0 { + return fmt.Errorf("no clusters found in kubeconfig") } - - if strings.Contains(address, ":") { - p.APIAddress = fmt.Sprintf("https://[%s]:%d", address, port) - } else { - p.APIAddress = fmt.Sprintf("https://%s:%d", address, port) + server := kubeconf.Clusters[0].Cluster.Server + if server == "" { + return fmt.Errorf("no server found in kubeconfig") } + log.Debugf("%s: replacing %v with %v", h, server, p.APIAddress) + output = strings.ReplaceAll(output, server, p.APIAddress) } - cfgString, err := kubeConfig(output, p.Config.Metadata.Name, p.APIAddress) - if err != nil { - return err - } - - p.Config.Metadata.Kubeconfig = cfgString + p.Config.Metadata.Kubeconfig = output return nil } - -// kubeConfig reads in the raw kubeconfig and changes the given address -// and cluster name into it -func kubeConfig(raw string, name string, address string) (string, error) { - cfg, err := clientcmd.Load([]byte(raw)) - if err != nil { - return "", err - } - - cfg.Clusters[name] = cfg.Clusters["local"] - delete(cfg.Clusters, "local") - cfg.Clusters[name].Server = address - - cfg.Contexts[name] = cfg.Contexts["Default"] - delete(cfg.Contexts, "Default") - cfg.Contexts[name].Cluster = name - cfg.Contexts[name].AuthInfo = "admin" - - cfg.CurrentContext = name - - cfg.AuthInfos["admin"] = cfg.AuthInfos["user"] - delete(cfg.AuthInfos, "user") - - out, err := clientcmd.Write(*cfg) - if err != nil { - return "", err - } - - return string(out), nil -} diff --git a/phase/get_kubeconfig_test.go b/phase/get_kubeconfig_test.go deleted file mode 100644 index cb42fc64..00000000 --- a/phase/get_kubeconfig_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package phase - -import ( - "strings" - "testing" - - "github.com/k0sproject/dig" - "github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1" - "github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster" - "github.com/k0sproject/rig" - "github.com/stretchr/testify/require" - "k8s.io/client-go/tools/clientcmd" -) - -func fakeReader(h *cluster.Host) (string, error) { - return strings.ReplaceAll(`apiVersion: v1 -clusters: -- cluster: - server: https://localhost:6443 - name: local -contexts: -- context: - cluster: local - user: user - name: Default -current-context: Default -kind: Config -preferences: {} -users: -- name: user - user: -`, "\t", " "), nil -} - -func TestGetKubeconfig(t *testing.T) { - cfg := &v1beta1.Cluster{ - Metadata: &v1beta1.ClusterMetadata{ - Name: "k0s", - }, - Spec: &cluster.Spec{ - K0s: &cluster.K0s{Config: dig.Mapping{}}, - Hosts: []*cluster.Host{ - {Role: "controller", Connection: rig.Connection{SSH: &rig.SSH{Address: "10.0.0.1", Port: 22}}}, - }, - }, - } - - origReadKubeconfig := readKubeconfig - defer func() { readKubeconfig = origReadKubeconfig }() - readKubeconfig = fakeReader - - origK0sConfig := k0sConfig - defer func() { k0sConfig = origK0sConfig }() - k0sConfig = func(h *cluster.Host) (dig.Mapping, error) { - return cfg.Spec.K0s.Config, nil - } - - p := GetKubeconfig{GenericPhase: GenericPhase{Config: cfg}} - require.NoError(t, p.Run()) - conf, err := clientcmd.Load([]byte(cfg.Metadata.Kubeconfig)) - require.NoError(t, err) - require.Equal(t, "https://10.0.0.1:6443", conf.Clusters["k0s"].Server) - - cfg.Spec.Hosts[0].Connection.SSH.Address = "abcd:efgh:ijkl:mnop" - p.APIAddress = "" - require.NoError(t, p.Run()) - conf, err = clientcmd.Load([]byte(cfg.Metadata.Kubeconfig)) - require.NoError(t, err) - require.Equal(t, "https://[abcd:efgh:ijkl:mnop]:6443", conf.Clusters["k0s"].Server) -}