mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-09-27 03:36:09 +08:00
310 lines
7.5 KiB
Go
310 lines
7.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
|
"k8s.io/client-go/util/retry"
|
|
|
|
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
|
|
)
|
|
|
|
var content = `package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
func main() {
|
|
http.HandleFunc("/health", health)
|
|
|
|
log.Println("Start listening http port 9080 ...")
|
|
if err := http.ListenAndServe(":9080", nil); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func health(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
resp, err := json.Marshal(map[string]string{
|
|
"status": "Authors is healthy in pod",
|
|
})
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
log.Println(err)
|
|
return
|
|
}
|
|
w.Write(resp)
|
|
}`
|
|
|
|
func (u *ut) kubevpnSyncWithFullProxy(t *testing.T) {
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
defer cancelFunc()
|
|
|
|
endpoint := u.kubevpnSync(t, ctx, false)
|
|
u.healthChecker(t, endpoint, nil, remoteSyncPod)
|
|
u.healthChecker(t, endpoint, map[string]string{"env": "test"}, remoteSyncPod)
|
|
}
|
|
|
|
func (u *ut) kubevpnSync(t *testing.T, ctx context.Context, isServiceMesh bool) string {
|
|
path := u.writeTempFile(t)
|
|
name := filepath.Base(path)
|
|
dir := filepath.Dir(path)
|
|
remoteDir := "/app/test"
|
|
|
|
args := []string{"sync",
|
|
"deploy/authors",
|
|
"--debug",
|
|
"--sync", fmt.Sprintf("%s:%s", dir, remoteDir),
|
|
"-c", "authors",
|
|
"--target-image", "ghcr.io/kubenetworks/authors:latest",
|
|
}
|
|
if isServiceMesh {
|
|
args = append(args, "--headers", "env=test")
|
|
}
|
|
cmd := exec.Command("kubevpn", args...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
err := cmd.Run()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
list, err := util.GetRunningPodList(ctx, u.clientset, u.namespace, fields.OneTermEqualSelector("origin-workload", "authors").String())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(list) == 0 {
|
|
t.Fatal("expect at least one pod")
|
|
}
|
|
|
|
remotePath := fmt.Sprintf("%s/%s", remoteDir, name)
|
|
containerName := "authors"
|
|
u.checkContent(ctx, t, list[0].Name, containerName, remotePath)
|
|
go u.execServer(ctx, t, list[0].Name, containerName, remotePath)
|
|
|
|
endpoint := fmt.Sprintf("http://%s:%v/health", list[0].Status.PodIP, 9080)
|
|
u.healthChecker(t, endpoint, nil, remoteSyncPod)
|
|
app := "authors"
|
|
ip, err := u.getServiceIP(app)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
endpoint = fmt.Sprintf("http://%s:%v/health", ip, 9080)
|
|
return endpoint
|
|
}
|
|
|
|
func (u *ut) execServer(ctx context.Context, t *testing.T, podName string, containerName string, remoteDir string) {
|
|
for ctx.Err() == nil {
|
|
output, err := util.Shell(
|
|
ctx,
|
|
u.clientset,
|
|
u.restconfig,
|
|
podName,
|
|
containerName,
|
|
u.namespace,
|
|
[]string{"go", "run", remoteDir},
|
|
)
|
|
if err != nil {
|
|
t.Log(err, output)
|
|
}
|
|
time.Sleep(time.Second * 1)
|
|
}
|
|
}
|
|
|
|
func (u *ut) kubevpnSyncWithServiceMesh(t *testing.T) {
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
defer cancelFunc()
|
|
|
|
endpoint := u.kubevpnSync(t, ctx, true)
|
|
u.healthChecker(t, endpoint, nil, remoteSyncOrigin)
|
|
u.healthChecker(t, endpoint, map[string]string{"env": "test"}, remoteSyncPod)
|
|
}
|
|
|
|
func (u *ut) checkContent(ctx context.Context, t *testing.T, podName string, containerName string, remotePath string) {
|
|
err := retry.OnError(
|
|
wait.Backoff{Duration: time.Second, Factor: 1, Jitter: 0, Steps: 120},
|
|
func(err error) bool { return err != nil },
|
|
func() error {
|
|
shell, err := util.Shell(
|
|
ctx,
|
|
u.clientset,
|
|
u.restconfig,
|
|
podName,
|
|
containerName,
|
|
u.namespace,
|
|
[]string{"cat", remotePath},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.TrimSpace(shell) != strings.TrimSpace(content) {
|
|
t.Logf("expect: %s, but was: %s", content, shell)
|
|
return fmt.Errorf("expect: %s, but was: %s", content, shell)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestCompile(t *testing.T) {
|
|
u := &ut{}
|
|
u.writeTempFile(t)
|
|
}
|
|
|
|
func (u *ut) writeTempFile(t *testing.T) string {
|
|
dir := t.TempDir()
|
|
file := filepath.Join(dir, "main.go")
|
|
temp, err := os.Create(file)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = temp.WriteString(content)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = temp.Chmod(0755)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = temp.Close()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
absPath, err := filepath.Abs(temp.Name())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return absPath
|
|
}
|
|
|
|
func (u *ut) checkSyncWithFullProxyStatus(t *testing.T) {
|
|
cmd := exec.Command("kubevpn", "status", "-o", "json")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
t.Fatal(err, string(output))
|
|
}
|
|
|
|
expect := status{List: []*connection{{
|
|
Namespace: u.namespace,
|
|
Status: "connected",
|
|
ProxyList: []*proxyItem{{
|
|
Namespace: u.namespace,
|
|
Workload: "deployments.apps/authors",
|
|
RuleList: []*proxyRule{{
|
|
Headers: nil,
|
|
CurrentDevice: false,
|
|
PortMap: map[int32]int32{9080: 9080, 80: 80},
|
|
}},
|
|
}},
|
|
SyncList: []*syncItem{{
|
|
Namespace: u.namespace,
|
|
Workload: "deploy/authors",
|
|
RuleList: []*syncRule{{}},
|
|
}},
|
|
}}}
|
|
|
|
var statuses status
|
|
if err = json.Unmarshal(output, &statuses); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(expect.List) == 0 || len(expect.List[0].SyncList) == 0 || len(expect.List[0].SyncList[0].RuleList) == 0 {
|
|
t.Fatal("expect List[0].SyncList[0].RuleList[0] not found", string(output))
|
|
}
|
|
|
|
expect.List[0].SyncList[0].RuleList[0].DstWorkload = statuses.List[0].SyncList[0].RuleList[0].DstWorkload
|
|
|
|
if !reflect.DeepEqual(statuses, expect) {
|
|
marshal, _ := json.Marshal(expect)
|
|
marshalB, _ := json.Marshal(statuses)
|
|
t.Fatalf("expect: %s, but was: %s", string(marshal), string(marshalB))
|
|
}
|
|
}
|
|
|
|
func (u *ut) kubevpnUnSync(t *testing.T) {
|
|
cmd := exec.Command("kubevpn", "status", "-o", "json")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
t.Fatal(err, string(output))
|
|
}
|
|
|
|
var statuses status
|
|
if err = json.Unmarshal(output, &statuses); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(statuses.List) == 0 || len(statuses.List[0].SyncList) == 0 || len(statuses.List[0].SyncList[0].RuleList) == 0 {
|
|
t.Fatal("expect List[0].SyncList[0].RuleList[0] not found", string(output))
|
|
}
|
|
|
|
cmd = exec.Command("kubevpn", "unsync", statuses.List[0].SyncList[0].RuleList[0].DstWorkload)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (u *ut) checkSyncWithServiceMeshStatus(t *testing.T) {
|
|
cmd := exec.Command("kubevpn", "status", "-o", "json")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
t.Fatal(err, string(output))
|
|
}
|
|
|
|
expect := status{List: []*connection{{
|
|
Namespace: u.namespace,
|
|
Status: "connected",
|
|
ProxyList: []*proxyItem{{
|
|
Namespace: u.namespace,
|
|
Workload: "deployments.apps/authors",
|
|
RuleList: []*proxyRule{{
|
|
Headers: map[string]string{"env": "test"},
|
|
CurrentDevice: false,
|
|
PortMap: map[int32]int32{9080: 9080, 80: 80},
|
|
}},
|
|
}},
|
|
SyncList: []*syncItem{{
|
|
Namespace: u.namespace,
|
|
Workload: "deploy/authors",
|
|
RuleList: []*syncRule{{}},
|
|
}},
|
|
}}}
|
|
|
|
var statuses status
|
|
if err = json.Unmarshal(output, &statuses); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(expect.List) == 0 || len(expect.List[0].SyncList) == 0 || len(expect.List[0].SyncList[0].RuleList) == 0 {
|
|
t.Fatal("expect List[0].SyncList[0].RuleList[0] not found", string(output))
|
|
}
|
|
|
|
expect.List[0].SyncList[0].RuleList[0].DstWorkload = statuses.List[0].SyncList[0].RuleList[0].DstWorkload
|
|
|
|
if !reflect.DeepEqual(statuses, expect) {
|
|
marshal, _ := json.Marshal(expect)
|
|
marshalB, _ := json.Marshal(statuses)
|
|
t.Fatalf("expect: %s, but was: %s", string(marshal), string(marshalB))
|
|
}
|
|
}
|