mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-05 13:17:42 +08:00
444 lines
11 KiB
Go
444 lines
11 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/goodrain/rainbond/worker/appm/store"
|
|
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
|
"github.com/goodrain/rainbond/worker/server/pb"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
)
|
|
|
|
func getReplicaSet() *appsv1.ReplicaSet {
|
|
layout := "2006-01-02T15:04:05Z"
|
|
creation, err := time.Parse(layout, "2019-08-15T12:15:56Z")
|
|
if err != nil {
|
|
fmt.Printf("%s\n", err.Error())
|
|
}
|
|
return &appsv1.ReplicaSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
CreationTimestamp: metav1.NewTime(creation),
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPods(filename string) ([]*corev1.Pod, error) {
|
|
pfile, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error opening '%s': %v", filename, err.Error())
|
|
}
|
|
|
|
var pods []*corev1.Pod
|
|
if err := json.Unmarshal([]byte(pfile), &pods); err != nil {
|
|
return nil, fmt.Errorf("error unmarshaling pfile: %v", err.Error())
|
|
}
|
|
|
|
return pods, nil
|
|
}
|
|
|
|
func serviceAppPodListEqual(a, b *pb.ServiceAppPodList) bool {
|
|
if a == b {
|
|
return true
|
|
}
|
|
podequal := func(m, n []*pb.ServiceAppPod) bool {
|
|
if len(m) != len(n) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
if podequal(a.OldPods, b.OldPods) && podequal(a.NewPods, b.NewPods) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func TestRuntimeServer_GetAppPods(t *testing.T) {
|
|
replicaset := getReplicaSet()
|
|
newpods, err := getPods("newpods.json")
|
|
if err != nil {
|
|
t.Errorf("error getting new pods: %s", err.Error())
|
|
}
|
|
oldpods, err := getPods("oldpods.json")
|
|
if err != nil {
|
|
t.Errorf("error getting old pods: %s", err.Error())
|
|
}
|
|
|
|
tests := []struct {
|
|
name, sid string
|
|
as *v1.AppService
|
|
expres *pb.ServiceAppPodList
|
|
experr bool
|
|
}{
|
|
{name: "empty result", sid: "dummy service id 1", as: nil, expres: nil, experr: false},
|
|
{name: "only new pods", sid: "dummy service id 2", as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetReplicaSets(replicaset)
|
|
for _, pod := range newpods {
|
|
as.SetPods(pod)
|
|
}
|
|
return as
|
|
}(), expres: &pb.ServiceAppPodList{
|
|
NewPods: []*pb.ServiceAppPod{{}, {}, {}},
|
|
}, experr: false},
|
|
{name: "old and new pods", sid: "dummy service id 4", as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetReplicaSets(replicaset)
|
|
pods := append(oldpods, newpods...)
|
|
for _, pod := range pods {
|
|
as.SetPods(pod)
|
|
}
|
|
return as
|
|
}(), expres: &pb.ServiceAppPodList{
|
|
OldPods: []*pb.ServiceAppPod{{}, {}, {}},
|
|
NewPods: []*pb.ServiceAppPod{{}, {}, {}},
|
|
}, experr: false},
|
|
}
|
|
|
|
for idx := range tests {
|
|
tc := tests[idx]
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
storer := store.NewMockStorer(ctrl)
|
|
rserver := &RuntimeServer{
|
|
store: storer,
|
|
}
|
|
storer.EXPECT().GetAppService(tc.sid).Return(tc.as)
|
|
|
|
sreq := &pb.ServiceRequest{ServiceId: tc.sid}
|
|
res, err := rserver.GetAppPods(context.Background(), sreq)
|
|
if tc.experr != (err != nil) {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !serviceAppPodListEqual(res, tc.expres) {
|
|
t.Errorf("Expected %+v for pods\n, but returned %v", tc.expres, res)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListEvents(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
storer := store.NewMockStorer(ctrl)
|
|
c, err := clientcmd.BuildConfigFromFlags("", "/Users/abe/go/src/github.com/goodrain/rainbond/test/admin.kubeconfig")
|
|
if err != nil {
|
|
t.Fatalf("read kube config file error: %v", err)
|
|
}
|
|
clientset, err := kubernetes.NewForConfig(c)
|
|
if err != nil {
|
|
t.Fatalf("create kube api client error: %v", err)
|
|
}
|
|
rserver := &RuntimeServer{
|
|
store: storer,
|
|
clientset: clientset,
|
|
}
|
|
as := &v1.AppService{}
|
|
storer.EXPECT().GetAppService("sid").Return(as)
|
|
|
|
name := "88d8c4c55657217522f3bb86cfbded7e-deployment-647b84b467-kd6zc"
|
|
namespace := "c1a29fe4d7b0413993dc859430cf743d"
|
|
podEvents := rserver.listPodEventsByName(name, namespace)
|
|
t.Logf("pod events: %v", podEvents)
|
|
}
|
|
|
|
func TestRuntimeServer_GetAppVolumeStatus(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
re *pb.ServiceRequest
|
|
as *v1.AppService
|
|
want *pb.ServiceVolumeStatusMessage
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "running pod",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PodStatus_PENDING",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodPending,
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
Ready: false,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_NOT_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PodStatus_INITIATING",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodPending,
|
|
Conditions: []corev1.PodCondition{
|
|
{
|
|
Type: corev1.PodInitialized,
|
|
Status: corev1.ConditionTrue,
|
|
},
|
|
},
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
Ready: false,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PodStatus_ABNORMAL",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
Conditions: []corev1.PodCondition{
|
|
{
|
|
Type: corev1.PodReady,
|
|
Status: corev1.ConditionTrue,
|
|
},
|
|
},
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
Ready: false,
|
|
State: corev1.ContainerState{
|
|
Waiting: nil,
|
|
Running: nil,
|
|
Terminated: &corev1.ContainerStateTerminated{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PodStatus_NOTREADY",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
Conditions: []corev1.PodCondition{
|
|
{
|
|
Type: corev1.PodReady,
|
|
Status: corev1.ConditionTrue,
|
|
},
|
|
},
|
|
ContainerStatuses: []corev1.ContainerStatus{},
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PodStatus_SCHEDULING",
|
|
re: &pb.ServiceRequest{
|
|
ServiceId: "serviceID",
|
|
},
|
|
as: func() *v1.AppService {
|
|
as := &v1.AppService{}
|
|
as.SetPods(&corev1.Pod{
|
|
Spec: corev1.PodSpec{
|
|
Volumes: []corev1.Volume{
|
|
{
|
|
Name: "manual1",
|
|
VolumeSource: corev1.VolumeSource{
|
|
HostPath: &corev1.HostPathVolumeSource{},
|
|
},
|
|
},
|
|
{
|
|
Name: "default-token-xwxgv",
|
|
VolumeSource: corev1.VolumeSource{
|
|
Secret: &corev1.SecretVolumeSource{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodPending,
|
|
Conditions: []corev1.PodCondition{
|
|
{
|
|
Type: corev1.PodScheduled,
|
|
Status: corev1.ConditionFalse,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return as
|
|
}(),
|
|
want: &pb.ServiceVolumeStatusMessage{
|
|
Status: map[string]pb.ServiceVolumeStatus{"1": pb.ServiceVolumeStatus_NOT_READY},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
storer := store.NewMockStorer(ctrl)
|
|
r := &RuntimeServer{
|
|
store: storer,
|
|
}
|
|
storer.EXPECT().GetAppService(tt.re.ServiceId).Return(tt.as)
|
|
|
|
got, err := r.GetAppVolumeStatus(context.Background(), tt.re)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetAppVolumeStatus() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("GetAppVolumeStatus() got = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|