Skip to content

Commit c147f66

Browse files
authored
Merge pull request #94 from dims/add-functional-test
Add functional test
2 parents ce8e082 + 010af62 commit c147f66

File tree

6 files changed

+385
-19
lines changed

6 files changed

+385
-19
lines changed

.travis.yml

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# ref: https://docs.travis-ci.com/user/languages/python
22
language: python
3-
python:
4-
- "2.7"
5-
- "3.4"
6-
- "3.5"
7-
# command to install dependencies
8-
install:
9-
- "pip install -r requirements.txt"
10-
- "pip install codecov"
3+
sudo: true
4+
services:
5+
- docker
6+
env:
7+
- TOXENV=py35,codecov
8+
- TOXENV=py34,codecov
9+
- TOXENV=py27,codecov
10+
- TOXENV=py27-functional,codecov
11+
- TOXENV=py35-functional,codecov
12+
- TOXENV=coverage,codecov
1113

12-
# command to run tests
13-
script: nosetests --with-coverage --cover-package=kubernetes.config,kubernetes.watch --cover-tests
14+
install:
15+
- pip install tox
1416

15-
after_success:
16-
- bash <(curl -s https://codecov.io/bash)
17+
script:
18+
- tox

kubernetes/e2e_test/__init__.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.

kubernetes/e2e_test/test_k8sclient.py

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
"""
16+
test_k8sclient
17+
----------------------------------
18+
19+
Tests for `k8sclient` module. Deploy Kubernetes using:
20+
http://kubernetes.io/docs/getting-started-guides/docker/
21+
22+
and then run this test
23+
"""
24+
25+
import unittest
26+
import urllib3
27+
import uuid
28+
29+
from kubernetes.client import api_client
30+
from kubernetes.client.apis import core_v1_api
31+
32+
33+
def _is_k8s_running():
34+
try:
35+
urllib3.PoolManager().request('GET', '127.0.0.1:8080')
36+
return True
37+
except urllib3.exceptions.HTTPError:
38+
return False
39+
40+
41+
class TestK8sclient(unittest.TestCase):
42+
@unittest.skipUnless(
43+
_is_k8s_running(), "Kubernetes is not available")
44+
def test_list_endpoints(self):
45+
client = api_client.ApiClient('http://127.0.0.1:8080/')
46+
api = core_v1_api.CoreV1Api(client)
47+
48+
endpoints = api.list_endpoints_for_all_namespaces()
49+
self.assertTrue(len(endpoints.items) > 0)
50+
51+
@unittest.skipUnless(
52+
_is_k8s_running(), "Kubernetes is not available")
53+
def test_pod_apis(self):
54+
client = api_client.ApiClient('http://127.0.0.1:8080/')
55+
api = core_v1_api.CoreV1Api(client)
56+
57+
name = 'test-' + str(uuid.uuid4())
58+
59+
pod_manifest = {'apiVersion': 'v1',
60+
'kind': 'Pod',
61+
'metadata': {'color': 'blue', 'name': name},
62+
'spec': {'containers': [{'image': 'dockerfile/redis',
63+
'name': 'redis'}]}}
64+
65+
resp = api.create_namespaced_pod(body=pod_manifest,
66+
namespace='default')
67+
self.assertEqual(name, resp.metadata.name)
68+
self.assertTrue(resp.status.phase)
69+
70+
resp = api.read_namespaced_pod(name=name,
71+
namespace='default')
72+
self.assertEqual(name, resp.metadata.name)
73+
self.assertTrue(resp.status.phase)
74+
75+
number_of_pods = len(api.list_pod_for_all_namespaces().items)
76+
self.assertTrue(number_of_pods > 0)
77+
78+
resp = api.delete_namespaced_pod(name=name, body={},
79+
namespace='default')
80+
81+
@unittest.skipUnless(
82+
_is_k8s_running(), "Kubernetes is not available")
83+
def test_service_apis(self):
84+
client = api_client.ApiClient('http://127.0.0.1:8080/')
85+
api = core_v1_api.CoreV1Api(client)
86+
87+
service_manifest = {'apiVersion': 'v1',
88+
'kind': 'Service',
89+
'metadata': {'labels': {'name': 'frontend'},
90+
'name': 'frontend',
91+
'resourceversion': 'v1'},
92+
'spec': {'ports': [{'name': 'port',
93+
'port': 80,
94+
'protocol': 'TCP',
95+
'targetPort': 80}],
96+
'selector': {'name': 'frontend'}}}
97+
98+
resp = api.create_namespaced_service(body=service_manifest,
99+
namespace='default')
100+
self.assertEqual('frontend', resp.metadata.name)
101+
self.assertTrue(resp.status)
102+
103+
resp = api.read_namespaced_service(name='frontend',
104+
namespace='default')
105+
self.assertEqual('frontend', resp.metadata.name)
106+
self.assertTrue(resp.status)
107+
108+
# TODO(dims) : Fails with "json: cannot unmarshal object into
109+
# Go value of type jsonpatch.Patch"
110+
# service_manifest['spec']['ports'] = [{'name': 'new',
111+
# 'port': 8080,
112+
# 'protocol': 'TCP',
113+
# 'targetPort': 8080}]
114+
# resp = api.patch_namespaced_service(body=service_manifest,
115+
# name='frontend',
116+
# namespace='default')
117+
# self.assertEqual(2, len(resp.spec.ports))
118+
# self.assertTrue(resp.status)
119+
120+
resp = api.delete_namespaced_service(name='frontend',
121+
namespace='default')
122+
123+
@unittest.skipUnless(
124+
_is_k8s_running(), "Kubernetes is not available")
125+
def test_replication_controller_apis(self):
126+
client = api_client.ApiClient('http://127.0.0.1:8080/')
127+
api = core_v1_api.CoreV1Api(client)
128+
129+
rc_manifest = {
130+
'apiVersion': 'v1',
131+
'kind': 'ReplicationController',
132+
'metadata': {'labels': {'name': 'frontend'},
133+
'name': 'frontend'},
134+
'spec': {'replicas': 2,
135+
'selector': {'name': 'frontend'},
136+
'template': {'metadata': {
137+
'labels': {'name': 'frontend'}},
138+
'spec': {'containers': [{
139+
'image': 'nginx',
140+
'name': 'nginx',
141+
'ports': [{'containerPort': 80,
142+
'protocol': 'TCP'}]}]}}}}
143+
144+
resp = api.create_namespaced_replication_controller(
145+
body=rc_manifest, namespace='default')
146+
self.assertEqual('frontend', resp.metadata.name)
147+
self.assertEqual(2, resp.spec.replicas)
148+
149+
resp = api.read_namespaced_replication_controller(
150+
name='frontend', namespace='default')
151+
self.assertEqual('frontend', resp.metadata.name)
152+
self.assertEqual(2, resp.spec.replicas)
153+
154+
resp = api.delete_namespaced_replication_controller(
155+
name='frontend', body={}, namespace='default')
156+
157+
158+
@unittest.skipUnless(
159+
_is_k8s_running(), "Kubernetes is not available")
160+
def test_configmap_apis(self):
161+
client = api_client.ApiClient('http://127.0.0.1:8080/')
162+
api = core_v1_api.CoreV1Api(client)
163+
164+
test_configmap = {
165+
"kind": "ConfigMap",
166+
"apiVersion": "v1",
167+
"metadata": {
168+
"name": "test-configmap",
169+
},
170+
"data": {
171+
"config.json": "{\"command\":\"/usr/bin/mysqld_safe\"}",
172+
"frontend.cnf": "[mysqld]\nbind-address = 10.0.0.3\nport = 3306\n"
173+
}
174+
}
175+
176+
resp = api.create_namespaced_config_map(
177+
body=test_configmap, namespace='default'
178+
)
179+
self.assertEqual('test-configmap', resp.metadata.name)
180+
181+
resp = api.read_namespaced_config_map(
182+
name='test-configmap', namespace='default')
183+
self.assertEqual('test-configmap', resp.metadata.name)
184+
185+
# TODO(dims): Fails with "json: cannot unmarshal object
186+
# into Go value of type jsonpatch.Patch"
187+
# test_configmap['data']['config.json'] = "{}"
188+
# resp = api.patch_namespaced_config_map(
189+
# name='test-configmap', namespace='default', body=test_configmap)
190+
191+
resp = api.delete_namespaced_config_map(
192+
name='test-configmap', body={}, namespace='default')
193+
194+
195+
@unittest.skipUnless(
196+
_is_k8s_running(), "Kubernetes is not available")
197+
def test_node_apis(self):
198+
client = api_client.ApiClient('http://127.0.0.1:8080/')
199+
api = core_v1_api.CoreV1Api(client)
200+
201+
for item in api.list_node().items:
202+
node = api.read_node(name=item.metadata.name)
203+
self.assertTrue(len(node.metadata.labels) > 0)
204+
self.assertTrue(isinstance(node.metadata.labels, dict))

scripts/kube-init.sh

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/bin/bash
2+
3+
# Copyright 2017 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -x
18+
19+
function clean_exit(){
20+
local error_code="$?"
21+
local spawned=$(jobs -p)
22+
if [ -n "$spawned" ]; then
23+
kill $(jobs -p)
24+
fi
25+
return $error_code
26+
}
27+
28+
trap "clean_exit" EXIT
29+
30+
# Switch off SE-Linux
31+
setenforce 0
32+
33+
# Install docker if needed
34+
path_to_executable=$(which docker)
35+
if [ -x "$path_to_executable" ] ; then
36+
echo "Found Docker installation"
37+
else
38+
curl -sSL https://get.docker.io | sudo bash
39+
fi
40+
docker --version
41+
42+
# Get the latest stable version of kubernetes
43+
export K8S_VERSION=$(curl -sS https://storage.googleapis.com/kubernetes-release/release/stable.txt)
44+
echo "K8S_VERSION : ${K8S_VERSION}"
45+
46+
echo "Starting docker service"
47+
sudo systemctl enable docker.service
48+
sudo systemctl start docker.service --ignore-dependencies
49+
echo "Checking docker service"
50+
sudo docker ps
51+
52+
# Run the docker containers for kubernetes
53+
echo "Starting Kubernetes containers"
54+
sudo docker run \
55+
--volume=/:/rootfs:ro \
56+
--volume=/sys:/sys:ro \
57+
--volume=/var/lib/docker/:/var/lib/docker:rw \
58+
--volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
59+
--volume=/var/run:/var/run:rw \
60+
--net=host \
61+
--pid=host \
62+
--privileged=true \
63+
--name=kubelet \
64+
-d \
65+
gcr.io/google_containers/hyperkube-amd64:${K8S_VERSION} \
66+
/hyperkube kubelet \
67+
--containerized \
68+
--hostname-override="127.0.0.1" \
69+
--address="0.0.0.0" \
70+
--api-servers=http://localhost:8080 \
71+
--config=/etc/kubernetes/manifests \
72+
--allow-privileged=true --v=2
73+
74+
75+
echo "Download Kubernetes CLI"
76+
wget -O kubectl "http://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl"
77+
chmod 755 kubectl
78+
./kubectl get nodes
79+
80+
set +x
81+
echo "Waiting for master components to start..."
82+
for i in {1..300}
83+
do
84+
running_count=$(./kubectl -s=http://127.0.0.1:8080 get pods --no-headers 2>/dev/null | grep "Running" | wc -l)
85+
# We expect to have 3 running pods - etcd, master and kube-proxy.
86+
if [ "$running_count" -ge 3 ]; then
87+
break
88+
fi
89+
echo -n "."
90+
sleep 1
91+
done
92+
set -x
93+
94+
echo "SUCCESS"
95+
echo "Cluster created!"
96+
echo ""
97+
98+
echo "Dump Kubernetes Objects..."
99+
./kubectl -s=http://127.0.0.1:8080 get componentstatuses
100+
./kubectl -s=http://127.0.0.1:8080 get configmaps
101+
./kubectl -s=http://127.0.0.1:8080 get daemonsets
102+
./kubectl -s=http://127.0.0.1:8080 get deployments
103+
./kubectl -s=http://127.0.0.1:8080 get events
104+
./kubectl -s=http://127.0.0.1:8080 get endpoints
105+
./kubectl -s=http://127.0.0.1:8080 get horizontalpodautoscalers
106+
./kubectl -s=http://127.0.0.1:8080 get ingress
107+
./kubectl -s=http://127.0.0.1:8080 get jobs
108+
./kubectl -s=http://127.0.0.1:8080 get limitranges
109+
./kubectl -s=http://127.0.0.1:8080 get nodes
110+
./kubectl -s=http://127.0.0.1:8080 get namespaces
111+
./kubectl -s=http://127.0.0.1:8080 get pods
112+
./kubectl -s=http://127.0.0.1:8080 get persistentvolumes
113+
./kubectl -s=http://127.0.0.1:8080 get persistentvolumeclaims
114+
./kubectl -s=http://127.0.0.1:8080 get quota
115+
./kubectl -s=http://127.0.0.1:8080 get resourcequotas
116+
./kubectl -s=http://127.0.0.1:8080 get replicasets
117+
./kubectl -s=http://127.0.0.1:8080 get replicationcontrollers
118+
./kubectl -s=http://127.0.0.1:8080 get secrets
119+
./kubectl -s=http://127.0.0.1:8080 get serviceaccounts
120+
./kubectl -s=http://127.0.0.1:8080 get services
121+
122+
123+
echo "Running tests..."
124+
set -x -e
125+
# Yield execution to venv command
126+
$*

test-requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ py>=1.4.31
55
randomize>=0.13
66
mock>=2.0.0
77
sphinx>=1.2.1,!=1.3b1,<1.4 # BSD
8-
recommonmark
8+
recommonmark
9+
codecov>=1.4.0

0 commit comments

Comments
 (0)