Skip to content

Commit 05c322c

Browse files
author
Matthew Fisher
committed
fix(controller): kill processes removed from procfile
When a process type is removed in a new build, the old containers are not killed, and there's no way for the user to stop them. This change will destroy the containers that no longer exist in the procfile.
1 parent 6a9bc79 commit 05c322c

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

controller/api/models.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ def _start_containers(self, to_add):
255255
def _destroy_containers(self, to_destroy):
256256
"""Destroys containers via the scheduler"""
257257
destroy_threads = []
258+
if not to_destroy:
259+
# do nothing if we didn't request any containers
260+
return
258261
for c in to_destroy:
259262
destroy_threads.append(threading.Thread(target=c.destroy))
260263
[t.start() for t in destroy_threads]
@@ -588,6 +591,19 @@ def create(self, user, *args, **kwargs):
588591
new_release.delete()
589592
raise
590593

594+
def save(self, **kwargs):
595+
try:
596+
previous_build = self.app.build_set.latest()
597+
to_destroy = []
598+
for proctype in previous_build.procfile.keys():
599+
if proctype not in self.procfile.keys():
600+
for c in self.app.container_set.filter(type=proctype):
601+
to_destroy.append(c)
602+
self.app._destroy_containers(to_destroy)
603+
except Build.DoesNotExist:
604+
pass
605+
return super(Build, self).save(**kwargs)
606+
591607
def __str__(self):
592608
return "{0}-{1}".format(self.app.id, self.uuid[:7])
593609

controller/api/tests/test_container.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ def test_container_release(self):
262262
self.assertEqual(response.data['results'][0]['release'], 'v2')
263263
# post a new build
264264
url = "/v1/apps/{app_id}/builds".format(**locals())
265-
body = {'image': 'autotest/example'}
265+
# a web proctype must exist on the second build or else the container will be removed
266+
body = {'image': 'autotest/example', 'procfile': {'web': 'echo hi'}}
266267
response = self.client.post(url, json.dumps(body), content_type='application/json',
267268
HTTP_AUTHORIZATION='token {}'.format(self.token))
268269
self.assertEqual(response.status_code, 201)
@@ -565,3 +566,30 @@ def test_scale_with_unauthorized_user_returns_403(self):
565566
response = self.client.post(url, json.dumps(body), content_type='application/json',
566567
HTTP_AUTHORIZATION='token {}'.format(unauthorized_token))
567568
self.assertEqual(response.status_code, 403)
569+
570+
def test_modified_procfile_from_build_removes_containers(self):
571+
"""
572+
When a new procfile is posted which removes a certain process type, deis should stop the
573+
existing containers.
574+
"""
575+
url = '/v1/apps'
576+
response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token))
577+
self.assertEqual(response.status_code, 201)
578+
app_id = response.data['id']
579+
# post a new build
580+
build_url = "/v1/apps/{app_id}/builds".format(**locals())
581+
body = {'image': 'autotest/example', 'sha': 'a'*40,
582+
'procfile': json.dumps({'web': 'node server.js', 'worker': 'node worker.js'})}
583+
response = self.client.post(build_url, json.dumps(body), content_type='application/json',
584+
HTTP_AUTHORIZATION='token {}'.format(self.token))
585+
url = "/v1/apps/{app_id}/scale".format(**locals())
586+
body = {'web': 4}
587+
response = self.client.post(url, json.dumps(body), content_type='application/json',
588+
HTTP_AUTHORIZATION='token {}'.format(self.token))
589+
self.assertEqual(response.status_code, 204)
590+
body = {'image': 'autotest/example', 'sha': 'a'*40,
591+
'procfile': json.dumps({'worker': 'node worker.js'})}
592+
response = self.client.post(build_url, json.dumps(body), content_type='application/json',
593+
HTTP_AUTHORIZATION='token {}'.format(self.token))
594+
self.assertEqual(response.status_code, 201)
595+
self.assertEqual(Container.objects.filter(type='web').count(), 0)

0 commit comments

Comments
 (0)