Skip to content

Commit 061ba01

Browse files
committed
nodes: add list unit tests
This PR adds tests for the nodes/list file as well as some test helpers. Additionally, nodes_test.go has been renamed to node_test.go to match the corresponding node.go.
1 parent 9d3f600 commit 061ba01

File tree

4 files changed

+245
-1
lines changed

4 files changed

+245
-1
lines changed

pkg/nodes/list.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ const (
1818

1919
// List returns node inventory.
2020
func List(apiClient *clients.Settings, options ...metav1.ListOptions) ([]*Builder, error) {
21+
if apiClient == nil {
22+
glog.V(100).Infof("Nodes 'apiClient' parameter can not be empty")
23+
24+
return nil, fmt.Errorf("failed to list node objects, 'apiClient' parameter is empty")
25+
}
26+
2127
passedOptions := metav1.ListOptions{}
2228
logMessage := "Listing all node resources"
2329

pkg/nodes/list_test.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package nodes
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
"time"
8+
9+
"github.com/openshift-kni/eco-goinfra/pkg/clients"
10+
"github.com/stretchr/testify/assert"
11+
corev1 "k8s.io/api/core/v1"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
"k8s.io/apimachinery/pkg/runtime"
14+
)
15+
16+
func TestNodesList(t *testing.T) {
17+
testCases := []struct {
18+
nodes []*Builder
19+
listOptions []metav1.ListOptions
20+
client bool
21+
expectedError error
22+
}{
23+
{
24+
nodes: []*Builder{buildValidNodeTestBuilder(buildTestClientWithDummyNode())},
25+
listOptions: nil,
26+
client: true,
27+
expectedError: nil,
28+
},
29+
{
30+
nodes: []*Builder{buildValidNodeTestBuilder(buildTestClientWithDummyNode())},
31+
listOptions: []metav1.ListOptions{{LabelSelector: "test"}},
32+
client: true,
33+
expectedError: nil,
34+
},
35+
{
36+
nodes: []*Builder{buildValidNodeTestBuilder(buildTestClientWithDummyNode())},
37+
listOptions: []metav1.ListOptions{{LabelSelector: "test"}, {LabelSelector: "test"}},
38+
client: true,
39+
expectedError: fmt.Errorf("error: more than one ListOptions was passed"),
40+
},
41+
{
42+
nodes: []*Builder{buildValidNodeTestBuilder(buildTestClientWithDummyNode())},
43+
listOptions: nil,
44+
client: false,
45+
expectedError: fmt.Errorf("failed to list node objects, 'apiClient' parameter is empty"),
46+
},
47+
}
48+
49+
for _, testCase := range testCases {
50+
var testSettings *clients.Settings
51+
52+
if testCase.client {
53+
testSettings = buildTestClientWithDummyNode()
54+
}
55+
56+
nodeBuilders, err := List(testSettings, testCase.listOptions...)
57+
assert.Equal(t, err, testCase.expectedError)
58+
59+
if testCase.expectedError == nil && len(testCase.listOptions) == 0 {
60+
assert.Equal(t, len(nodeBuilders), len(testCase.nodes))
61+
}
62+
}
63+
}
64+
65+
func TestNodesListExternalIPv4Networks(t *testing.T) {
66+
testCases := []struct {
67+
client bool
68+
expectedError error
69+
}{
70+
{
71+
client: true,
72+
expectedError: nil,
73+
},
74+
{
75+
client: false,
76+
expectedError: fmt.Errorf("failed to list node objects, 'apiClient' parameter is empty"),
77+
},
78+
}
79+
80+
for _, testCase := range testCases {
81+
var testSettings *clients.Settings
82+
83+
if testCase.client {
84+
node := buildDummyNode(defaultNodeName)
85+
node.Annotations = map[string]string{
86+
ovnExternalAddresses: defaultExternalNetworks,
87+
}
88+
testSettings = clients.GetTestClients(clients.TestClientParams{
89+
K8sMockObjects: []runtime.Object{node},
90+
})
91+
}
92+
93+
ipv4Networks, err := ListExternalIPv4Networks(testSettings)
94+
assert.Equal(t, testCase.expectedError, err)
95+
96+
if testCase.expectedError == nil {
97+
assert.Equal(t, []string{defaultExternalIPv4}, ipv4Networks)
98+
}
99+
}
100+
}
101+
102+
func TestNodesWaitForAllNodesAreReady(t *testing.T) {
103+
testCases := []struct {
104+
client bool
105+
ready bool
106+
expectedError error
107+
}{
108+
{
109+
client: true,
110+
ready: true,
111+
expectedError: nil,
112+
},
113+
{
114+
client: false,
115+
ready: true,
116+
expectedError: fmt.Errorf("failed to list node objects, 'apiClient' parameter is empty"),
117+
},
118+
{
119+
client: true,
120+
ready: false,
121+
expectedError: context.DeadlineExceeded,
122+
},
123+
}
124+
125+
for _, testCase := range testCases {
126+
var testSettings *clients.Settings
127+
128+
if testCase.client {
129+
testSettings = clients.GetTestClients(clients.TestClientParams{
130+
K8sMockObjects: []runtime.Object{buildDummyNodeWithReadiness(defaultNodeName, testCase.ready)},
131+
})
132+
}
133+
134+
ready, err := WaitForAllNodesAreReady(testSettings, time.Second)
135+
assert.Equal(t, testCase.expectedError, err)
136+
assert.Equal(t, testCase.expectedError == nil, ready)
137+
}
138+
}
139+
140+
func TestNodesWaitForAllNodesToReboot(t *testing.T) {
141+
// There's no way to test for success without editing the node while the function is running so only failures
142+
// are covered here.
143+
testCases := []struct {
144+
client bool
145+
rebooted bool
146+
expectedError error
147+
}{
148+
{
149+
client: false,
150+
rebooted: true,
151+
expectedError: fmt.Errorf("failed to list node objects, 'apiClient' parameter is empty"),
152+
},
153+
{
154+
client: true,
155+
rebooted: false,
156+
expectedError: context.DeadlineExceeded,
157+
},
158+
}
159+
160+
for _, testCase := range testCases {
161+
var testSettings *clients.Settings
162+
163+
if testCase.client {
164+
testSettings = clients.GetTestClients(clients.TestClientParams{
165+
K8sMockObjects: []runtime.Object{buildDummyNodeWithReadiness(defaultNodeName, testCase.rebooted)},
166+
})
167+
}
168+
169+
ready, err := WaitForAllNodesToReboot(testSettings, time.Second)
170+
assert.Equal(t, testCase.expectedError, err)
171+
assert.Equal(t, testCase.expectedError == nil, ready)
172+
}
173+
}
174+
175+
// buildDummyNodeWithReadiness returns a dummy node with the specified value for the ready condition.
176+
func buildDummyNodeWithReadiness(name string, ready bool) *corev1.Node {
177+
node := buildDummyNode(name)
178+
179+
readyStatus := corev1.ConditionFalse
180+
if ready {
181+
readyStatus = corev1.ConditionTrue
182+
}
183+
184+
node.Status.Conditions = []corev1.NodeCondition{{
185+
Type: corev1.NodeReady,
186+
Status: readyStatus,
187+
}}
188+
189+
return node
190+
}

pkg/nodes/node_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package nodes
2+
3+
import (
4+
"github.com/openshift-kni/eco-goinfra/pkg/clients"
5+
corev1 "k8s.io/api/core/v1"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/apimachinery/pkg/runtime"
8+
)
9+
10+
const (
11+
defaultNodeName = "test-node"
12+
defaultNodeLabel = "node-role.kubernetes.io/control-plane"
13+
defaultExternalNetworks = `{"ipv4":"10.0.0.0/8","ipv6":"fd00::/8"}`
14+
defaultExternalIPv4 = "10.0.0.0/8"
15+
)
16+
17+
// buildDummyNode returns a Node with the provided name.
18+
func buildDummyNode(name string) *corev1.Node {
19+
return &corev1.Node{
20+
ObjectMeta: metav1.ObjectMeta{
21+
Name: name,
22+
},
23+
}
24+
}
25+
26+
// buildTestClientWithDummyNode returns a client with a dummy node.
27+
func buildTestClientWithDummyNode() *clients.Settings {
28+
return clients.GetTestClients(clients.TestClientParams{
29+
K8sMockObjects: []runtime.Object{buildDummyNode(defaultNodeName)},
30+
})
31+
}
32+
33+
func buildValidNodeTestBuilder(apiClient *clients.Settings) *Builder {
34+
return newNodeBuilder(apiClient, defaultNodeName)
35+
}
36+
37+
// newNodeBuilder creates a new Builder instances for testing purposes.
38+
func newNodeBuilder(apiClient *clients.Settings, name string) *Builder {
39+
if apiClient == nil {
40+
return nil
41+
}
42+
43+
builder := Builder{
44+
apiClient: apiClient.K8sClient,
45+
Definition: buildDummyNode(name),
46+
}
47+
48+
return &builder
49+
}

pkg/nodes/nodes_test.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)