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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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{}
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)
cmd := exec.Command("kind", subCommand...)
cmd.Stdout = config.Stdout
cmd.Stderr = config.Stderr
if err := cmd.Run(); err != nil {
return clusterConfig, err
}
kubeConfigFile = KubeconfigTempFile
}
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
}
clusterConfig.MasterIP = clusterConfig.Rest.Host
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
}