-
Notifications
You must be signed in to change notification settings - Fork 74
/
get_kubeconfig.go
123 lines (97 loc) · 2.84 KB
/
get_kubeconfig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package phase
import (
"fmt"
"strings"
"github.com/k0sproject/dig"
"github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster"
"gopkg.in/yaml.v2"
"k8s.io/client-go/tools/clientcmd"
)
// GetKubeconfig is a phase to get and dump the admin kubeconfig
type GetKubeconfig struct {
GenericPhase
APIAddress string
}
// 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
}
output, err := readKubeconfig(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
}
port := 6443
if p, ok := cfg.Dig("spec", "api", "port").(int); ok && p != 0 {
port = p
}
if strings.Contains(address, ":") {
p.APIAddress = fmt.Sprintf("https://[%s]:%d", address, port)
} else {
p.APIAddress = fmt.Sprintf("https://%s:%d", address, port)
}
}
cfgString, err := kubeConfig(output, p.Config.Metadata.Name, p.APIAddress)
if err != nil {
return err
}
p.Config.Metadata.Kubeconfig = cfgString
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
}