271 lines
6.8 KiB
Go
271 lines
6.8 KiB
Go
package kubernetes
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes/fake"
|
|
)
|
|
|
|
func TestCommandInitOption_getKarmadaAPIServerIP(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
option CommandInitOption
|
|
nodes []string
|
|
labels map[string]string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "KarmadaAPIServerAdvertiseAddress is not empty",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
KarmadaAPIServerAdvertiseAddress: "127.0.0.1",
|
|
},
|
|
nodes: []string{"node1"},
|
|
labels: map[string]string{},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "three nodes but they are not master",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
nodes: []string{"node1", "node2", "node3"},
|
|
labels: map[string]string{},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "three master nodes",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
nodes: []string{"node1", "node2", "node3"},
|
|
labels: map[string]string{"node-role.kubernetes.io/control-plane": ""},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "no nodes",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
for _, v := range tt.nodes {
|
|
_, err := tt.option.KubeClientSet.CoreV1().Nodes().Create(context.Background(), &corev1.Node{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: v,
|
|
Labels: tt.labels,
|
|
},
|
|
Status: corev1.NodeStatus{
|
|
Addresses: []corev1.NodeAddress{
|
|
{Address: "127.0.0.1"},
|
|
},
|
|
},
|
|
}, metav1.CreateOptions{})
|
|
if err != nil {
|
|
t.Errorf("create node error: %v", err)
|
|
}
|
|
}
|
|
if err := tt.option.getKarmadaAPIServerIP(); (err != nil) != tt.wantErr {
|
|
t.Errorf("CommandInitOption.getKarmadaAPIServerIP() = %v, want error:%v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_nodeStatus(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
nodeConditions []corev1.NodeCondition
|
|
isHealth bool
|
|
}{
|
|
{
|
|
name: "node is ready",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeReady, Status: corev1.ConditionTrue},
|
|
},
|
|
isHealth: true,
|
|
},
|
|
{
|
|
name: "node is unready",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeReady, Status: corev1.ConditionFalse},
|
|
},
|
|
isHealth: false,
|
|
},
|
|
{
|
|
name: "node's memory pressure is true",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeMemoryPressure, Status: corev1.ConditionTrue},
|
|
},
|
|
isHealth: false,
|
|
},
|
|
{
|
|
name: "node's memory pressure is false",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeMemoryPressure, Status: corev1.ConditionFalse},
|
|
},
|
|
isHealth: true,
|
|
},
|
|
{
|
|
name: "node's disk pressure is true",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeDiskPressure, Status: corev1.ConditionTrue},
|
|
},
|
|
isHealth: false,
|
|
},
|
|
{
|
|
name: "node's disk pressure is false",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeDiskPressure, Status: corev1.ConditionFalse},
|
|
},
|
|
isHealth: true,
|
|
},
|
|
{
|
|
name: "node's network unavailable is false",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeNetworkUnavailable, Status: corev1.ConditionFalse},
|
|
},
|
|
isHealth: true,
|
|
},
|
|
{
|
|
name: "node's network unavailable is true",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeNetworkUnavailable, Status: corev1.ConditionTrue},
|
|
},
|
|
isHealth: false,
|
|
},
|
|
{
|
|
name: "node's pid pressure is false",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodePIDPressure, Status: corev1.ConditionFalse},
|
|
},
|
|
isHealth: true,
|
|
},
|
|
{
|
|
name: "node's pid pressure is true",
|
|
nodeConditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodePIDPressure, Status: corev1.ConditionTrue},
|
|
},
|
|
isHealth: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := nodeStatus(tt.nodeConditions); got != tt.isHealth {
|
|
t.Errorf("nodeStatus() = %v, want %v", got, tt.isHealth)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommandInitOption_AddNodeSelectorLabels(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
option CommandInitOption
|
|
status corev1.ConditionStatus
|
|
spec corev1.NodeSpec
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "there is healthy node",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
status: corev1.ConditionTrue,
|
|
spec: corev1.NodeSpec{},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "there is unhealthy node",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
status: corev1.ConditionFalse,
|
|
spec: corev1.NodeSpec{},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "there is taint node",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
status: corev1.ConditionTrue,
|
|
spec: corev1.NodeSpec{
|
|
Taints: []corev1.Taint{
|
|
{
|
|
Effect: corev1.TaintEffectNoSchedule,
|
|
},
|
|
},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
_, err := tt.option.KubeClientSet.CoreV1().Nodes().Create(context.Background(), &corev1.Node{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "test-node"},
|
|
Status: corev1.NodeStatus{
|
|
Conditions: []corev1.NodeCondition{
|
|
{Type: corev1.NodeReady, Status: tt.status},
|
|
},
|
|
},
|
|
Spec: tt.spec,
|
|
}, metav1.CreateOptions{})
|
|
if err != nil {
|
|
t.Errorf("create node error: %v", err)
|
|
}
|
|
if err := tt.option.AddNodeSelectorLabels(); (err != nil) != tt.wantErr {
|
|
t.Errorf("CommandInitOption.AddNodeSelectorLabels() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommandInitOption_isNodeExist(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
option CommandInitOption
|
|
nodeName string
|
|
labels map[string]string
|
|
exists bool
|
|
}{
|
|
{
|
|
name: "there is matched node",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
nodeName: "node1",
|
|
labels: map[string]string{"foo": "bar"},
|
|
exists: true,
|
|
},
|
|
{
|
|
name: "there is no matched node",
|
|
option: CommandInitOption{
|
|
KubeClientSet: fake.NewSimpleClientset(),
|
|
},
|
|
nodeName: "node2",
|
|
labels: map[string]string{"bar": "foo"},
|
|
exists: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
_, err := tt.option.KubeClientSet.CoreV1().Nodes().Create(context.Background(), &corev1.Node{
|
|
ObjectMeta: metav1.ObjectMeta{Name: tt.nodeName, Labels: tt.labels},
|
|
}, metav1.CreateOptions{})
|
|
if err != nil {
|
|
t.Errorf("create node error: %v", err)
|
|
}
|
|
if got := tt.option.isNodeExist("foo=bar"); got != tt.exists {
|
|
t.Errorf("CommandInitOption.isNodeExist() = %v, want %v", got, tt.exists)
|
|
}
|
|
})
|
|
}
|
|
}
|