github.com/ahjdzx/deis@v1.1.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.assertContains(response, 'Invalid scaling format', status_code=400) 307 body = {'invalid': 1} 308 response = self.client.post(url, json.dumps(body), content_type='application/json', 309 HTTP_AUTHORIZATION='token {}'.format(self.token)) 310 self.assertContains(response, 'Container type invalid', status_code=400) 311 312 def test_container_str(self): 313 """Test the text representation of a container.""" 314 url = '/v1/apps' 315 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 316 self.assertEqual(response.status_code, 201) 317 app_id = response.data['id'] 318 # post a new build 319 url = "/v1/apps/{app_id}/builds".format(**locals()) 320 body = {'image': 'autotest/example', 'sha': 'a'*40, 321 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 322 response = self.client.post(url, json.dumps(body), content_type='application/json', 323 HTTP_AUTHORIZATION='token {}'.format(self.token)) 324 self.assertEqual(response.status_code, 201) 325 # scale up 326 url = "/v1/apps/{app_id}/scale".format(**locals()) 327 body = {'web': 4, 'worker': 2} 328 response = self.client.post(url, json.dumps(body), content_type='application/json', 329 HTTP_AUTHORIZATION='token {}'.format(self.token)) 330 self.assertEqual(response.status_code, 204) 331 # should start with zero 332 url = "/v1/apps/{app_id}/containers".format(**locals()) 333 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 334 self.assertEqual(response.status_code, 200) 335 self.assertEqual(len(response.data['results']), 6) 336 uuid = response.data['results'][0]['uuid'] 337 container = Container.objects.get(uuid=uuid) 338 self.assertEqual(container.short_name(), 339 "{}.{}.{}".format(container.app, container.type, container.num)) 340 self.assertEqual(str(container), 341 "{}.{}.{}".format(container.app, container.type, container.num)) 342 343 def test_container_command_format(self): 344 # regression test for https://github.com/deis/deis/pull/1285 345 url = '/v1/apps' 346 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 347 self.assertEqual(response.status_code, 201) 348 app_id = response.data['id'] 349 # post a new build 350 url = "/v1/apps/{app_id}/builds".format(**locals()) 351 body = {'image': 'autotest/example', 'sha': 'a'*40, 352 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 353 response = self.client.post(url, json.dumps(body), content_type='application/json', 354 HTTP_AUTHORIZATION='token {}'.format(self.token)) 355 self.assertEqual(response.status_code, 201) 356 # scale up 357 url = "/v1/apps/{app_id}/scale".format(**locals()) 358 body = {'web': 1} 359 response = self.client.post(url, json.dumps(body), content_type='application/json', 360 HTTP_AUTHORIZATION='token {}'.format(self.token)) 361 self.assertEqual(response.status_code, 204) 362 url = "/v1/apps/{app_id}/containers".format(**locals()) 363 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 364 # verify that the container._command property got formatted 365 self.assertEqual(response.status_code, 200) 366 self.assertEqual(len(response.data['results']), 1) 367 uuid = response.data['results'][0]['uuid'] 368 container = Container.objects.get(uuid=uuid) 369 self.assertNotIn('{c_type}', container._command) 370 371 def test_container_scale_errors(self): 372 url = '/v1/apps' 373 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 374 self.assertEqual(response.status_code, 201) 375 app_id = response.data['id'] 376 # should start with zero 377 url = "/v1/apps/{app_id}/containers".format(**locals()) 378 response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 379 self.assertEqual(response.status_code, 200) 380 self.assertEqual(len(response.data['results']), 0) 381 # post a new build 382 url = "/v1/apps/{app_id}/builds".format(**locals()) 383 body = {'image': 'autotest/example', 'sha': 'a'*40, 384 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 385 response = self.client.post(url, json.dumps(body), content_type='application/json', 386 HTTP_AUTHORIZATION='token {}'.format(self.token)) 387 self.assertEqual(response.status_code, 201) 388 # scale to a negative number 389 url = "/v1/apps/{app_id}/scale".format(**locals()) 390 body = {'web': -1} 391 response = self.client.post(url, json.dumps(body), content_type='application/json', 392 HTTP_AUTHORIZATION='token {}'.format(self.token)) 393 self.assertEqual(response.status_code, 400) 394 # scale to something other than a number 395 url = "/v1/apps/{app_id}/scale".format(**locals()) 396 body = {'web': 'one'} 397 response = self.client.post(url, json.dumps(body), content_type='application/json', 398 HTTP_AUTHORIZATION='token {}'.format(self.token)) 399 self.assertEqual(response.status_code, 400) 400 # scale to something other than a number 401 url = "/v1/apps/{app_id}/scale".format(**locals()) 402 body = {'web': [1]} 403 response = self.client.post(url, json.dumps(body), content_type='application/json', 404 HTTP_AUTHORIZATION='token {}'.format(self.token)) 405 self.assertEqual(response.status_code, 400) 406 # scale up to an integer as a sanity check 407 url = "/v1/apps/{app_id}/scale".format(**locals()) 408 body = {'web': 1} 409 response = self.client.post(url, json.dumps(body), content_type='application/json', 410 HTTP_AUTHORIZATION='token {}'.format(self.token)) 411 self.assertEqual(response.status_code, 204) 412 413 def test_admin_can_manage_other_containers(self): 414 """If a non-admin user creates a container, an administrator should be able to 415 manage it. 416 """ 417 user = User.objects.get(username='autotest2') 418 token = Token.objects.get(user=user).key 419 url = '/v1/apps' 420 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(token)) 421 self.assertEqual(response.status_code, 201) 422 app_id = response.data['id'] 423 # post a new build 424 url = "/v1/apps/{app_id}/builds".format(**locals()) 425 body = {'image': 'autotest/example', 'sha': 'a'*40, 426 'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})} 427 response = self.client.post(url, json.dumps(body), content_type='application/json', 428 HTTP_AUTHORIZATION='token {}'.format(token)) 429 self.assertEqual(response.status_code, 201) 430 # login as admin, scale up 431 url = "/v1/apps/{app_id}/scale".format(**locals()) 432 body = {'web': 4, 'worker': 2} 433 response = self.client.post(url, json.dumps(body), content_type='application/json', 434 HTTP_AUTHORIZATION='token {}'.format(self.token)) 435 self.assertEqual(response.status_code, 204) 436 437 def test_scale_without_build_should_error(self): 438 """A user should not be able to scale processes unless a build is present.""" 439 app_id = 'autotest' 440 url = '/v1/apps' 441 body = {'cluster': 'autotest', 'id': app_id} 442 response = self.client.post(url, json.dumps(body), content_type='application/json', 443 HTTP_AUTHORIZATION='token {}'.format(self.token)) 444 url = '/v1/apps/{app_id}/scale'.format(**locals()) 445 body = {'web': '1'} 446 response = self.client.post(url, json.dumps(body), content_type='application/json', 447 HTTP_AUTHORIZATION='token {}'.format(self.token)) 448 self.assertEqual(response.status_code, 400) 449 self.assertEqual(response.data, "No build associated with this release") 450 451 def test_command_good(self): 452 """Test the default command for each container workflow""" 453 url = '/v1/apps' 454 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 455 self.assertEqual(response.status_code, 201) 456 app_id = response.data['id'] 457 app = App.objects.get(id=app_id) 458 user = User.objects.get(username='autotest') 459 # Heroku Buildpack app 460 build = Build.objects.create(owner=user, 461 app=app, 462 image="qwerty", 463 procfile={'web': 'node server.js', 464 'worker': 'node worker.js'}, 465 sha='african-swallow', 466 dockerfile='') 467 # create an initial release 468 release = Release.objects.create(version=2, 469 owner=user, 470 app=app, 471 config=app.config_set.latest(), 472 build=build) 473 # create a container 474 c = Container.objects.create(owner=user, 475 app=app, 476 release=release, 477 type='web', 478 num=1) 479 # use `start web` for backwards compatibility with slugrunner 480 self.assertEqual(c._command, 'start web') 481 c.type = 'worker' 482 self.assertEqual(c._command, 'start worker') 483 # switch to docker image app 484 build.sha = None 485 c.type = 'web' 486 self.assertEqual(c._command, "bash -c 'node server.js'") 487 # switch to dockerfile app 488 build.sha = 'european-swallow' 489 build.dockerfile = 'dockerdockerdocker' 490 self.assertEqual(c._command, "bash -c 'node server.js'") 491 c.type = 'cmd' 492 self.assertEqual(c._command, '') 493 # ensure we can override the cmd process type in a Procfile 494 build.procfile['cmd'] = 'node server.js' 495 self.assertEqual(c._command, "bash -c 'node server.js'") 496 c.type = 'worker' 497 self.assertEqual(c._command, "bash -c 'node worker.js'") 498 c.release.build.procfile = None 499 # for backwards compatibility if no Procfile is supplied 500 self.assertEqual(c._command, 'start worker') 501 502 def test_run_command_good(self): 503 """Test the run command for each container workflow""" 504 url = '/v1/apps' 505 response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token)) 506 self.assertEqual(response.status_code, 201) 507 app_id = response.data['id'] 508 app = App.objects.get(id=app_id) 509 user = User.objects.get(username='autotest') 510 # dockerfile + procfile worflow 511 build = Build.objects.create(owner=user, 512 app=app, 513 image="qwerty", 514 procfile={'web': 'node server.js', 515 'worker': 'node worker.js'}, 516 dockerfile='foo', 517 sha='somereallylongsha') 518 # create an initial release 519 release = Release.objects.create(version=2, 520 owner=user, 521 app=app, 522 config=app.config_set.latest(), 523 build=build) 524 # create a container 525 c = Container.objects.create(owner=user, 526 app=app, 527 release=release, 528 type='web', 529 num=1) 530 rc, output = c.run('echo hi') 531 self.assertEqual(rc, 0) 532 self.assertEqual(json.loads(output)['entrypoint'], '/bin/bash') 533 # docker image workflow 534 build.dockerfile = None 535 build.sha = None 536 rc, output = c.run('echo hi') 537 self.assertEqual(json.loads(output)['entrypoint'], '/bin/bash') 538 # procfile workflow 539 build.sha = 'somereallylongsha' 540 rc, output = c.run('echo hi') 541 self.assertEqual(json.loads(output)['entrypoint'], '/runner/init')