Files
kubesphere/pkg/models/components/components_test.go
2020-01-02 20:52:00 +08:00

357 lines
7.7 KiB
Go

package components
import (
"fmt"
"github.com/google/go-cmp/cmp"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
"testing"
"time"
)
func service(name, namespace string, selector map[string]string) runtime.Object {
return &v1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: v1.ServiceSpec{
Selector: selector,
},
}
}
func pods(name, namespace string, labels map[string]string, healthPods, totalPods int) []runtime.Object {
var ps []runtime.Object
for index := 0; index < totalPods; index++ {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", name, index),
Namespace: namespace,
Labels: labels,
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
ContainerStatuses: []v1.ContainerStatus{
{
Name: fmt.Sprintf("%s-%d", name, index),
Ready: true,
},
},
},
}
if index >= healthPods {
pod.Status.Phase = v1.PodPending
pod.Status.ContainerStatuses[0].Ready = false
}
ps = append(ps, pod)
}
return ps
}
func nodes(name string, healthNodes, totalNodes int) []runtime.Object {
var ns []runtime.Object
for index := 0; index < totalNodes; index++ {
node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", name, index),
},
Status: v1.NodeStatus{
Phase: v1.NodeRunning,
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionTrue,
},
},
},
}
if index >= healthNodes {
node.Status.Phase = v1.NodePending
node.Status.Conditions[0].Status = v1.ConditionFalse
}
ns = append(ns, node)
}
return ns
}
func TestGetSystemHealthStatus(t *testing.T) {
var tests = []struct {
description string
labels map[string]string
namespace string
name string
healthPods int
totalPods int
healthNodes int
totalNodes int
expected v1alpha2.HealthStatus
}{
{
"no backends",
map[string]string{"app": "foo"},
"kube-system",
"",
0,
0,
0,
0,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Namespace: "kube-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 0,
HealthyBackends: 0,
},
},
NodeStatus: v1alpha2.NodeStatus{},
},
},
{
"all healthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
2,
2,
2,
2,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 2,
HealthyBackends: 2,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 2,
HealthyNodes: 2,
},
},
},
{
"all unhealthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
0,
2,
0,
2,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 2,
HealthyBackends: 0,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 2,
HealthyNodes: 0,
},
},
},
{
"half healthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
2,
4,
2,
4,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 4,
HealthyNodes: 2,
},
},
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
svc := service(test.name, test.namespace, test.labels)
ns := nodes(test.name, test.healthNodes, test.totalNodes)
var objs []runtime.Object
objs = append(objs, ps...)
objs = append(objs, svc)
objs = append(objs, ns...)
client := fake.NewSimpleClientset(objs...)
informer := informers.NewSharedInformerFactory(client, time.Minute*10)
informer.Core().V1().Services().Informer().GetIndexer().Add(svc)
for _, obj := range ps {
informer.Core().V1().Pods().Informer().GetIndexer().Add(obj)
}
for _, obj := range ns {
informer.Core().V1().Nodes().Informer().GetIndexer().Add(obj)
}
c := NewComponentsGetter(informer)
healthStatus, err := c.GetSystemHealthStatus()
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(healthStatus, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}
}
func TestGetComponentStatus(t *testing.T) {
var tests = []struct {
description string
name string
namespace string
labels map[string]string
healthPods int
totalPods int
expected v1alpha2.ComponentStatus
expectedError bool
}{
{
"no component",
"random",
"foo",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "",
Namespace: "",
SelfLink: "",
Label: nil,
StartedAt: time.Time{},
TotalBackends: 0,
HealthyBackends: 0,
},
true,
},
{
"all healthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
false,
},
{
"all unhealthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
0,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 0,
},
false,
},
{
"half healthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
false,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
svc := service(test.name, test.namespace, test.labels)
var objs []runtime.Object
objs = append(objs, ps...)
objs = append(objs, svc)
client := fake.NewSimpleClientset(objs...)
informer := informers.NewSharedInformerFactory(client, time.Minute*10)
informer.Core().V1().Services().Informer().GetIndexer().Add(svc)
for _, obj := range ps {
informer.Core().V1().Pods().Informer().GetIndexer().Add(obj)
}
c := NewComponentsGetter(informer)
healthStatus, err := c.GetComponentStatus(test.name)
if err == nil && test.expectedError {
t.Fatalf("expected error while got nothing")
} else if err != nil && !test.expectedError {
t.Fatal(err)
}
if diff := cmp.Diff(healthStatus, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}
}