Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions rootfs/api/models/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
from docker import auth as docker_auth
from django.conf import settings
from django.db import models
from django.db.models import F, Func, Value, JSONField
from django.contrib.auth import get_user_model
from rest_framework.exceptions import ValidationError, NotFound

from api.utils import get_session
from api.utils import get_session, dict_diff
from api.exceptions import AlreadyExists, DryccException, ServiceUnavailable
from api.utils import DeployLock, generate_app_name, apply_tasks
from scheduler import KubeHTTPException, KubeException
Expand Down Expand Up @@ -828,29 +829,36 @@ def _scale(self, user, structure, release, app_settings): # noqa
structure[target] = int(count)
validate_app_structure(structure)
except (TypeError, ValueError, ValidationError) as e:
raise DryccException('Invalid scaling format: {}'.format(e))
err_msg = 'Invalid scaling format: {}'.format(e)
self.log(err_msg)
raise DryccException(err_msg)

# test for available process types
for ptype in structure:
if ptype not in (PTYPE_WEB, PTYPE_RUN) and \
ptype not in release.ptypes:
raise NotFound(
'Container type {} does not exist in application'.format(ptype))

# merge current structure and the new items together
old_structure = self.structure
new_structure = old_structure.copy()
new_structure.update(structure)
if new_structure != self.structure:
err_msg = 'Container type {} does not exist in application'.format(ptype)
self.log(err_msg)
raise NotFound(err_msg)

new_scale = dict_diff(structure, self.structure).get("changed", {})
old_scale = dict_diff(self.structure, structure).get("changed", {})

if new_scale:
try:
self._scale_pods(structure, release, app_settings)
self._scale_pods(new_scale, release, app_settings)
except ServiceUnavailable:
# scaling failed, go back to old scaling numbers
self._scale_pods(old_structure, release, app_settings)
self._scale_pods(old_scale, release, app_settings)
raise
# save new structure to the database
self.structure = new_structure
self.save()
App.objects.filter(id=self.id).update(
structure=Func(
F("structure"),
Value(new_scale, JSONField()),
function="jsonb_concat",
)
)
msg = '{} scaled pods '.format(user.username) + ' '.join(
"{}={}".format(k, v) for k, v in list(structure.items()))
self.log(msg)
Expand Down
10 changes: 5 additions & 5 deletions rootfs/api/tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,23 +259,23 @@ def test_build_forgotten_procfile(self, mock_requests):
response = self.client.post(url, body)
self.assertEqual(response.status_code, 201, response.data)

# verify worker is not there
# verify worker is not there, only web
url = f"/v2/apps/{app_id}/pods/"
response = self.client.get(url)
self.assertEqual(response.status_code, 200, response.data)
self.assertEqual(len(response.data['results']), 0)
self.assertEqual(len(response.data['results']), 1)

# verify web is not there
# verify web is in there
url = f"/v2/apps/{app_id}/pods/"
response = self.client.get(url)
self.assertEqual(response.status_code, 200, response.data)
self.assertEqual(len(response.data['results']), 0)
self.assertEqual(len(response.data['results']), 1)

# look at the app structure
url = f"/v2/apps/{app_id}"
response = self.client.get(url)
self.assertEqual(response.status_code, 200, response.data)
self.assertEqual(response.json()['structure'], {'web': 0})
self.assertEqual(response.json()['structure'], {'web': 1})

@override_settings(DRYCC_DEPLOY_PROCFILE_MISSING_REMOVE=False)
def test_build_no_remove_process(self, mock_requests):
Expand Down
5 changes: 2 additions & 3 deletions rootfs/api/tests/test_pods.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,10 @@ def test_modified_procfile_from_build_removes_pods(self, mock_requests):
}
response = self.client.post(build_url, body)
self.assertEqual(response.status_code, 201, response.data)

# make sure no pods are web
# web is default ptype
application = App.objects.get(id=app_id)
pods = application.list_pods(type='web')
self.assertEqual(len(pods), 0)
self.assertEqual(len(pods), 4)

def test_list_pods_failure(self, mock_requests):
"""
Expand Down