Skip to content

Commit 9f8ac04

Browse files
committed
fix(config): return a 422 if unsetting a config key that does not exist
http://www.bennadel.com/blog/2434-http-status-codes-for-invalid-data-400-vs-422.htm is a good explanation of the differences
1 parent 0e6473b commit 9f8ac04

3 files changed

Lines changed: 32 additions & 4 deletions

File tree

rootfs/api/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ class AlreadyExists(APIException):
1818
status_code = 409
1919

2020

21+
class UnprocessableEntity(APIException):
22+
status_code = 422
23+
24+
2125
class ServiceUnavailable(APIException):
2226
status_code = 503
2327
default_detail = 'Service temporarily unavailable, try again later.'

rootfs/api/models/config.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from jsonfield import JSONField
44

55
from api.models.release import Release
6-
from api.models import UuidAuditedModel, DeisException
6+
from api.models import UuidAuditedModel
7+
from api.exceptions import DeisException, UnprocessableEntity
78

89

910
class Config(UuidAuditedModel):
@@ -130,9 +131,16 @@ def save(self, **kwargs):
130131
data = getattr(previous_config, attr, {}).copy()
131132
new_data = getattr(self, attr, {}).copy()
132133

133-
data.update(new_data)
134-
# remove config keys if we provided a null value
135-
[data.pop(k) for k, v in new_data.items() if v is None]
134+
# remove config keys if a null value is provided
135+
for key, value in new_data.items():
136+
if value is None:
137+
# error if unsetting non-existing key
138+
if key not in data:
139+
raise UnprocessableEntity('{} does not exist under {}'.format(key, attr)) # noqa
140+
141+
data.pop(key)
142+
else:
143+
data[key] = value
136144
setattr(self, attr, data)
137145

138146
self.set_healthchecks()

rootfs/api/tests/test_release.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,19 @@ def json(self):
333333
body = {'version': 2}
334334
response = self.client.post(url, body)
335335
self.assertEqual(response.status_code, 400, response.data)
336+
337+
def test_release_unset_config(self, mock_requests):
338+
"""
339+
Test that a release is created when an app is created, a config can be
340+
set and then unset without causing a 409 (conflict)
341+
"""
342+
url = '/v2/apps'
343+
response = self.client.post(url)
344+
self.assertEqual(response.status_code, 201, response.data)
345+
app_id = response.data['id']
346+
347+
# check that updating config rolls a new release
348+
url = '/v2/apps/{app_id}/config'.format(**locals())
349+
body = {'cpu': json.dumps({'cmd': None})}
350+
response = self.client.post(url, body)
351+
self.assertEqual(response.status_code, 422, response.data)

0 commit comments

Comments
 (0)