Skip to content

Commit

Permalink
Simplify kubeconfig retrieval by using k0s kubeconfig command (#720)
Browse files Browse the repository at this point in the history
* Simplify kubeconfig retrieval by using k0s kubeconfig command

Signed-off-by: Kimmo Lehto <[email protected]>

* Restore --kubeconfig-api-address functionality

Signed-off-by: Kimmo Lehto <[email protected]>

---------

Signed-off-by: Kimmo Lehto <[email protected]>
  • Loading branch information
kke authored Jun 10, 2024
1 parent aaa01d2 commit 1afb01f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 153 deletions.
108 changes: 25 additions & 83 deletions phase/get_kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,108 +15,51 @@ 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
}

// 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
}
70 changes: 0 additions & 70 deletions phase/get_kubeconfig_test.go

This file was deleted.

0 comments on commit 1afb01f

Please sign in to comment.