karmada/pkg/karmadactl/cmdinit/kubernetes/node_test.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)
}
})
}
}