Skip to content

Commit e27847f

Browse files
andrewsykimmurali-reddy
authored andcommitted
package utils unit tests and CI fixes (#261)
* package utils unit tests * add tests to travis CI * make push needs IMG_TAG in docker push command
1 parent f822109 commit e27847f

File tree

11 files changed

+337
-33
lines changed

11 files changed

+337
-33
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ env:
1919
- GIT_BRANCH=$TRAVIS_BRANCH
2020

2121
script:
22+
- build/travis-test.sh
2223
# All successfully built commits get an image placed in the kube-router-git
2324
# image repo and tagged with the commit hash.
2425
- build/travis-deploy.sh

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ kube-router:
2222
@echo Finished kube-router binary build.
2323

2424
test: gofmt ## Runs code quality pipelines (gofmt, tests, coverage, lint, etc)
25+
go test github.com/cloudnativelabs/kube-router/utils/
2526

2627
vagrant-up: export docker=$(DOCKER)
2728
vagrant-up: export DEV_IMG=$(REGISTRY_DEV):$(IMG_TAG)
@@ -75,7 +76,7 @@ docker-login: ## Logs into a docker registry using {DOCKER,QUAY}_{USERNAME,PASSW
7576

7677
push: container docker-login ## Pushes a Docker container image to a registry.
7778
@echo Starting kube-router container image push.
78-
$(DOCKER) push "$(REGISTRY_DEV)"
79+
$(DOCKER) push "$(REGISTRY_DEV):$(IMG_TAG)"
7980
@echo Finished kube-router container image push.
8081

8182
push-release: push

build-image/Dockerfile

Lines changed: 0 additions & 18 deletions
This file was deleted.

build-image/entrypoint.sh

Lines changed: 0 additions & 6 deletions
This file was deleted.

build-image/make.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
NAME=kube-router-build
2-
docker build -t kube-router-build:latest .
3-
docker rm -f $NAME
4-
docker run --name=$NAME -v $GOPATH:/data/go kube-router-build:latest "$@"
2+
docker run --rm --name=$NAME -w /go/src/github.com/cloudnativelabs/kube-router -v $GOPATH:/go golang:1.8.3 "make" "$@"

build/travis-test.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
set -o errexit
3+
set -o pipefail
4+
5+
echo "Running tests on Travis"
6+
make test

kube-router.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ func main() {
4747
}
4848

4949
if config.EnablePprof {
50-
go func() {
51-
fmt.Fprintf(os.Stdout, http.ListenAndServe("0.0.0.0:6060", nil).Error())
52-
}()
50+
go func() {
51+
fmt.Fprintf(os.Stdout, http.ListenAndServe("0.0.0.0:6060", nil).Error())
52+
}()
5353
}
5454

5555
err = kubeRouter.Run()

utils/node.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
// GetNodeObject returns the node API object for the node
15-
func GetNodeObject(clientset *kubernetes.Clientset, hostnameOverride string) (*apiv1.Node, error) {
15+
func GetNodeObject(clientset kubernetes.Interface, hostnameOverride string) (*apiv1.Node, error) {
1616

1717
// assuming kube-router is running as pod, first check env NODE_NAME
1818
nodeName := os.Getenv("NODE_NAME")

utils/node_test.go

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package utils
2+
3+
import (
4+
"errors"
5+
"net"
6+
"os"
7+
"reflect"
8+
"testing"
9+
10+
apiv1 "k8s.io/api/core/v1"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"k8s.io/client-go/kubernetes/fake"
13+
)
14+
15+
func Test_GetNodeObject(t *testing.T) {
16+
curHostname, err := os.Hostname()
17+
if err != nil {
18+
t.Fatalf("failed to get local hostname: %v", err)
19+
}
20+
21+
testcases := []struct {
22+
name string
23+
envNodeName string
24+
hostnameOverride string
25+
existingNode *apiv1.Node
26+
err error
27+
}{
28+
{
29+
"node with NODE_NAME exists",
30+
"test-node",
31+
"",
32+
&apiv1.Node{
33+
ObjectMeta: metav1.ObjectMeta{
34+
Name: "test-node",
35+
},
36+
},
37+
nil,
38+
},
39+
{
40+
"node with hostname overrie exists",
41+
"something-else",
42+
"test-node",
43+
&apiv1.Node{
44+
ObjectMeta: metav1.ObjectMeta{
45+
Name: "test-node",
46+
},
47+
},
48+
nil,
49+
},
50+
{
51+
"node with current hostname exists",
52+
"something-else",
53+
"something-else",
54+
&apiv1.Node{
55+
ObjectMeta: metav1.ObjectMeta{
56+
Name: curHostname,
57+
},
58+
},
59+
nil,
60+
},
61+
{
62+
"node with NODE_NAME, hostname override or current hostname does not exists",
63+
"test-node",
64+
"",
65+
&apiv1.Node{
66+
ObjectMeta: metav1.ObjectMeta{
67+
Name: "another-node",
68+
},
69+
},
70+
errors.New("Failed to identify the node by NODE_NAME, hostname or --hostname-override"),
71+
},
72+
}
73+
74+
for _, testcase := range testcases {
75+
t.Run(testcase.name, func(t *testing.T) {
76+
clientset := fake.NewSimpleClientset()
77+
_, err := clientset.Core().Nodes().Create(testcase.existingNode)
78+
if err != nil {
79+
t.Fatalf("failed to create existing nodes for test: %v", err)
80+
}
81+
82+
os.Setenv("NODE_NAME", testcase.envNodeName)
83+
defer os.Unsetenv("NODE_NAME")
84+
85+
_, err = GetNodeObject(clientset, testcase.hostnameOverride)
86+
if !reflect.DeepEqual(err, testcase.err) {
87+
t.Logf("actual error: %v", err)
88+
t.Logf("expected error: %v", testcase.err)
89+
t.Error("did not get expected error")
90+
}
91+
})
92+
}
93+
}
94+
95+
func Test_GetNodeIP(t *testing.T) {
96+
testcases := []struct {
97+
name string
98+
node *apiv1.Node
99+
ip net.IP
100+
err error
101+
}{
102+
{
103+
"has external and internal IPs",
104+
&apiv1.Node{
105+
ObjectMeta: metav1.ObjectMeta{
106+
Name: "test-node",
107+
},
108+
Status: apiv1.NodeStatus{
109+
Addresses: []apiv1.NodeAddress{
110+
{
111+
Type: apiv1.NodeInternalIP,
112+
Address: "10.0.0.1",
113+
},
114+
{
115+
Type: apiv1.NodeExternalIP,
116+
Address: "1.1.1.1",
117+
},
118+
},
119+
},
120+
},
121+
net.ParseIP("10.0.0.1"),
122+
nil,
123+
},
124+
{
125+
"has only internal IP",
126+
&apiv1.Node{
127+
ObjectMeta: metav1.ObjectMeta{
128+
Name: "test-node",
129+
},
130+
Status: apiv1.NodeStatus{
131+
Addresses: []apiv1.NodeAddress{
132+
{
133+
Type: apiv1.NodeInternalIP,
134+
Address: "10.0.0.1",
135+
},
136+
},
137+
},
138+
},
139+
net.ParseIP("10.0.0.1"),
140+
nil,
141+
},
142+
{
143+
"has only external IP",
144+
&apiv1.Node{
145+
ObjectMeta: metav1.ObjectMeta{
146+
Name: "test-node",
147+
},
148+
Status: apiv1.NodeStatus{
149+
Addresses: []apiv1.NodeAddress{
150+
{
151+
Type: apiv1.NodeExternalIP,
152+
Address: "1.1.1.1",
153+
},
154+
},
155+
},
156+
},
157+
net.ParseIP("1.1.1.1"),
158+
nil,
159+
},
160+
{
161+
"has no addresses",
162+
&apiv1.Node{
163+
ObjectMeta: metav1.ObjectMeta{
164+
Name: "test-node",
165+
},
166+
Status: apiv1.NodeStatus{
167+
Addresses: []apiv1.NodeAddress{},
168+
},
169+
},
170+
nil,
171+
errors.New("host IP unknown"),
172+
},
173+
}
174+
175+
for _, testcase := range testcases {
176+
t.Run(testcase.name, func(t *testing.T) {
177+
ip, err := GetNodeIP(testcase.node)
178+
if !reflect.DeepEqual(err, testcase.err) {
179+
t.Logf("actual error: %v", err)
180+
t.Logf("expected error: %v", testcase.err)
181+
t.Error("did not get expected error")
182+
}
183+
184+
if !reflect.DeepEqual(ip, testcase.ip) {
185+
t.Logf("actual ip: %v", ip)
186+
t.Logf("expected ip: %v", testcase.ip)
187+
t.Error("did not get expected node ip")
188+
}
189+
})
190+
}
191+
}

utils/pod_cidr.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package utils
22

33
import (
44
"encoding/json"
5+
"errors"
56
"fmt"
67
"io/ioutil"
78
"net"
9+
"reflect"
810

911
"github.com/containernetworking/cni/libcni"
1012
"github.com/containernetworking/cni/plugins/ipam/host-local/backend/allocator"
@@ -23,7 +25,13 @@ func GetPodCidrFromCniSpec(cniConfFilePath string) (net.IPNet, error) {
2325
if err != nil {
2426
return net.IPNet{}, fmt.Errorf("Failed to get IPAM details from the CNI conf file: %s", err.Error())
2527
}
26-
return net.IPNet(ipamConfig.Subnet), nil
28+
29+
podCidr := net.IPNet(ipamConfig.Subnet)
30+
if reflect.DeepEqual(podCidr, net.IPNet{}) {
31+
return net.IPNet{}, errors.New("subnet missing from CNI IPAM")
32+
}
33+
34+
return podCidr, nil
2735
}
2836

2937
// InsertPodCidrInCniSpec inserts the pod CIDR allocated to the node by kubernetes controlller manager

0 commit comments

Comments
 (0)