github.com/blystad/deis@v0.11.0/controller/api/tests/test_config.py (about) 1 """ 2 Unit tests for the Deis api app. 3 4 Run the tests with "./manage.py test api" 5 """ 6 7 from __future__ import unicode_literals 8 9 import json 10 import mock 11 import requests 12 13 from django.test import TransactionTestCase 14 from django.test.utils import override_settings 15 16 from api.models import Config 17 18 19 def mock_import_repository_task(*args, **kwargs): 20 resp = requests.Response() 21 resp.status_code = 200 22 resp._content_consumed = True 23 return resp 24 25 26 @override_settings(CELERY_ALWAYS_EAGER=True) 27 class ConfigTest(TransactionTestCase): 28 29 """Tests setting and updating config values""" 30 31 fixtures = ['tests.json'] 32 33 def setUp(self): 34 self.assertTrue( 35 self.client.login(username='autotest', password='password')) 36 body = {'id': 'autotest', 'domain': 'autotest.local', 'type': 'mock', 37 'hosts': 'host1,host2', 'auth': 'base64string', 'options': {}} 38 response = self.client.post('/api/clusters', json.dumps(body), 39 content_type='application/json') 40 self.assertEqual(response.status_code, 201) 41 42 @mock.patch('requests.post', mock_import_repository_task) 43 def test_config(self): 44 """ 45 Test that config is auto-created for a new app and that 46 config can be updated using a PATCH 47 """ 48 url = '/api/apps' 49 body = {'cluster': 'autotest'} 50 response = self.client.post(url, json.dumps(body), content_type='application/json') 51 self.assertEqual(response.status_code, 201) 52 app_id = response.data['id'] 53 # check to see that an initial/empty config was created 54 url = "/api/apps/{app_id}/config".format(**locals()) 55 response = self.client.get(url) 56 self.assertEqual(response.status_code, 200) 57 self.assertIn('values', response.data) 58 self.assertEqual(response.data['values'], json.dumps({})) 59 config1 = response.data 60 # set an initial config value 61 body = {'values': json.dumps({'NEW_URL1': 'http://localhost:8080/'})} 62 response = self.client.post(url, json.dumps(body), content_type='application/json') 63 self.assertEqual(response.status_code, 201) 64 self.assertIn('x-deis-release', response._headers) 65 config2 = response.data 66 self.assertNotEqual(config1['uuid'], config2['uuid']) 67 self.assertIn('NEW_URL1', json.loads(response.data['values'])) 68 # read the config 69 response = self.client.get(url) 70 self.assertEqual(response.status_code, 200) 71 config3 = response.data 72 self.assertEqual(config2, config3) 73 self.assertIn('NEW_URL1', json.loads(response.data['values'])) 74 # set an additional config value 75 body = {'values': json.dumps({'NEW_URL2': 'http://localhost:8080/'})} 76 response = self.client.post(url, json.dumps(body), content_type='application/json') 77 self.assertEqual(response.status_code, 201) 78 config3 = response.data 79 self.assertNotEqual(config2['uuid'], config3['uuid']) 80 self.assertIn('NEW_URL1', json.loads(response.data['values'])) 81 self.assertIn('NEW_URL2', json.loads(response.data['values'])) 82 # read the config again 83 response = self.client.get(url) 84 self.assertEqual(response.status_code, 200) 85 config4 = response.data 86 self.assertEqual(config3, config4) 87 self.assertIn('NEW_URL1', json.loads(response.data['values'])) 88 self.assertIn('NEW_URL2', json.loads(response.data['values'])) 89 # unset a config value 90 body = {'values': json.dumps({'NEW_URL2': None})} 91 response = self.client.post(url, json.dumps(body), content_type='application/json') 92 self.assertEqual(response.status_code, 201) 93 config5 = response.data 94 self.assertNotEqual(config4['uuid'], config5['uuid']) 95 self.assertNotIn('NEW_URL2', json.dumps(response.data['values'])) 96 # unset all config values 97 body = {'values': json.dumps({'NEW_URL1': None})} 98 response = self.client.post(url, json.dumps(body), content_type='application/json') 99 self.assertEqual(response.status_code, 201) 100 self.assertNotIn('NEW_URL1', json.dumps(response.data['values'])) 101 # disallow put/patch/delete 102 self.assertEqual(self.client.put(url).status_code, 405) 103 self.assertEqual(self.client.patch(url).status_code, 405) 104 self.assertEqual(self.client.delete(url).status_code, 405) 105 return config5 106 107 @mock.patch('requests.post', mock_import_repository_task) 108 def test_config_set_same_key(self): 109 """ 110 Test that config sets on the same key function properly 111 """ 112 url = '/api/apps' 113 body = {'cluster': 'autotest'} 114 response = self.client.post(url, json.dumps(body), content_type='application/json') 115 self.assertEqual(response.status_code, 201) 116 app_id = response.data['id'] 117 url = "/api/apps/{app_id}/config".format(**locals()) 118 # set an initial config value 119 body = {'values': json.dumps({'PORT': '5000'})} 120 response = self.client.post(url, json.dumps(body), content_type='application/json') 121 self.assertEqual(response.status_code, 201) 122 self.assertIn('PORT', json.loads(response.data['values'])) 123 # reset same config value 124 body = {'values': json.dumps({'PORT': '5001'})} 125 response = self.client.post(url, json.dumps(body), content_type='application/json') 126 self.assertEqual(response.status_code, 201) 127 self.assertIn('PORT', json.loads(response.data['values'])) 128 self.assertEqual(json.loads(response.data['values'])['PORT'], '5001') 129 130 @mock.patch('requests.post', mock_import_repository_task) 131 def test_config_str(self): 132 """Test the text representation of a node.""" 133 config5 = self.test_config() 134 config = Config.objects.get(uuid=config5['uuid']) 135 self.assertEqual(str(config), "{}-{}".format(config5['app'], config5['uuid'][:7])) 136 137 @mock.patch('requests.post', mock_import_repository_task) 138 def test_limit_memory(self): 139 """ 140 Test that limit is auto-created for a new app and that 141 limits can be updated using a PATCH 142 """ 143 url = '/api/apps' 144 body = {'cluster': 'autotest'} 145 response = self.client.post(url, json.dumps(body), content_type='application/json') 146 self.assertEqual(response.status_code, 201) 147 app_id = response.data['id'] 148 url = '/api/apps/{app_id}/config'.format(**locals()) 149 # check default limit 150 response = self.client.get(url, content_type='application/json') 151 self.assertEqual(response.status_code, 200) 152 self.assertIn('memory', response.data) 153 self.assertEqual(json.loads(response.data['memory']), {}) 154 # regression test for https://github.com/deis/deis/issues/1563 155 self.assertNotIn('"', response.data['memory']) 156 # set an initial limit 157 mem = {'web': '1G'} 158 body = {'memory': json.dumps(mem)} 159 response = self.client.post(url, json.dumps(body), content_type='application/json') 160 self.assertEqual(response.status_code, 201) 161 self.assertIn('x-deis-release', response._headers) 162 limit1 = response.data 163 # check memory limits 164 response = self.client.get(url, content_type='application/json') 165 self.assertEqual(response.status_code, 200) 166 self.assertIn('memory', response.data) 167 memory = json.loads(response.data['memory']) 168 self.assertIn('web', memory) 169 self.assertEqual(memory['web'], '1G') 170 # set an additional value 171 body = {'memory': json.dumps({'worker': '512M'})} 172 response = self.client.post(url, json.dumps(body), content_type='application/json') 173 self.assertEqual(response.status_code, 201) 174 limit2 = response.data 175 self.assertNotEqual(limit1['uuid'], limit2['uuid']) 176 memory = json.loads(response.data['memory']) 177 self.assertIn('worker', memory) 178 self.assertEqual(memory['worker'], '512M') 179 self.assertIn('web', memory) 180 self.assertEqual(memory['web'], '1G') 181 # read the limit again 182 response = self.client.get(url) 183 self.assertEqual(response.status_code, 200) 184 limit3 = response.data 185 self.assertEqual(limit2, limit3) 186 memory = json.loads(response.data['memory']) 187 self.assertIn('worker', memory) 188 self.assertEqual(memory['worker'], '512M') 189 self.assertIn('web', memory) 190 self.assertEqual(memory['web'], '1G') 191 # regression test for https://github.com/deis/deis/issues/1613 192 # ensure that config:set doesn't wipe out previous limits 193 body = {'values': json.dumps({'NEW_URL2': 'http://localhost:8080/'})} 194 response = self.client.post(url, json.dumps(body), content_type='application/json') 195 self.assertEqual(response.status_code, 201) 196 self.assertIn('NEW_URL2', json.loads(response.data['values'])) 197 # read the limit again 198 response = self.client.get(url) 199 self.assertEqual(response.status_code, 200) 200 memory = json.loads(response.data['memory']) 201 self.assertIn('worker', memory) 202 self.assertEqual(memory['worker'], '512M') 203 self.assertIn('web', memory) 204 self.assertEqual(memory['web'], '1G') 205 # unset a value 206 body = {'memory': json.dumps({'worker': None})} 207 response = self.client.post(url, json.dumps(body), content_type='application/json') 208 self.assertEqual(response.status_code, 201) 209 limit4 = response.data 210 self.assertNotEqual(limit3['uuid'], limit4['uuid']) 211 self.assertNotIn('worker', json.dumps(response.data['memory'])) 212 # disallow put/patch/delete 213 self.assertEqual(self.client.put(url).status_code, 405) 214 self.assertEqual(self.client.patch(url).status_code, 405) 215 self.assertEqual(self.client.delete(url).status_code, 405) 216 return limit4 217 218 @mock.patch('requests.post', mock_import_repository_task) 219 def test_limit_cpu(self): 220 """ 221 Test that CPU limits can be set 222 """ 223 url = '/api/apps' 224 body = {'cluster': 'autotest'} 225 response = self.client.post(url, json.dumps(body), content_type='application/json') 226 self.assertEqual(response.status_code, 201) 227 app_id = response.data['id'] 228 url = '/api/apps/{app_id}/config'.format(**locals()) 229 # check default limit 230 response = self.client.get(url, content_type='application/json') 231 self.assertEqual(response.status_code, 200) 232 self.assertIn('cpu', response.data) 233 self.assertEqual(json.loads(response.data['cpu']), {}) 234 # regression test for https://github.com/deis/deis/issues/1563 235 self.assertNotIn('"', response.data['cpu']) 236 # set an initial limit 237 body = {'cpu': json.dumps({'web': '1024'})} 238 response = self.client.post(url, json.dumps(body), content_type='application/json') 239 self.assertEqual(response.status_code, 201) 240 self.assertIn('x-deis-release', response._headers) 241 limit1 = response.data 242 # check memory limits 243 response = self.client.get(url, content_type='application/json') 244 self.assertEqual(response.status_code, 200) 245 self.assertIn('cpu', response.data) 246 cpu = json.loads(response.data['cpu']) 247 self.assertIn('web', cpu) 248 self.assertEqual(cpu['web'], '1024') 249 # set an additional value 250 body = {'cpu': json.dumps({'worker': '512'})} 251 response = self.client.post(url, json.dumps(body), content_type='application/json') 252 self.assertEqual(response.status_code, 201) 253 limit2 = response.data 254 self.assertNotEqual(limit1['uuid'], limit2['uuid']) 255 cpu = json.loads(response.data['cpu']) 256 self.assertIn('worker', cpu) 257 self.assertEqual(cpu['worker'], '512') 258 self.assertIn('web', cpu) 259 self.assertEqual(cpu['web'], '1024') 260 # read the limit again 261 response = self.client.get(url) 262 self.assertEqual(response.status_code, 200) 263 limit3 = response.data 264 self.assertEqual(limit2, limit3) 265 cpu = json.loads(response.data['cpu']) 266 self.assertIn('worker', cpu) 267 self.assertEqual(cpu['worker'], '512') 268 self.assertIn('web', cpu) 269 self.assertEqual(cpu['web'], '1024') 270 # unset a value 271 body = {'memory': json.dumps({'worker': None})} 272 response = self.client.post(url, json.dumps(body), content_type='application/json') 273 self.assertEqual(response.status_code, 201) 274 limit4 = response.data 275 self.assertNotEqual(limit3['uuid'], limit4['uuid']) 276 self.assertNotIn('worker', json.dumps(response.data['memory'])) 277 # disallow put/patch/delete 278 self.assertEqual(self.client.put(url).status_code, 405) 279 self.assertEqual(self.client.patch(url).status_code, 405) 280 self.assertEqual(self.client.delete(url).status_code, 405) 281 return limit4 282 283 @mock.patch('requests.post', mock_import_repository_task) 284 def test_tags(self): 285 """ 286 Test that tags can be set on an application 287 """ 288 url = '/api/apps' 289 body = {'cluster': 'autotest'} 290 response = self.client.post(url, json.dumps(body), content_type='application/json') 291 self.assertEqual(response.status_code, 201) 292 app_id = response.data['id'] 293 url = '/api/apps/{app_id}/config'.format(**locals()) 294 # check default 295 response = self.client.get(url, content_type='application/json') 296 self.assertEqual(response.status_code, 200) 297 self.assertIn('tags', response.data) 298 self.assertEqual(json.loads(response.data['tags']), {}) 299 # set some tags 300 body = {'tags': json.dumps({'environ': 'dev'})} 301 response = self.client.post(url, json.dumps(body), content_type='application/json') 302 self.assertEqual(response.status_code, 201) 303 self.assertIn('x-deis-release', response._headers) 304 tags1 = response.data 305 # check tags again 306 response = self.client.get(url, content_type='application/json') 307 self.assertEqual(response.status_code, 200) 308 self.assertIn('tags', response.data) 309 tags = json.loads(response.data['tags']) 310 self.assertIn('environ', tags) 311 self.assertEqual(tags['environ'], 'dev') 312 # set an additional value 313 body = {'tags': json.dumps({'rack': '1'})} 314 response = self.client.post(url, json.dumps(body), content_type='application/json') 315 self.assertEqual(response.status_code, 201) 316 tags2 = response.data 317 self.assertNotEqual(tags1['uuid'], tags2['uuid']) 318 tags = json.loads(response.data['tags']) 319 self.assertIn('rack', tags) 320 self.assertEqual(tags['rack'], '1') 321 self.assertIn('environ', tags) 322 self.assertEqual(tags['environ'], 'dev') 323 # read the limit again 324 response = self.client.get(url) 325 self.assertEqual(response.status_code, 200) 326 tags3 = response.data 327 self.assertEqual(tags2, tags3) 328 tags = json.loads(response.data['tags']) 329 self.assertIn('rack', tags) 330 self.assertEqual(tags['rack'], '1') 331 self.assertIn('environ', tags) 332 self.assertEqual(tags['environ'], 'dev') 333 # unset a value 334 body = {'tags': json.dumps({'rack': None})} 335 response = self.client.post(url, json.dumps(body), content_type='application/json') 336 self.assertEqual(response.status_code, 201) 337 tags4 = response.data 338 self.assertNotEqual(tags3['uuid'], tags4['uuid']) 339 self.assertNotIn('rack', json.dumps(response.data['tags'])) 340 # set invalid values 341 body = {'tags': json.dumps({'valid': 'in\nvalid'})} 342 response = self.client.post(url, json.dumps(body), content_type='application/json') 343 self.assertEqual(response.status_code, 400) 344 body = {'tags': json.dumps({'in.valid': 'valid'})} 345 response = self.client.post(url, json.dumps(body), content_type='application/json') 346 self.assertEqual(response.status_code, 400) 347 # disallow put/patch/delete 348 self.assertEqual(self.client.put(url).status_code, 405) 349 self.assertEqual(self.client.patch(url).status_code, 405) 350 self.assertEqual(self.client.delete(url).status_code, 405) 351 return tags4