Skip to content

Commit 5b706c7

Browse files
committed
Merge pull request #1630 from mboersma/1613-limit-is-config
fix(controller): store limit fields on config
2 parents e44dc1f + 0a518d6 commit 5b706c7

10 files changed

Lines changed: 388 additions & 321 deletions

File tree

client/deis.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ def limits_list(self, args):
13731373
app = args.get('--app')
13741374
if not app:
13751375
app = self._session.app
1376-
response = self._dispatch('get', "/api/apps/{}/limits".format(app))
1376+
response = self._dispatch('get', "/api/apps/{}/config".format(app))
13771377
if response.status_code == requests.codes.ok: # @UndefinedVariable
13781378
self._print_limits(app, response.json())
13791379
else:
@@ -1426,7 +1426,7 @@ def limits_set(self, args):
14261426
try:
14271427
progress = TextProgress()
14281428
progress.start()
1429-
response = self._dispatch('post', "/api/apps/{}/limits".format(app), json.dumps(body))
1429+
response = self._dispatch('post', "/api/apps/{}/config".format(app), json.dumps(body))
14301430
finally:
14311431
progress.cancel()
14321432
progress.join()
@@ -1472,7 +1472,7 @@ def limits_unset(self, args):
14721472
try:
14731473
progress = TextProgress()
14741474
progress.start()
1475-
response = self._dispatch('post', "/api/apps/{}/limits".format(app), json.dumps(body))
1475+
response = self._dispatch('post', "/api/apps/{}/config".format(app), json.dumps(body))
14761476
finally:
14771477
progress.cancel()
14781478
progress.join()
@@ -1483,7 +1483,7 @@ def limits_unset(self, args):
14831483
else:
14841484
raise ResponseError(response)
14851485

1486-
def _print_limits(self, app, limit):
1486+
def _print_limits(self, app, config):
14871487
print("=== {} Limits".format(app))
14881488

14891489
def write(d):
@@ -1498,9 +1498,9 @@ def write(d):
14981498
print(("{k:<" + str(width) + "} {v}").format(**locals()))
14991499

15001500
print("\n--- Memory")
1501-
write(json.loads(limit.get('memory', '{}')))
1501+
write(json.loads(config.get('memory', '{}')))
15021502
print("\n--- CPU")
1503-
write(json.loads(limit.get('cpu', '{}')))
1503+
write(json.loads(config.get('cpu', '{}')))
15041504

15051505
def ps(self, args):
15061506
"""

controller/api/fields.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,6 @@
88
from django import forms
99
from django.db import models
1010

11-
import json_field
12-
13-
14-
class JSONField(json_field.JSONField):
15-
16-
"""
17-
A subclass of json_field.JSONField that fixes empty JSON object
18-
encoding behavior.
19-
"""
20-
21-
def get_db_prep_value(self, value, *args, **kwargs):
22-
# if it's one of these values, it's already encoded
23-
if value in ['{}', '[]']:
24-
return value
25-
return super(JSONField, self).get_db_prep_value(value, *args, **kwargs)
26-
2711

2812
class UuidField(models.CharField):
2913
"""A univerally unique ID field."""

controller/api/models.py

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from django.utils.encoding import python_2_unicode_compatible
2222
from django_fsm import FSMField, transition
2323
from django_fsm.signals import post_transition
24+
from json_field.fields import JSONField
2425

2526
from api import fields, tasks
2627
from registry import publish_release
@@ -87,7 +88,7 @@ class Cluster(UuidAuditedModel):
8788
domain = models.CharField(max_length=128)
8889
hosts = models.CharField(max_length=256)
8990
auth = models.TextField()
90-
options = fields.JSONField(default='{}', blank=True)
91+
options = JSONField(default={}, blank=True)
9192

9293
def __str__(self):
9394
return self.id
@@ -122,7 +123,7 @@ class App(UuidAuditedModel):
122123
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
123124
id = models.SlugField(max_length=64, unique=True)
124125
cluster = models.ForeignKey('Cluster')
125-
structure = fields.JSONField(default='{}', blank=True)
126+
structure = JSONField(default={}, blank=True)
126127

127128
class Meta:
128129
permissions = (('use_app', 'Can use app'),)
@@ -135,7 +136,7 @@ def url(self):
135136
return self.id + '.' + self.cluster.domain
136137

137138
def create(self, *args, **kwargs):
138-
config = Config.objects.create(owner=self.owner, app=self, values={})
139+
config = Config.objects.create(owner=self.owner, app=self)
139140
build = Build.objects.create(owner=self.owner, app=self, image=settings.DEFAULT_BUILD)
140141
Release.objects.create(version=1, owner=self.owner, app=self, config=config, build=build)
141142

@@ -308,10 +309,8 @@ def _command_announceable(self):
308309
@transition(field=state, source=INITIALIZED, target=CREATED)
309310
def create(self):
310311
image = self.release.image
311-
kwargs = {}
312-
if self.release.config.limit is not None:
313-
kwargs = {'memory': self.release.config.limit.memory,
314-
'cpu': self.release.config.limit.cpu}
312+
kwargs = {'memory': self.release.config.memory,
313+
'cpu': self.release.config.cpu}
315314
self._scheduler.create(name=self._job_id,
316315
image=image,
317316
command=self._command,
@@ -339,10 +338,8 @@ def deploy(self, release):
339338
new_job_id = self._job_id
340339
image = self.release.image
341340
c_type = self.type
342-
kwargs = {}
343-
if self.release.config.limit is not None:
344-
kwargs = {'memory': self.release.config.limit.memory,
345-
'cpu': self.release.config.limit.cpu}
341+
kwargs = {'memory': self.release.config.memory,
342+
'cpu': self.release.config.cpu}
346343
self._scheduler.create(name=new_job_id,
347344
image=image,
348345
command=self._command.format(**locals()),
@@ -411,7 +408,7 @@ class Build(UuidAuditedModel):
411408

412409
# optional fields populated by builder
413410
sha = models.CharField(max_length=40, blank=True)
414-
procfile = fields.JSONField(default='{}', blank=True)
411+
procfile = JSONField(default={}, blank=True)
415412
dockerfile = models.TextField(blank=True)
416413

417414
class Meta:
@@ -432,29 +429,9 @@ class Config(UuidAuditedModel):
432429

433430
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
434431
app = models.ForeignKey('App')
435-
values = fields.JSONField(default='{}', blank=True)
436-
limit = models.ForeignKey('Limit', null=True)
437-
438-
class Meta:
439-
get_latest_by = 'created'
440-
ordering = ['-created']
441-
unique_together = (('app', 'uuid'),)
442-
443-
def __str__(self):
444-
return "{}-{}".format(self.app.id, self.uuid[:7])
445-
446-
447-
@python_2_unicode_compatible
448-
class Limit(UuidAuditedModel):
449-
"""
450-
Set of resource limits applied by the scheduler
451-
during runtime execution of the Application.
452-
"""
453-
454-
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
455-
app = models.ForeignKey('App')
456-
memory = fields.JSONField(default='{}', blank=True)
457-
cpu = fields.JSONField(default='{}', blank=True)
432+
values = JSONField(default={}, blank=True)
433+
memory = JSONField(default={}, blank=True)
434+
cpu = JSONField(default={}, blank=True)
458435

459436
class Meta:
460437
get_latest_by = 'created'
@@ -553,7 +530,6 @@ def save(self, *args, **kwargs): # noqa
553530
# compare this build to the previous build
554531
old_build = prev_release.build if prev_release else None
555532
old_config = prev_release.config if prev_release else None
556-
old_limit = prev_release.config.limit if prev_release else None
557533
# if the build changed, log it and who pushed it
558534
if self.version == 1:
559535
self.summary += "{} created initial release".format(self.app.owner)
@@ -579,15 +555,14 @@ def save(self, *args, **kwargs): # noqa
579555
if self.summary:
580556
self.summary += ' and '
581557
self.summary += "{} {}".format(self.config.owner, changes)
582-
# if the limit changes, log the dict diff
583-
if self.config.limit != old_limit:
558+
# if the limits changed (memory or cpu), log the dict diff
584559
changes = []
585-
old_mem = old_limit.memory if old_limit else {}
586-
diff = dict_diff(self.config.limit.memory, old_mem)
560+
old_mem = old_config.memory if old_config else {}
561+
diff = dict_diff(self.config.memory, old_mem)
587562
if diff.get('added') or diff.get('changed') or diff.get('deleted'):
588563
changes.append('memory')
589-
old_cpu = old_limit.cpu if old_limit else {}
590-
diff = dict_diff(self.config.limit.cpu, old_cpu)
564+
old_cpu = old_config.cpu if old_config else {}
565+
diff = dict_diff(self.config.cpu, old_cpu)
591566
if diff.get('added') or diff.get('changed') or diff.get('deleted'):
592567
changes.append('cpu')
593568
if changes:

controller/api/serializers.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,26 +100,14 @@ class ConfigSerializer(serializers.ModelSerializer):
100100
app = serializers.SlugRelatedField(slug_field='id')
101101
values = serializers.ModelField(
102102
model_field=models.Config()._meta.get_field('values'), required=False)
103-
104-
class Meta:
105-
"""Metadata options for a :class:`ConfigSerializer`."""
106-
model = models.Config
107-
read_only_fields = ('uuid', 'created', 'updated')
108-
109-
110-
class LimitSerializer(serializers.ModelSerializer):
111-
"""Serialize a :class:`~api.models.Limit` model."""
112-
113-
owner = serializers.Field(source='owner.username')
114-
app = serializers.SlugRelatedField(slug_field='id')
115103
memory = serializers.ModelField(
116-
model_field=models.Limit()._meta.get_field('memory'), required=False)
104+
model_field=models.Config()._meta.get_field('memory'), required=False)
117105
cpu = serializers.ModelField(
118-
model_field=models.Limit()._meta.get_field('cpu'), required=False)
106+
model_field=models.Config()._meta.get_field('cpu'), required=False)
119107

120108
class Meta:
121-
"""Metadata options for a :class:`LimitSerializer`."""
122-
model = models.Limit
109+
"""Metadata options for a :class:`ConfigSerializer`."""
110+
model = models.Config
123111
read_only_fields = ('uuid', 'created', 'updated')
124112

125113
def validate_memory(self, attrs, source):

0 commit comments

Comments
 (0)