github.com/amrnt/deis@v1.3.1/controller/api/tests/test_container.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.contrib.auth.models import User 14 from django.test import TransactionTestCase 15 from django_fsm import TransitionNotAllowed 16 from rest_framework.authtoken.models import Token 17 18 from api.models import App, Build, Container, Release 19 20 21 def mock_import_repository_task(*args, **kwargs): 22 resp = requests.Response() 23 resp.status_code = 200 24 resp._content_consumed = True 25 return resp 26 27 28 class ContainerTest(TransactionTestCase): 29 """Tests creation of containers on nodes""" 30 31 fixtures = ['tests.json'] 32 33 def setUp(self): 34 self.user = User.objects.get(username='autotest') 35 self.token = Token.objects.get(user=self.user).key 36 37 def test_container_state_good(self): 38 """Test that the finite state machine transitions with a good scheduler""" 39 url = '/v1/apps' 40 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 41 self.assertEqual(response.status_code, 201) 42 app_id = response.data['id'] 43 app = App.objects.get(id=app_id) 44 user = User.objects.get(username='autotest') 45 build = Build.objects.create(owner=user, app=app, image="qwerty") 46 # create an initial release 47 release = Release.objects.create(version=2, 48 owner=user, 49 app=app, 50 config=app.config_set.latest(), 51 build=build) 52 # create a container 53 c = Container.objects.create(owner=user, 54 app=app, 55 release=release, 56 type='web', 57 num=1) 58 self.assertEqual(c.state, 'initialized') 59 # test an illegal transition 60 self.assertRaises(TransitionNotAllowed, lambda: c.start()) 61 c.create() 62 self.assertEqual(c.state, 'created') 63 c.start() 64 self.assertEqual(c.state, 'up') 65 c.destroy() 66 self.assertEqual(c.state, 'destroyed') 67 68 def test_container_state_protected(self): 69 """Test that you cannot directly modify the state""" 70 url = '/v1/apps' 71 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 72 self.assertEqual(response.status_code, 201) 73 app_id = response.data['id'] 74 app = App.objects.get(id=app_id) 75 user = User.objects.get(username='autotest') 76 build = Build.objects.create(owner=user, app=app, image="qwerty") 77 # create an initial release 78 release = Release.objects.create(version=2, 79 owner=user, 80 app=app, 81 config=app.config_set.latest(), 82 build=build) 83 # create a container 84 c = Container.objects.create(owner=user, 85 app=app, 86 release=release, 87 type='web', 88 num=1) 89 self.assertRaises(AttributeError, lambda: setattr(c, 'state', 'up')) 90 91 def test_container_api_heroku(self): 92 url = '/v1/apps' 93 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 94 self.assertEqual(response.status_code, 201) 95 app_id = response.data['id'] 96 # should start with zero 97 url = "/v1/apps/{app_id}/containers".format(**locals()) 98 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 99 self.assertEqual(response.status_code, 200) 100 self.assertEqual(len(response.data['results']), 0) 101 # post a new build 102 url = "/v1/apps/{app_id}/builds".format(**locals()) 103 body = {'image': 'autotest/example', 'sha': 'a'*40, 104 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 105 response = self.client.post(url, json.dumps(body), content_type='application/json', 106 HTTP_AUTHORIZATION='token {}'.format(self.token)) 107 self.assertEqual(response.status_code, 201) 108 # scale up 109 url = "/v1/apps/{app_id}/scale".format(**locals()) 110 # test setting one proc type at a time 111 body = {'web': 4} 112 response = self.client.post(url, json.dumps(body), content_type='application/json', 113 HTTP_AUTHORIZATION='token {}'.format(self.token)) 114 self.assertEqual(response.status_code, 204) 115 body = {'worker': 2} 116 response = self.client.post(url, json.dumps(body), content_type='application/json', 117 HTTP_AUTHORIZATION='token {}'.format(self.token)) 118 self.assertEqual(response.status_code, 204) 119 url = "/v1/apps/{app_id}/containers".format(**locals()) 120 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 121 self.assertEqual(response.status_code, 200) 122 self.assertEqual(len(response.data['results']), 6) 123 url = "/v1/apps/{app_id}".format(**locals()) 124 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 125 self.assertEqual(response.status_code, 200) 126 # ensure the structure field is up-to-date 127 self.assertEqual(response.data['structure']['web'], 4) 128 self.assertEqual(response.data['structure']['worker'], 2) 129 # test listing/retrieving container info 130 url = "/v1/apps/{app_id}/containers/web".format(**locals()) 131 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 132 self.assertEqual(response.status_code, 200) 133 self.assertEqual(len(response.data['results']), 4) 134 num = response.data['results'][0]['num'] 135 url = "/v1/apps/{app_id}/containers/web/{num}".format(**locals()) 136 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 137 self.assertEqual(response.status_code, 200) 138 self.assertEqual(response.data['num'], num) 139 # scale down 140 url = "/v1/apps/{app_id}/scale".format(**locals()) 141 # test setting two proc types at a time 142 body = {'web': 2, 'worker': 1} 143 response = self.client.post(url, json.dumps(body), content_type='application/json', 144 HTTP_AUTHORIZATION='token {}'.format(self.token)) 145 self.assertEqual(response.status_code, 204) 146 url = "/v1/apps/{app_id}/containers".format(**locals()) 147 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 148 self.assertEqual(response.status_code, 200) 149 self.assertEqual(len(response.data['results']), 3) 150 self.assertEqual(max(c['num'] for c in response.data['results']), 2) 151 url = "/v1/apps/{app_id}".format(**locals()) 152 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 153 self.assertEqual(response.status_code, 200) 154 # ensure the structure field is up-to-date 155 self.assertEqual(response.data['structure']['web'], 2) 156 self.assertEqual(response.data['structure']['worker'], 1) 157 # scale down to 0 158 url = "/v1/apps/{app_id}/scale".format(**locals()) 159 body = {'web': 0, 'worker': 0} 160 response = self.client.post(url, json.dumps(body), content_type='application/json', 161 HTTP_AUTHORIZATION='token {}'.format(self.token)) 162 self.assertEqual(response.status_code, 204) 163 url = "/v1/apps/{app_id}/containers".format(**locals()) 164 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 165 self.assertEqual(response.status_code, 200) 166 self.assertEqual(len(response.data['results']), 0) 167 url = "/v1/apps/{app_id}".format(**locals()) 168 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 169 self.assertEqual(response.status_code, 200) 170 171 @mock.patch('requests.post', mock_import_repository_task) 172 def test_container_api_docker(self): 173 url = '/v1/apps' 174 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 175 self.assertEqual(response.status_code, 201) 176 app_id = response.data['id'] 177 # should start with zero 178 url = "/v1/apps/{app_id}/containers".format(**locals()) 179 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 180 self.assertEqual(response.status_code, 200) 181 self.assertEqual(len(response.data['results']), 0) 182 # post a new build 183 url = "/v1/apps/{app_id}/builds".format(**locals()) 184 body = {'image': 'autotest/example', 'dockerfile': "FROM busybox\nCMD /bin/true"} 185 response = self.client.post(url, json.dumps(body), content_type='application/json', 186 HTTP_AUTHORIZATION='token {}'.format(self.token)) 187 self.assertEqual(response.status_code, 201) 188 # scale up 189 url = "/v1/apps/{app_id}/scale".format(**locals()) 190 body = {'cmd': 6} 191 response = self.client.post(url, json.dumps(body), content_type='application/json', 192 HTTP_AUTHORIZATION='token {}'.format(self.token)) 193 self.assertEqual(response.status_code, 204) 194 url = "/v1/apps/{app_id}/containers".format(**locals()) 195 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 196 self.assertEqual(response.status_code, 200) 197 self.assertEqual(len(response.data['results']), 6) 198 url = "/v1/apps/{app_id}".format(**locals()) 199 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 200 self.assertEqual(response.status_code, 200) 201 # test listing/retrieving container info 202 url = "/v1/apps/{app_id}/containers/cmd".format(**locals()) 203 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 204 self.assertEqual(response.status_code, 200) 205 self.assertEqual(len(response.data['results']), 6) 206 # scale down 207 url = "/v1/apps/{app_id}/scale".format(**locals()) 208 body = {'cmd': 3} 209 response = self.client.post(url, json.dumps(body), content_type='application/json', 210 HTTP_AUTHORIZATION='token {}'.format(self.token)) 211 self.assertEqual(response.status_code, 204) 212 url = "/v1/apps/{app_id}/containers".format(**locals()) 213 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 214 self.assertEqual(response.status_code, 200) 215 self.assertEqual(len(response.data['results']), 3) 216 self.assertEqual(max(c['num'] for c in response.data['results']), 3) 217 url = "/v1/apps/{app_id}".format(**locals()) 218 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 219 self.assertEqual(response.status_code, 200) 220 # scale down to 0 221 url = "/v1/apps/{app_id}/scale".format(**locals()) 222 body = {'cmd': 0} 223 response = self.client.post(url, json.dumps(body), content_type='application/json', 224 HTTP_AUTHORIZATION='token {}'.format(self.token)) 225 self.assertEqual(response.status_code, 204) 226 url = "/v1/apps/{app_id}/containers".format(**locals()) 227 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 228 self.assertEqual(response.status_code, 200) 229 self.assertEqual(len(response.data['results']), 0) 230 url = "/v1/apps/{app_id}".format(**locals()) 231 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 232 self.assertEqual(response.status_code, 200) 233 234 @mock.patch('requests.post', mock_import_repository_task) 235 def test_container_release(self): 236 url = '/v1/apps' 237 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 238 self.assertEqual(response.status_code, 201) 239 app_id = response.data['id'] 240 # should start with zero 241 url = "/v1/apps/{app_id}/containers".format(**locals()) 242 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 243 self.assertEqual(response.status_code, 200) 244 self.assertEqual(len(response.data['results']), 0) 245 # post a new build 246 url = "/v1/apps/{app_id}/builds".format(**locals()) 247 body = {'image': 'autotest/example', 'sha': 'a'*40, 248 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 249 response = self.client.post(url, json.dumps(body), content_type='application/json', 250 HTTP_AUTHORIZATION='token {}'.format(self.token)) 251 self.assertEqual(response.status_code, 201) 252 # scale up 253 url = "/v1/apps/{app_id}/scale".format(**locals()) 254 body = {'web': 1} 255 response = self.client.post(url, json.dumps(body), content_type='application/json', 256 HTTP_AUTHORIZATION='token {}'.format(self.token)) 257 self.assertEqual(response.status_code, 204) 258 url = "/v1/apps/{app_id}/containers".format(**locals()) 259 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 260 self.assertEqual(response.status_code, 200) 261 self.assertEqual(len(response.data['results']), 1) 262 self.assertEqual(response.data['results'][0]['release'], 'v2') 263 # post a new build 264 url = "/v1/apps/{app_id}/builds".format(**locals()) 265 body = {'image': 'autotest/example'} 266 response = self.client.post(url, json.dumps(body), content_type='application/json', 267 HTTP_AUTHORIZATION='token {}'.format(self.token)) 268 self.assertEqual(response.status_code, 201) 269 self.assertEqual(response.data['image'], body['image']) 270 url = "/v1/apps/{app_id}/containers".format(**locals()) 271 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 272 self.assertEqual(response.status_code, 200) 273 self.assertEqual(len(response.data['results']), 1) 274 self.assertEqual(response.data['results'][0]['release'], 'v3') 275 # post new config 276 url = "/v1/apps/{app_id}/config".format(**locals()) 277 body = {'values': json.dumps({'KEY': 'value'})} 278 response = self.client.post(url, json.dumps(body), content_type='application/json', 279 HTTP_AUTHORIZATION='token {}'.format(self.token)) 280 self.assertEqual(response.status_code, 201) 281 url = "/v1/apps/{app_id}/containers".format(**locals()) 282 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 283 self.assertEqual(response.status_code, 200) 284 self.assertEqual(len(response.data['results']), 1) 285 self.assertEqual(response.data['results'][0]['release'], 'v4') 286 287 def test_container_errors(self): 288 url = '/v1/apps' 289 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 290 self.assertEqual(response.status_code, 201) 291 app_id = response.data['id'] 292 # create a release so we can scale 293 app = App.objects.get(id=app_id) 294 user = User.objects.get(username='autotest') 295 build = Build.objects.create(owner=user, app=app, image="qwerty") 296 # create an initial release 297 Release.objects.create(version=2, 298 owner=user, 299 app=app, 300 config=app.config_set.latest(), 301 build=build) 302 url = "/v1/apps/{app_id}/scale".format(**locals()) 303 body = {'web': 'not_an_int'} 304 response = self.client.post(url, json.dumps(body), content_type='application/json', 305 HTTP_AUTHORIZATION='token {}'.format(self.token)) 306 self.assertEqual(response.status_code, 400) 307 self.assertEqual(response.data, {'detail': 'Invalid scaling format'}) 308 body = {'invalid': 1} 309 response = self.client.post(url, json.dumps(body), content_type='application/json', 310 HTTP_AUTHORIZATION='token {}'.format(self.token)) 311 self.assertContains(response, 'Container type invalid', status_code=400) 312 313 def test_container_str(self): 314 """Test the text representation of a container.""" 315 url = '/v1/apps' 316 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 317 self.assertEqual(response.status_code, 201) 318 app_id = response.data['id'] 319 # post a new build 320 url = "/v1/apps/{app_id}/builds".format(**locals()) 321 body = {'image': 'autotest/example', 'sha': 'a'*40, 322 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 323 response = self.client.post(url, json.dumps(body), content_type='application/json', 324 HTTP_AUTHORIZATION='token {}'.format(self.token)) 325 self.assertEqual(response.status_code, 201) 326 # scale up 327 url = "/v1/apps/{app_id}/scale".format(**locals()) 328 body = {'web': 4, 'worker': 2} 329 response = self.client.post(url, json.dumps(body), content_type='application/json', 330 HTTP_AUTHORIZATION='token {}'.format(self.token)) 331 self.assertEqual(response.status_code, 204) 332 # should start with zero 333 url = "/v1/apps/{app_id}/containers".format(**locals()) 334 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 335 self.assertEqual(response.status_code, 200) 336 self.assertEqual(len(response.data['results']), 6) 337 uuid = response.data['results'][0]['uuid'] 338 container = Container.objects.get(uuid=uuid) 339 self.assertEqual(container.short_name(), 340 "{}.{}.{}".format(container.app, container.type, container.num)) 341 self.assertEqual(str(container), 342 "{}.{}.{}".format(container.app, container.type, container.num)) 343 344 def test_container_command_format(self): 345 # regression test for https://github.com/deis/deis/pull/1285 346 url = '/v1/apps' 347 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 348 self.assertEqual(response.status_code, 201) 349 app_id = response.data['id'] 350 # post a new build 351 url = "/v1/apps/{app_id}/builds".format(**locals()) 352 body = {'image': 'autotest/example', 'sha': 'a'*40, 353 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 354 response = self.client.post(url, json.dumps(body), content_type='application/json', 355 HTTP_AUTHORIZATION='token {}'.format(self.token)) 356 self.assertEqual(response.status_code, 201) 357 # scale up 358 url = "/v1/apps/{app_id}/scale".format(**locals()) 359 body = {'web': 1} 360 response = self.client.post(url, json.dumps(body), content_type='application/json', 361 HTTP_AUTHORIZATION='token {}'.format(self.token)) 362 self.assertEqual(response.status_code, 204) 363 url = "/v1/apps/{app_id}/containers".format(**locals()) 364 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 365 # verify that the container._command property got formatted 366 self.assertEqual(response.status_code, 200) 367 self.assertEqual(len(response.data['results']), 1) 368 uuid = response.data['results'][0]['uuid'] 369 container = Container.objects.get(uuid=uuid) 370 self.assertNotIn('{c_type}', container._command) 371 372 def test_container_scale_errors(self): 373 url = '/v1/apps' 374 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 375 self.assertEqual(response.status_code, 201) 376 app_id = response.data['id'] 377 # should start with zero 378 url = "/v1/apps/{app_id}/containers".format(**locals()) 379 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 380 self.assertEqual(response.status_code, 200) 381 self.assertEqual(len(response.data['results']), 0) 382 # post a new build 383 url = "/v1/apps/{app_id}/builds".format(**locals()) 384 body = {'image': 'autotest/example', 'sha': 'a'*40, 385 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 386 response = self.client.post(url, json.dumps(body), content_type='application/json', 387 HTTP_AUTHORIZATION='token {}'.format(self.token)) 388 self.assertEqual(response.status_code, 201) 389 # scale to a negative number 390 url = "/v1/apps/{app_id}/scale".format(**locals()) 391 body = {'web': -1} 392 response = self.client.post(url, json.dumps(body), content_type='application/json', 393 HTTP_AUTHORIZATION='token {}'.format(self.token)) 394 self.assertEqual(response.status_code, 400) 395 # scale to something other than a number 396 url = "/v1/apps/{app_id}/scale".format(**locals()) 397 body = {'web': 'one'} 398 response = self.client.post(url, json.dumps(body), content_type='application/json', 399 HTTP_AUTHORIZATION='token {}'.format(self.token)) 400 self.assertEqual(response.status_code, 400) 401 # scale to something other than a number 402 url = "/v1/apps/{app_id}/scale".format(**locals()) 403 body = {'web': [1]} 404 response = self.client.post(url, json.dumps(body), content_type='application/json', 405 HTTP_AUTHORIZATION='token {}'.format(self.token)) 406 self.assertEqual(response.status_code, 400) 407 # scale up to an integer as a sanity check 408 url = "/v1/apps/{app_id}/scale".format(**locals()) 409 body = {'web': 1} 410 response = self.client.post(url, json.dumps(body), content_type='application/json', 411 HTTP_AUTHORIZATION='token {}'.format(self.token)) 412 self.assertEqual(response.status_code, 204) 413 414 def test_admin_can_manage_other_containers(self): 415 """If a non-admin user creates a container, an administrator should be able to 416 manage it. 417 """ 418 user = User.objects.get(username='autotest2') 419 token = Token.objects.get(user=user).key 420 url = '/v1/apps' 421 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(token)) 422 self.assertEqual(response.status_code, 201) 423 app_id = response.data['id'] 424 # post a new build 425 url = "/v1/apps/{app_id}/builds".format(**locals()) 426 body = {'image': 'autotest/example', 'sha': 'a'*40, 427 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 428 response = self.client.post(url, json.dumps(body), content_type='application/json', 429 HTTP_AUTHORIZATION='token {}'.format(token)) 430 self.assertEqual(response.status_code, 201) 431 # login as admin, scale up 432 url = "/v1/apps/{app_id}/scale".format(**locals()) 433 body = {'web': 4, 'worker': 2} 434 response = self.client.post(url, json.dumps(body), content_type='application/json', 435 HTTP_AUTHORIZATION='token {}'.format(self.token)) 436 self.assertEqual(response.status_code, 204) 437 438 def test_scale_without_build_should_error(self): 439 """A user should not be able to scale processes unless a build is present.""" 440 app_id = 'autotest' 441 url = '/v1/apps' 442 body = {'cluster': 'autotest', 'id': app_id} 443 response = self.client.post(url, json.dumps(body), content_type='application/json', 444 HTTP_AUTHORIZATION='token {}'.format(self.token)) 445 url = '/v1/apps/{app_id}/scale'.format(**locals()) 446 body = {'web': '1'} 447 response = self.client.post(url, json.dumps(body), content_type='application/json', 448 HTTP_AUTHORIZATION='token {}'.format(self.token)) 449 self.assertEqual(response.status_code, 400) 450 self.assertEqual(response.data, {'detail': 'No build associated with this release'}) 451 452 def test_command_good(self): 453 """Test the default command for each container workflow""" 454 url = '/v1/apps' 455 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 456 self.assertEqual(response.status_code, 201) 457 app_id = response.data['id'] 458 app = App.objects.get(id=app_id) 459 user = User.objects.get(username='autotest') 460 # Heroku Buildpack app 461 build = Build.objects.create(owner=user, 462 app=app, 463 image="qwerty", 464 procfile={'web': 'node server.js', 465 'worker': 'node worker.js'}, 466 sha='african-swallow', 467 dockerfile='') 468 # create an initial release 469 release = Release.objects.create(version=2, 470 owner=user, 471 app=app, 472 config=app.config_set.latest(), 473 build=build) 474 # create a container 475 c = Container.objects.create(owner=user, 476 app=app, 477 release=release, 478 type='web', 479 num=1) 480 # use `start web` for backwards compatibility with slugrunner 481 self.assertEqual(c._command, 'start web') 482 c.type = 'worker' 483 self.assertEqual(c._command, 'start worker') 484 # switch to docker image app 485 build.sha = None 486 c.type = 'web' 487 self.assertEqual(c._command, "bash -c 'node server.js'") 488 # switch to dockerfile app 489 build.sha = 'european-swallow' 490 build.dockerfile = 'dockerdockerdocker' 491 self.assertEqual(c._command, "bash -c 'node server.js'") 492 c.type = 'cmd' 493 self.assertEqual(c._command, '') 494 # ensure we can override the cmd process type in a Procfile 495 build.procfile['cmd'] = 'node server.js' 496 self.assertEqual(c._command, "bash -c 'node server.js'") 497 c.type = 'worker' 498 self.assertEqual(c._command, "bash -c 'node worker.js'") 499 c.release.build.procfile = None 500 # for backwards compatibility if no Procfile is supplied 501 self.assertEqual(c._command, 'start worker') 502 503 def test_run_command_good(self): 504 """Test the run command for each container workflow""" 505 url = '/v1/apps' 506 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 507 self.assertEqual(response.status_code, 201) 508 app_id = response.data['id'] 509 app = App.objects.get(id=app_id) 510 user = User.objects.get(username='autotest') 511 # dockerfile + procfile worflow 512 build = Build.objects.create(owner=user, 513 app=app, 514 image="qwerty", 515 procfile={'web': 'node server.js', 516 'worker': 'node worker.js'}, 517 dockerfile='foo', 518 sha='somereallylongsha') 519 # create an initial release 520 release = Release.objects.create(version=2, 521 owner=user, 522 app=app, 523 config=app.config_set.latest(), 524 build=build) 525 # create a container 526 c = Container.objects.create(owner=user, 527 app=app, 528 release=release, 529 type='web', 530 num=1) 531 rc, output = c.run('echo hi') 532 self.assertEqual(rc, 0) 533 self.assertEqual(json.loads(output)['entrypoint'], '/bin/bash') 534 # docker image workflow 535 build.dockerfile = None 536 build.sha = None 537 rc, output = c.run('echo hi') 538 self.assertEqual(json.loads(output)['entrypoint'], '/bin/bash') 539 # procfile workflow 540 build.sha = 'somereallylongsha' 541 rc, output = c.run('echo hi') 542 self.assertEqual(json.loads(output)['entrypoint'], '/runner/init') 543 544 def test_scale_with_unauthorized_user_returns_403(self): 545 """An unauthorized user should not be able to access an app's resources. 546 547 If an unauthorized user is trying to scale an app he or she does not have access to, it 548 should return a 403. Currently, it returns a 404. FIXME! 549 """ 550 url = '/v1/apps' 551 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 552 self.assertEqual(response.status_code, 201) 553 app_id = response.data['id'] 554 # post a new build 555 url = "/v1/apps/{app_id}/builds".format(**locals()) 556 body = {'image': 'autotest/example', 'sha': 'a'*40, 557 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 558 response = self.client.post(url, json.dumps(body), content_type='application/json', 559 HTTP_AUTHORIZATION='token {}'.format(self.token)) 560 unauthorized_user = User.objects.get(username='autotest2') 561 unauthorized_token = Token.objects.get(user=unauthorized_user).key 562 # scale up with unauthorized user 563 url = "/v1/apps/{app_id}/scale".format(**locals()) 564 body = {'web': 4} 565 response = self.client.post(url, json.dumps(body), content_type='application/json', 566 HTTP_AUTHORIZATION='token {}'.format(unauthorized_token)) 567 self.assertEqual(response.status_code, 403)