350 lines
7.5 KiB
Go
350 lines
7.5 KiB
Go
/*
|
|
* Copyright 2024 the KubeSphere Authors.
|
|
* Please refer to the LICENSE file in the root directory of the project.
|
|
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
|
*/
|
|
|
|
package components
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
runtimefakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
|
|
|
"kubesphere.io/kubesphere/pkg/scheme"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
|
|
)
|
|
|
|
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
|
|
}
|
|
|
|
var _ = Describe("Components", func() {
|
|
|
|
})
|
|
|
|
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) {
|
|
pods := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
|
|
svc := service(test.name, test.namespace, test.labels)
|
|
nodes := nodes(test.name, test.healthNodes, test.totalNodes)
|
|
|
|
client := runtimefakeclient.NewClientBuilder().
|
|
WithScheme(scheme.Scheme).
|
|
WithRuntimeObjects(pods...).
|
|
WithRuntimeObjects(svc).
|
|
WithRuntimeObjects(nodes...).Build()
|
|
|
|
c := NewComponentsGetter(client)
|
|
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) {
|
|
pods := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
|
|
svc := service(test.name, test.namespace, test.labels)
|
|
|
|
client := runtimefakeclient.NewClientBuilder().
|
|
WithScheme(scheme.Scheme).
|
|
WithRuntimeObjects(pods...).
|
|
WithRuntimeObjects(svc).Build()
|
|
|
|
c := NewComponentsGetter(client)
|
|
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
|
|
}
|
|
})
|
|
}
|
|
}
|