You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.2 KiB

2 years ago
package framework
import (
"bytes"
"github.com/spf13/viper"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/client-go/tools/clientcmd"
"os"
"os/exec"
)
type KindConfig struct {
Name string `json:"name"` // 创建 cluster 的参数使用
Config string `json:"config"` // 这个 config string 会当作 kind create cluster --config 中的内容传入
Retain bool `json:"retain"` // 在执行完测试任务后,是否保留
}
type KindProvider struct{}
// 检查这个对象是否实现了接口ClusterProvider。这种方法可以也推荐在一切实现某个接口的对象下来检查。
var _ ClusterProvider = &KindProvider{}
2 years ago
func (k *KindProvider) Validate(config *Config) error {
// 1. 获取配置
if config == nil {
return field.Invalid(field.NewPath("config"), nil, "Not inital config object")
}
kindConfig := config.Sub("cluster").Sub("kind")
root := field.NewPath("cluster", "kind")
if kindConfig == nil {
return field.Invalid(root, nil, "Config does not have kind configuration")
}
// 2. 检查必要项
if kindConfig.GetString("name") == "" {
// 3. 设置默认项
kindConfig.Set("name", "e2e")
}
return nil
}
func (k *KindProvider) Deploy(config *Config) (ClusterConfig, error) {
clusterConfig := ClusterConfig{}
// 1. 获取配置
kindConfig, err := getKindConfig(config.Sub("cluster").Sub("kind"))
if err != nil {
return clusterConfig, err
}
var kubeConfigFile string
// 2. 确认是否存在 cluster
if kindConfig.Name != "" {
// 判断集群是否存在的命令kind get kubeconfig --name <kindConfig.Name>
output := &bytes.Buffer{} // 用来接受配置文件的内容
cmd := exec.Command(
"kind",
"get",
"kubeconfig",
"--name", kindConfig.Name)
cmd.Stdout = output
cmd.Stderr = config.Stderr
if err := cmd.Run(); err == nil {
// 2.1 存在,生成访问 k8s 集群的config文件
if err := os.WriteFile(KubeconfigTempFile, output.Bytes(), os.ModePerm); err != nil {
return clusterConfig, err
}
kubeConfigFile = KubeconfigTempFile
}
}
if kubeConfigFile == "" {
// 2.2 不存在,创建,并返回访问 k8s 集群的config文件
// 创建集群的命令kind create cluster --kubeconfig <KubeconfigTempFile> --config <KindConfigTempFile>
subCommand := []string{"create", "cluster", "--kubeconfig", KubeconfigTempFile}
if kindConfig.Config != "" {
if err := os.WriteFile(KindConfigTempFile,
[]byte(kindConfig.Config),
os.ModePerm); err != nil {
return clusterConfig, err
}
defer func() { _ = os.Remove(KindConfigTempFile) }()
subCommand = append(subCommand, "--config", KindConfigTempFile)
}
subCommand = append(subCommand, "--name", kindConfig.Name)
2 years ago
cmd := exec.Command("kind", subCommand...)
cmd.Stdout = config.Stdout
cmd.Stderr = config.Stderr
if err := cmd.Run(); err != nil {
return clusterConfig, err
}
kubeConfigFile = KubeconfigTempFile
2 years ago
}
defer func() { _ = os.Remove(kubeConfigFile) }() // 退出函数之前清空kubeconfig 文件内容。
// 3. 创建 Cluster config
clusterConfig.Name = kindConfig.Name
if clusterConfig.Rest, err = clientcmd.BuildConfigFromFlags("", kubeConfigFile); err != nil {
return clusterConfig, err
2 years ago
}
clusterConfig.MasterIP = clusterConfig.Rest.Host
2 years ago
return clusterConfig, nil
}
func (k *KindProvider) Destroy(config *Config) error {
// 1. 根据 config 判断时候保留集群
// 1.1 获取配置
kindConfig, err := getKindConfig(config.Sub("cluster").Sub("kind"))
if err != nil {
return err
}
if kindConfig.Retain {
// 2. 保留就退出
return nil
}
// 3. 不保留就销毁
// 销毁集群的命令kind delete cluster --name <kindConfig.Name>
cmd := exec.Command("kind",
"delete",
"cluster",
"--name", kindConfig.Name)
cmd.Stdout = config.Stdout
cmd.Stderr = config.Stderr
if err := cmd.Run(); err != nil {
return err
}
return nil
}
func getKindConfig(config *viper.Viper) (KindConfig, error) {
kindConfig := KindConfig{}
if config == nil {
return kindConfig, field.Invalid(
field.NewPath("cluster", "kind"),
nil,
"Not inital config object")
}
if err := config.Unmarshal(&kindConfig); err != nil {
return kindConfig, err
}
if kindConfig.Name == "" {
kindConfig.Name = "e2e"
}
return kindConfig, nil
}