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.

177 lines
4.5 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"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
)
type KubectlConfig struct {
previousContext string
config *Config // 主要是使用里面的stdout/stderr
}
func NewKubectlConfig(config *Config) *KubectlConfig {
return &KubectlConfig{
config: config,
}
}
var contextNameRegex = regexp.MustCompile("[^a-zA-Z0-9_]")
func (k *KubectlConfig) getContextName(config *ClusterConfig) string {
return fmt.Sprintf("%s-context",
contextNameRegex.ReplaceAllString(
strings.ToLower(config.Name),
""))
}
func (k *KubectlConfig) Command(cmd string, args ...string) *exec.Cmd {
command := exec.Command(cmd, args...)
command.Stdout = k.config.Stdout
command.Stderr = k.config.Stderr
return command
}
func (k *KubectlConfig) SetContext(config *ClusterConfig) error {
contextName := k.getContextName(config)
// 1. 获取当前context保存起来如果有
// 获取命令为kubectl config current-context
cmd := k.Command("kubectl",
"config",
"current-context")
currentContext := &bytes.Buffer{}
cmd.Stdout = currentContext
err := cmd.Run()
// 如果执行成功,说明存在 currentcontext就把它保存起来在DeleteContext的时候来回复
defer func() {
if err == nil {
k.previousContext = strings.TrimSpace(currentContext.String())
}
}()
// 2. 从 clusterconfig 创建 context
// context 组成:
// - cluster
// - credentials
// - user
// 三个元素组成context
// 2.1 设置 cluster
// 命令为kubectl config set-cluster <contextName> --server <MasterIP> --insecure-skip-tls-verify=true
if err := k.Command(
"kubectl",
"config",
"set-cluster",
contextName,
"--server", config.MasterIP,
"--insecure-skip-tls-verify=true").Run(); err != nil {
return err
}
// 2.2 设置授权
if config.Rest.BearerToken != "" {
// 命令为kubectl config set-credentials <contextName> --token <config.Rest.BearerToken>
if err := k.Command(
"kubectl",
"config",
"set-credentials",
contextName,
"--token", config.Rest.BearerToken).Run(); err != nil {
return err
}
} else if config.Rest.CertData != nil && config.Rest.KeyData != nil {
keyFile := fmt.Sprintf(KeyTempFileFmt, contextName)
certFile := fmt.Sprintf(CertTempFileFmt, contextName)
if err := os.WriteFile(keyFile, config.Rest.KeyData, os.ModePerm); err != nil {
return err
}
defer func() {
_ = os.Remove(keyFile)
}()
if err := os.WriteFile(certFile, config.Rest.CertData, os.ModePerm); err != nil {
return err
}
defer func() {
_ = os.Remove(certFile)
}()
// 命令为kubectl config set-credentials <contextName> --embed-certs=true --client-key=<keyFile> --client-certificate=<certFile>
if err := k.Command(
"kubectl",
"config",
"set-credentials",
contextName,
"--embed-certs=true",
"--client-key="+keyFile,
"--client-certificate="+certFile).Run(); err != nil {
return err
}
} else {
return fmt.Errorf("Counld not find credentials in config or credential method is not supported")
}
// 2.3 组合 context
// 命令为kubectl config set-context <contextName> --cluster <contextName> --user=<contextName>
if err := k.Command("kubectl",
"config",
"set-context",
contextName,
"--cluster="+contextName,
"--user="+contextName).Run(); err != nil {
return err
}
// 3. 切换到新创建的 context
// 命令为kubectl config use-context <contextName>
if err := k.Command(
"kubectl",
"config",
"use-context", contextName).Run(); err != nil {
return err
}
return nil
}
func (k *KubectlConfig) DeleteContext(config *ClusterConfig) error {
contextName := k.getContextName(config)
// 1. 删除 cluster
// 命令为kubectl config delete-cluster <contextName>
if err := k.Command(
"kubectl",
"config",
"delete-cluster", contextName).Run(); err != nil {
return err
}
// 2. 删除 user
// 命令为kubectl config delete-user <contextName>
if err := k.Command(
"kubectl",
"config",
"delete-user", contextName).Run(); err != nil {
return err
}
// 3. 删除 context
// 命令为kubectl config delete-context <contextName>
if err := k.Command(
"kubectl",
"config",
"delete-context", contextName).Run(); err != nil {
return err
}
// 4. 如果 previousContext 不为空,恢复到之前的 context
if k.previousContext != "" {
// 命令为kubectl config use-context <k.previousContext>
// 不处理执行错误,因为这里出错不影响测试任务
_ = k.Command(
"kubectl",
"config",
"use-context", k.previousContext).Run()
}
return nil
}