pull file
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
Close Stale Issues / close_stale_issues (push) Has been cancelled
repo-sync / repo-sync (push) Has been cancelled
auto-deploy-tencent-scf / pre-check (push) Has been cancelled
auto-deploy-tencent-scf / deploy serverless (push) Has been cancelled
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
Close Stale Issues / close_stale_issues (push) Has been cancelled
repo-sync / repo-sync (push) Has been cancelled
auto-deploy-tencent-scf / pre-check (push) Has been cancelled
auto-deploy-tencent-scf / deploy serverless (push) Has been cancelled
This commit is contained in:
73
krew/pkg/utils/client.go
Normal file
73
krew/pkg/utils/client.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
func GetK8sClient() (*kubernetes.Clientset, *rest.Config, error) {
|
||||
var kubeconfig string
|
||||
|
||||
envKubeConfig := os.Getenv("KUBECONFIG")
|
||||
if envKubeConfig == "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, nil, GenErrorMsg(SERVER_ERROR, err.Error())
|
||||
}
|
||||
kubeconfig = filepath.Join(home, ".kube", "config")
|
||||
} else {
|
||||
kubeconfig = envKubeConfig
|
||||
}
|
||||
|
||||
// use the current context in kubeconfig
|
||||
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||
if err != nil {
|
||||
return nil, nil, GenErrorMsg(SERVER_ERROR, err.Error())
|
||||
}
|
||||
config.QPS = float32(10.0)
|
||||
config.Burst = 20
|
||||
|
||||
// create the clientset
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, config, GenErrorMsg(SERVER_ERROR, err.Error())
|
||||
}
|
||||
return clientset, config, nil
|
||||
}
|
||||
|
||||
func GetBiliName(client *kubernetes.Clientset, namespace, deploymentName string) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
|
||||
defer cancel()
|
||||
deployment, err := client.AppsV1().Deployments(namespace).Get(ctx, deploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", GenErrorMsg(SERVER_ERROR, err.Error())
|
||||
}
|
||||
|
||||
// we dont do much checks here
|
||||
selector := deployment.Spec.Selector.MatchLabels
|
||||
if len(selector) == 0 {
|
||||
return "", GenErrorMsg(SERVER_ERROR, "deployment doesn't have any selectors, please check the deploy template")
|
||||
}
|
||||
listOptions := metav1.ListOptions{
|
||||
LabelSelector: labels.Set(selector).String(),
|
||||
}
|
||||
pods, err := client.CoreV1().Pods(namespace).List(ctx, listOptions)
|
||||
if err != nil {
|
||||
return "", GenErrorMsg(SERVER_ERROR, "cannot list the pods with deploy selectors")
|
||||
}
|
||||
if len(pods.Items) != 1 {
|
||||
return "", GenErrorMsg(SERVER_ERROR, fmt.Sprintf("pod number is expected to be 1, currently %d", len(pods.Items)))
|
||||
}
|
||||
|
||||
// only one pod is supposed to be existing, soft constraint
|
||||
return pods.Items[0].ObjectMeta.GetName(), nil
|
||||
}
|
||||
19
krew/pkg/utils/client_test.go
Normal file
19
krew/pkg/utils/client_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetK8sClient(t *testing.T) {
|
||||
client, _, err := GetK8sClient()
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if client == nil {
|
||||
t.Logf("test failed for returned client is empty, this should not happen")
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
}
|
||||
38
krew/pkg/utils/cmd.go
Normal file
38
krew/pkg/utils/cmd.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func Run(cmd *exec.Cmd, in io.Reader) error {
|
||||
cmd.Stdin = in
|
||||
|
||||
stdoutReader, _ := cmd.StdoutPipe()
|
||||
stdoutScanner := bufio.NewScanner(stdoutReader)
|
||||
go func() {
|
||||
for stdoutScanner.Scan() {
|
||||
fmt.Println(stdoutScanner.Text())
|
||||
}
|
||||
}()
|
||||
stderrReader, _ := cmd.StderrPipe()
|
||||
stderrScanner := bufio.NewScanner(stderrReader)
|
||||
go func() {
|
||||
for stderrScanner.Scan() {
|
||||
fmt.Println(stderrScanner.Text())
|
||||
}
|
||||
}()
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return GenErrorMsg(EXEC_ERROR, err.Error())
|
||||
}
|
||||
|
||||
// Stuck here until there are out and err
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return GenErrorMsg(EXEC_ERROR, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
17
krew/pkg/utils/cmd_test.go
Normal file
17
krew/pkg/utils/cmd_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
|
||||
// Just make sure there is no error...
|
||||
testCmd := exec.Command("ls")
|
||||
err := Run(testCmd, nil)
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
22
krew/pkg/utils/error.go
Normal file
22
krew/pkg/utils/error.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
// For errors about kustomize
|
||||
TEMPLATE_ERROR = "template error"
|
||||
// For errors about file system
|
||||
FILE_ERROR = "file system error"
|
||||
// For errors about create/delete/... resources in cluster
|
||||
SERVER_ERROR = "cluster operation error"
|
||||
// For exec errors
|
||||
EXEC_ERROR = "exec error"
|
||||
)
|
||||
|
||||
func GenErrorMsg(errType, customMsg string) error {
|
||||
errorMsg := fmt.Sprintf("[ERROR] %s: %s", errType, customMsg)
|
||||
return errors.New(errorMsg)
|
||||
}
|
||||
38
krew/pkg/utils/error_test.go
Normal file
38
krew/pkg/utils/error_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServerGenErrorMsg(t *testing.T) {
|
||||
expectedErr := GenErrorMsg(SERVER_ERROR, "test for server")
|
||||
if !strings.Contains(expectedErr.Error(), SERVER_ERROR) {
|
||||
t.Logf("server error generate failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestTemplateGenErrorMsg(t *testing.T) {
|
||||
expectedErr := GenErrorMsg(TEMPLATE_ERROR, "test for template")
|
||||
if !strings.Contains(expectedErr.Error(), TEMPLATE_ERROR) {
|
||||
t.Logf("template error generate failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecGenErrorMsg(t *testing.T) {
|
||||
expectedErr := GenErrorMsg(EXEC_ERROR, "test for exec")
|
||||
if !strings.Contains(expectedErr.Error(), EXEC_ERROR) {
|
||||
t.Logf("error error generate failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileGenErrorMsg(t *testing.T) {
|
||||
expectedErr := GenErrorMsg(FILE_ERROR, "test for file")
|
||||
if !strings.Contains(expectedErr.Error(), FILE_ERROR) {
|
||||
t.Logf("file error generate failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
83
krew/pkg/utils/fileSys.go
Normal file
83
krew/pkg/utils/fileSys.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/resources"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
var assetFS = resources.GetStaticResources()
|
||||
|
||||
// GetResourceFileSys file
|
||||
func GetResourceFileSys() (filesys.FileSystem, error) {
|
||||
inDiskSys := filesys.MakeFsOnDisk()
|
||||
// copy from the resources into the target folder on the in memory FS
|
||||
if err := copyDirtoDiskFS(".", "bilipro", inDiskSys); err != nil {
|
||||
return nil, GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
return inDiskSys, nil
|
||||
}
|
||||
|
||||
func copyFileToDiskFS(src, dst string, diskFS filesys.FileSystem) error {
|
||||
// skip all .go files
|
||||
if strings.HasSuffix(src, ".go") {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
var srcFileDesc fs.File
|
||||
var dstFileDesc filesys.File
|
||||
|
||||
if srcFileDesc, err = assetFS.Open(src); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
defer srcFileDesc.Close()
|
||||
|
||||
if dstFileDesc, err = diskFS.Create(dst); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
defer dstFileDesc.Close()
|
||||
|
||||
// Note: I had to read the whole string, for some reason io.Copy was not copying the whole content
|
||||
input, err := io.ReadAll(srcFileDesc)
|
||||
if err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
|
||||
_, err = dstFileDesc.Write(input)
|
||||
if err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyDirtoDiskFS(src string, dst string, diskFS filesys.FileSystem) error {
|
||||
var err error
|
||||
var fds []fs.DirEntry
|
||||
|
||||
if err = diskFS.MkdirAll(dst); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
|
||||
if fds, err = assetFS.ReadDir(src); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
for _, fd := range fds {
|
||||
srcfp := path.Join(src, fd.Name())
|
||||
dstfp := path.Join(dst, fd.Name())
|
||||
|
||||
if fd.IsDir() {
|
||||
if err = copyDirtoDiskFS(srcfp, dstfp, diskFS); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err = copyFileToDiskFS(srcfp, dstfp, diskFS); err != nil {
|
||||
return GenErrorMsg(FILE_ERROR, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
88
krew/pkg/utils/fileSys_test.go
Normal file
88
krew/pkg/utils/fileSys_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
func TestCopyFiletoDiskFS(t *testing.T) {
|
||||
expectedFile, err := assetFS.Open("base/ns/namespace.yaml")
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
expectedOutput, err := io.ReadAll(expectedFile)
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
inDiskSys := filesys.MakeFsOnDisk()
|
||||
|
||||
err = copyFileToDiskFS("base/ns/namespace.yaml", filepath.Join(dir, "fixtures/testNamespace.yaml"), inDiskSys)
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
actualOutput, err := os.ReadFile(filepath.Join(dir, "fixtures/testNamespace.yaml"))
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if string(expectedOutput) != string(actualOutput) {
|
||||
t.Logf("test failed due to copy file failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyDirtoDiskFS(t *testing.T) {
|
||||
expectedFile, err := assetFS.Open("base/bilibiliPro/deployment.yaml")
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
expectedOutput, err := io.ReadAll(expectedFile)
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
inDiskSys := filesys.MakeFsOnDisk()
|
||||
|
||||
err = copyDirtoDiskFS("base/bilibiliPro", filepath.Join(dir, "fixtures"), inDiskSys)
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
actualOutput, err := os.ReadFile(filepath.Join(dir, "fixtures/deployment.yaml"))
|
||||
if err != nil {
|
||||
t.Logf("test failed due to %s", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if string(expectedOutput) != string(actualOutput) {
|
||||
t.Logf("test failed due to copy file failed")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user