constellation/operators/constellation-node-operator/internal/node/node_test.go
Daniel Weiße 90f3336c8e
deps: remove go.mod files from submodules (#2769)
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2024-01-08 13:19:38 +01:00

241 lines
6.0 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package node
import (
"testing"
updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/api/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestReady(t *testing.T) {
testCases := map[string]struct {
node corev1.Node
wantReady bool
}{
"node without status conditions": {},
"node with NodeReady set to false": {
node: corev1.Node{
Status: corev1.NodeStatus{
Conditions: []corev1.NodeCondition{
{Type: corev1.NodeReady, Status: corev1.ConditionFalse},
},
},
},
},
"node with NodeReady set to unknown": {
node: corev1.Node{
Status: corev1.NodeStatus{
Conditions: []corev1.NodeCondition{
{Type: corev1.NodeReady, Status: corev1.ConditionUnknown},
},
},
},
},
"node with NodeReady set to true": {
node: corev1.Node{
Status: corev1.NodeStatus{
Conditions: []corev1.NodeCondition{
{Type: corev1.NodeReady, Status: corev1.ConditionTrue},
},
},
},
wantReady: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
assert.Equal(tc.wantReady, Ready(&tc.node))
})
}
}
func TestIsControlPlaneNode(t *testing.T) {
testCases := map[string]struct {
node corev1.Node
wantControlPlane bool
}{
"node without labels": {},
"node with control-plane role label": {
node: corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{controlPlaneRoleLabel: ""},
},
},
wantControlPlane: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
assert.Equal(tc.wantControlPlane, IsControlPlaneNode(&tc.node))
})
}
}
func TestVPCIP(t *testing.T) {
testCases := map[string]struct {
node corev1.Node
wantVPCIP string
wantErr bool
}{
"node without addresses": {
wantErr: true,
},
"node with multiple addresses": {
node: corev1.Node{
Status: corev1.NodeStatus{
Addresses: []corev1.NodeAddress{
{Type: corev1.NodeExternalIP, Address: "external"},
{Type: corev1.NodeInternalIP, Address: "192.0.2.1"},
{Type: corev1.NodeInternalIP, Address: "second-internal"},
},
},
},
wantVPCIP: "192.0.2.1",
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
gotIP, err := VPCIP(&tc.node)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.wantVPCIP, gotIP)
})
}
}
func TestFindPending(t *testing.T) {
testCases := map[string]struct {
pendingNodes []updatev1alpha1.PendingNode
node *corev1.Node
wantPending *updatev1alpha1.PendingNode
}{
"everything nil": {},
"node nil": {
pendingNodes: pendingNodes,
},
"node is not in pending nodes list": {
pendingNodes: pendingNodes,
node: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "doesnotexist",
},
},
},
"pending node is leaving": {
pendingNodes: pendingNodes,
node: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "leavingnode",
},
},
},
"pending node is not ready": {
pendingNodes: pendingNodes,
node: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "unreadynode",
},
},
},
"pending node is found": {
pendingNodes: pendingNodes,
node: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "joiningnode",
},
},
wantPending: &pendingNodes[0],
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
pending := FindPending(tc.pendingNodes, tc.node)
if tc.wantPending == nil {
assert.Nil(pending)
return
}
assert.Equal(*tc.wantPending, *pending)
})
}
}
func TestFilterLabels(t *testing.T) {
labels := map[string]string{
"key": "value",
"app.kubernetes.io/component": "component",
"app.kubernetes.io/created-by": "created-by",
"app.kubernetes.io/instance": "instance",
"app.kubernetes.io/managed-by": "managed-by",
"app.kubernetes.io/name": "name",
"app.kubernetes.io/part-of": "part-of",
"app.kubernetes.io/version": "version",
"kubernetes.io/arch": "arch",
"kubernetes.io/os": "os",
"beta.kubernetes.io/arch": "arch",
"beta.kubernetes.io/os": "os",
"kubernetes.io/hostname": "hostname",
"kubernetes.io/change-cause": "change-cause",
"kubernetes.io/description": "description",
"node.kubernetes.io/instance-type": "instance-type",
"failure-domain.beta.kubernetes.io/region": "region",
"failure-domain.beta.kubernetes.io/zone": "zone",
"topology.kubernetes.io/region": "region",
"topology.kubernetes.io/zone": "zone",
"node.kubernetes.io/windows-build": "windows-build",
"node-role.kubernetes.io/control-plane": "control-plane",
}
wantFiltered := map[string]string{
"key": "value",
}
assert := assert.New(t)
assert.Equal(wantFiltered, FilterLabels(labels))
}
var pendingNodes = []updatev1alpha1.PendingNode{
{
Spec: updatev1alpha1.PendingNodeSpec{
NodeName: "joiningnode",
Goal: updatev1alpha1.NodeGoalJoin,
},
Status: updatev1alpha1.PendingNodeStatus{
CSPNodeState: updatev1alpha1.NodeStateReady,
},
},
{
Spec: updatev1alpha1.PendingNodeSpec{
NodeName: "unreadynode",
Goal: updatev1alpha1.NodeGoalJoin,
},
Status: updatev1alpha1.PendingNodeStatus{
CSPNodeState: updatev1alpha1.NodeStateCreating,
},
},
{
Spec: updatev1alpha1.PendingNodeSpec{
NodeName: "leavingnode",
Goal: updatev1alpha1.NodeGoalLeave,
},
},
}