-
Notifications
You must be signed in to change notification settings - Fork 1
/
kind.go
138 lines (108 loc) · 4.49 KB
/
kind.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package kubernetes
import (
"os"
"os/exec"
"strings"
"github.com/atlarge-research/apate/pkg/kubernetes/kubeconfig"
"github.com/atlarge-research/apate/pkg/env"
"github.com/pkg/errors"
"sigs.k8s.io/kind/cmd/kind/app"
"sigs.k8s.io/kind/pkg/cmd"
"sigs.k8s.io/kind/pkg/cmd/kind"
)
// KinDClusterManager is a struct which implements ClusterManager by creating a kind cluster.
type KinDClusterManager struct{}
// GetKubeConfig validates the cluster name, creates the Kind cluster and returns its kubeconfig.
func (k *KinDClusterManager) GetKubeConfig() (*kubeconfig.KubeConfig, error) {
if env.ControlPlaneEnv().KinDClusterName == "" {
return nil, errors.New("trying to create a KinDClusterManager cluster with an empty name")
}
err := k.deleteCluster()
if err != nil {
return nil, errors.Wrap(err, "failure to delete kind cluster to prepare for creating a new one")
}
if err = k.prepareCluster(); err != nil {
return nil, errors.Wrapf(err, "failed to start kind cluster. Possible cleanup error: %v", k.deleteCluster())
}
err = k.writeKubeConfig()
if err != nil {
err = errors.Wrap(err, "failed to write kubeconfig")
return nil, errors.Wrapf(k.deleteCluster(), "failed to delete kind cluster to clean up earlier failure (%v)", err)
}
kubeConfig, err := kubeconfig.FromPath(env.ControlPlaneEnv().KubeConfigLocation)
if err != nil {
return nil, errors.Wrap(err, "failed to read kubeconfig")
}
return kubeConfig, nil
}
// Shutdown deletes the KinD cluster.
func (k *KinDClusterManager) Shutdown(*Cluster) error {
return errors.Wrap(k.deleteCluster(), "failed to delete kind cluster")
}
func (k *KinDClusterManager) writeKubeConfig() error {
kubeConfigLocation := env.ControlPlaneEnv().KubeConfigLocation
if env.ControlPlaneEnv().UseDockerHostname {
// Replace any https address by the "docker" hostname.
// This is used in CI, where the control plane had a 172.17.0.0/16 address, and the KinDClusterManager cluster a 172.18.0.0/16 address
// which was only reachable using "docker"s as hostname.
// #nosec
cmdSed := exec.Command("sed", "-i", "-r", "s/https:\\/\\/(.+):/https:\\/\\/docker:/g", kubeConfigLocation)
return errors.Wrap(cmdSed.Run(), "failed to apply sed to the kube config")
}
// Update kube config to use internal
return errors.Wrapf(k.useInternalKubeConfig(env.ControlPlaneEnv().KinDClusterName, kubeConfigLocation), "failed to use internal Kubeconfig")
}
func (k *KinDClusterManager) prepareCluster() error {
// TODO: use our own/a global logger?
logger := cmd.NewLogger()
args := []string{
"create",
"cluster",
}
args = append(args, "--name", strings.ToLower(env.ControlPlaneEnv().KinDClusterName))
args = append(args, "--kubeconfig", env.ControlPlaneEnv().KubeConfigLocation)
args = append(args, "--config", env.ControlPlaneEnv().ManagerConfigLocation)
if env.ControlPlaneEnv().DebugEnabled {
// This number is also used in KinD internally to denote trace.
args = append(args, "--verbosity=2147483647")
}
// Set up a cluster
// Can't simply call Run as is done in Delete since we want to get error messages back.
// Run just logs the error and returns.
c := kind.NewCommand(logger, cmd.StandardIOStreams())
c.SetArgs(args)
return errors.Wrapf(c.Execute(), "failed to create kind cluster with kind %v", strings.Join(args, " "))
}
func (k *KinDClusterManager) useInternalKubeConfig(name string, kubeConfigLocation string) error {
logger := cmd.NewLogger()
args := []string{
"get",
"kubeconfig",
}
args = append(args, "--name", strings.ToLower(name))
args = append(args, "--internal")
cfg, err := os.Create(kubeConfigLocation)
if err != nil {
return errors.Wrapf(err, "failed to create file for Kubeconfig at %v", kubeConfigLocation)
}
c := kind.NewCommand(logger, cmd.IOStreams{
In: os.Stdin,
Out: cfg,
ErrOut: os.Stderr,
})
c.SetArgs(args)
return errors.Wrapf(c.Execute(), "failed run kind %v to retrieve internal Kubeconfig", strings.Join(args, " "))
}
func (k *KinDClusterManager) deleteCluster() error {
// TODO: use our own/a global logger?
logger := cmd.NewLogger()
args := []string{
"delete",
"cluster",
}
args = append(args, "--name", strings.ToLower(env.ControlPlaneEnv().KinDClusterName))
// Deletes the cluster
// As far as I could test this call never errors (it just doesn't do anything
// when the cluster doesn't exist) so I don't think the system used in CreateCluster is necessary.
return errors.Wrapf(app.Run(logger, cmd.StandardIOStreams(), args), "failed to run kind %v to delete cluster", strings.Join(args, " "))
}