-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathtest_pods.py
More file actions
201 lines (165 loc) · 7.68 KB
/
test_pods.py
File metadata and controls
201 lines (165 loc) · 7.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
"""
Unit tests for the Deis scheduler module.
Run the tests with './manage.py test scheduler'
"""
from unittest import mock
from datetime import datetime, timedelta
from scheduler import KubeHTTPException
from scheduler.tests import TestCase
from scheduler.utils import generate_random_name
class PodsTest(TestCase):
"""Tests scheduler pod calls"""
def create(self, namespace=None, name=generate_random_name(), **kwargs):
"""
Helper function to create and verify a pod on the namespace
"""
namespace = self.namespace if namespace is None else namespace
# these are all required even if it is kwargs...
kwargs = {
'app_type': kwargs.get('app_type', 'web'),
'version': kwargs.get('version', 'v99'),
'replicas': kwargs.get('replicas', 4),
'pod_termination_grace_period_seconds': 2,
'image': 'quay.io/fake/image',
'entrypoint': 'sh',
'command': 'start',
'deploy_timeout': 10,
}
pod = self.scheduler.pod.create(namespace, name, **kwargs)
self.assertEqual(pod.status_code, 201, pod.json())
return name
def test_create_failure(self):
with self.assertRaises(
KubeHTTPException,
msg='failed to create Pod doesnotexist in Namespace {}: 404 Not Found'.format(self.namespace) # noqa
):
self.create('doesnotexist', 'doesnotexist')
def test_create(self):
self.create()
def test_delete_failure(self):
# test failure
with self.assertRaises(
KubeHTTPException,
msg='failed to delete Pod foo in Namespace {}: 404 Not Found'.format(self.namespace) # noqa
):
self.scheduler.pod.delete(self.namespace, 'foo')
def test_delete(self):
# test success
name = self.create()
response = self.scheduler.pod.delete(self.namespace, name)
data = response.json()
self.assertEqual(response.status_code, 200, data)
def test_get_pods(self):
# test success
name = self.create()
response = self.scheduler.pod.get(self.namespace)
data = response.json()
self.assertEqual(response.status_code, 200, data)
self.assertIn('items', data)
self.assertEqual(1, len(data['items']), data['items'])
# simple verify of data
self.assertEqual(data['items'][0]['metadata']['name'], name, data)
def test_get_pod_failure(self):
# test failure
with self.assertRaises(
KubeHTTPException,
msg='failed to get Pod doesnotexist in Namespace {}: 404 Not Found'.format(self.namespace) # noqa
):
self.scheduler.pod.get(self.namespace, 'doesnotexist')
def test_get_pod(self):
# test success
name = self.create()
response = self.scheduler.pod.get(self.namespace, name)
data = response.json()
self.assertEqual(response.status_code, 200, data)
self.assertEqual(data['kind'], 'Pod')
self.assertEqual(data['metadata']['name'], name)
self.assertDictContainsSubset(
{
'app': self.namespace,
'heritage': 'deis'
},
data['metadata']['labels']
)
def test_liveness_status(self):
# Missing Ready type means pod has passed liveness check
pod = {'status': {'conditions': []}}
self.assertTrue(self.scheduler.pod.liveness_status(pod))
# fake out a minimal pod structure for success
pod['status']['conditions'].append({
'type': 'Ready',
'status': 'True'
})
self.assertTrue(self.scheduler.pod.liveness_status(pod))
# fake out a minimal pod structure for failure
pod['status']['conditions'][0]['status'] = 'False'
self.assertFalse(self.scheduler.pod.liveness_status(pod))
def test_readiness_status(self):
# create a pod to then manipulate
name = self.create()
pod = self.scheduler.pod.get(self.namespace, name).json()
# on a newly created pod has an overall "Running" status with ready state on a container
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Running')
# on a newly created pod has been deleted with ready state on a container
pod['metadata']['deletionTimestamp'] = 'fake'
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Terminating')
del pod['metadata']['deletionTimestamp']
# now say the app container is not Ready
container = pod['status']['containerStatuses'][0]
container['ready'] = False
# state of the container is Starting when container is not ready but says Running
self.assertTrue('running' in container['state'].keys())
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Starting')
# verify Terminating status
del container['state']['running']
container['state']['terminated'] = 'fake'
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Terminating')
# test metdata terminating
del container['state']['terminated']
pod['metadata']['deletionTimestamp'] = 'fake'
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Terminating')
del pod['metadata']['deletionTimestamp']
# inject fake state
container['state']['random'] = 'fake'
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Unknown')
# no containers around means Unknown
pod['status']['containerStatuses'] = []
self.assertEqual(self.scheduler.pod.readiness_status(pod), 'Unknown')
def test_ready(self):
# create a pod to then manipulate
name = self.create()
pod = self.scheduler.pod.get(self.namespace, name).json()
# pod itself shouldn't be ready yet
self.assertFalse(self.scheduler.pod.ready(pod))
# only pod but no other probe
pod['status']['phase'] = 'Running'
# fake out functions for failure
with mock.patch('scheduler.resources.pod.Pod.readiness_status') as ready:
ready.return_value = 'Starting'
# only readiness is ready so overall ready status is False
self.assertFalse(self.scheduler.pod.ready(pod))
with mock.patch('scheduler.resources.pod.Pod.liveness_status') as liveness:
liveness.return_value = False
# all things have lined up, go time
self.assertFalse(self.scheduler.pod.ready(pod))
# fake out other functions since they are tested by themselves
with mock.patch('scheduler.resources.pod.Pod.readiness_status') as ready:
ready.return_value = 'Running'
with mock.patch('scheduler.resources.pod.Pod.liveness_status') as liveness:
# keep liveness as failing for now
liveness.return_value = False
# only readiness is ready so overall ready status is False
self.assertFalse(self.scheduler.pod.ready(pod))
# all things have lined up, go time
liveness.return_value = True
self.assertTrue(self.scheduler.pod.ready(pod))
def test_deleted(self):
# create a pod to then manipulate
name = self.create()
pod = self.scheduler.pod.get(self.namespace, name).json()
# pod should no be deleted yet
self.assertFalse(self.scheduler.pod.deleted(pod))
# set deleted 10 minutes in the past
ts_deleted = datetime.utcnow() - timedelta(minutes=10)
pod['metadata']['deletionTimestamp'] = ts_deleted.strftime(self.scheduler.DATETIME_FORMAT)
self.assertTrue(self.scheduler.pod.deleted(pod))