-
Notifications
You must be signed in to change notification settings - Fork 200
/
kind.go
171 lines (139 loc) · 4.9 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package tests
import (
"bytes"
"fmt"
"html/template"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"path/filepath"
"get.porter.sh/porter/mage/docker"
"get.porter.sh/porter/mage/tools"
porterpkg "get.porter.sh/porter/pkg"
"github.com/carolynvs/magex/mgx"
"github.com/carolynvs/magex/pkg"
"github.com/carolynvs/magex/shx"
"github.com/magefile/mage/mg"
"github.com/pkg/errors"
)
const (
// Name of the KIND cluster used for testing
DefaultKindClusterName = "porter"
// Relative location of the KUBECONFIG for the test cluster
Kubeconfig = "kind.config"
)
var (
must = shx.CommandBuilder{StopOnError: true}
)
// Ensure that the test KIND cluster is up.
func EnsureTestCluster() {
mg.Deps(EnsureKubectl)
if !useCluster() {
CreateTestCluster()
}
mgx.Must(docker.StartDockerRegistry())
}
// get the config of the current kind cluster, if available
func getClusterConfig() (kubeconfig string, ok bool) {
contents, err := shx.OutputE("kind", "get", "kubeconfig", "--name", getKindClusterName())
return contents, err == nil
}
// setup environment to use the current kind cluster, if available
func useCluster() bool {
contents, ok := getClusterConfig()
if ok {
log.Println("Reusing existing kind cluster")
userKubeConfig, _ := filepath.Abs(os.Getenv("KUBECONFIG"))
currentKubeConfig := filepath.Join(pwd(), Kubeconfig)
if userKubeConfig != currentKubeConfig {
fmt.Printf("ATTENTION! You should set your KUBECONFIG to match the cluster used by this project\n\n\texport KUBECONFIG=%s\n\n", currentKubeConfig)
}
os.Setenv("KUBECONFIG", currentKubeConfig)
err := ioutil.WriteFile(Kubeconfig, []byte(contents), porterpkg.FileModeWritable)
mgx.Must(errors.Wrapf(err, "error writing %s", Kubeconfig))
return true
}
return false
}
func setClusterNamespace(name string) {
must.RunE("kubectl", "config", "set-context", "--current", "--namespace", name)
}
// Create a KIND cluster named porter.
func CreateTestCluster() {
mg.Deps(tools.EnsureKind, docker.RestartDockerRegistry)
// Determine host ip to populate kind config api server details
// https://kind.sigs.k8s.io/docs/user/configuration/#api-server
addrs, err := net.InterfaceAddrs()
mgx.Must(errors.Wrap(err, "could not get a list of network interfaces"))
var ipAddress string
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
fmt.Println("Current IP address : ", ipnet.IP.String())
ipAddress = ipnet.IP.String()
break
}
}
}
os.Setenv("KUBECONFIG", filepath.Join(pwd(), Kubeconfig))
kindCfgPath := "mage/tests/kind.config.yaml"
kindCfg, err := ioutil.ReadFile(kindCfgPath)
mgx.Must(errors.Wrapf(err, "error reading %s", kindCfgPath))
kindCfgTmpl, err := template.New("kind.config.yaml").Parse(string(kindCfg))
mgx.Must(errors.Wrapf(err, "error parsing EnsureKind config template %s", kindCfgPath))
var kindCfgContents bytes.Buffer
kindCfgData := struct {
Address string
}{
Address: ipAddress,
}
err = kindCfgTmpl.Execute(&kindCfgContents, kindCfgData)
err = ioutil.WriteFile("kind.config.yaml", kindCfgContents.Bytes(), porterpkg.FileModeWritable)
mgx.Must(errors.Wrap(err, "could not write kind config file"))
defer os.Remove("kind.config.yaml")
must.Command("kind", "create", "cluster", "--name", getKindClusterName(), "--config", "kind.config.yaml").
Env("KIND_EXPERIMENTAL_DOCKER_NETWORK=" + docker.DefaultNetworkName).Run()
// Document the local registry
kubectl("apply", "-f", "mage/tests/local-registry.yaml").Run()
}
// Delete the KIND cluster named porter.
func DeleteTestCluster() {
mg.Deps(tools.EnsureKind)
must.RunE("kind", "delete", "cluster", "--name", getKindClusterName())
}
func kubectl(args ...string) shx.PreparedCommand {
kubeconfig := fmt.Sprintf("KUBECONFIG=%s", os.Getenv("KUBECONFIG"))
return must.Command("kubectl", args...).Env(kubeconfig)
}
// Ensure kubectl is installed.
func EnsureKubectl() {
if ok, _ := pkg.IsCommandAvailable("kubectl", ""); ok {
return
}
versionURL := "https://storage.googleapis.com/kubernetes-release/release/stable.txt"
versionResp, err := http.Get(versionURL)
mgx.Must(errors.Wrapf(err, "unable to determine the latest version of kubectl"))
if versionResp.StatusCode > 299 {
mgx.Must(errors.Errorf("GET %s (%d): %s", versionURL, versionResp.StatusCode, versionResp.Status))
}
defer versionResp.Body.Close()
kubectlVersion, err := ioutil.ReadAll(versionResp.Body)
mgx.Must(errors.Wrapf(err, "error reading response from %s", versionURL))
kindURL := "https://storage.googleapis.com/kubernetes-release/release/{{.VERSION}}/bin/{{.GOOS}}/{{.GOARCH}}/kubectl{{.EXT}}"
mgx.Must(pkg.DownloadToGopathBin(kindURL, "kubectl", string(kubectlVersion)))
}
func pwd() string {
wd, err := os.Getwd()
if err != nil {
panic(errors.Wrap(err, "pwd failed"))
}
return wd
}
func getKindClusterName() string {
if name, ok := os.LookupEnv("KIND_NAME"); ok {
return name
}
return DefaultKindClusterName
}