Skip to content

Commit 0c89448

Browse files
author
Gabriel Monroy
committed
first pass at layer refactoring, with passing test suite
1 parent 50df654 commit 0c89448

12 files changed

Lines changed: 333 additions & 468 deletions

File tree

api/models.py

Lines changed: 101 additions & 185 deletions
Large diffs are not rendered by default.

api/serializers.py

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ class FormationSerializer(serializers.ModelSerializer):
120120
owner = serializers.Field(source='owner.username')
121121
id = serializers.SlugField(default=utils.generate_app_name)
122122
flavor = serializers.SlugRelatedField(slug_field='id')
123-
structure = serializers.ModelField(
124-
model_field=models.Formation()._meta.get_field('structure'), required=False)
123+
containers = serializers.ModelField(
124+
model_field=models.Formation()._meta.get_field('containers'), required=False)
125125

126126
class Meta:
127127
"""Metadata options for a FormationSerializer."""
@@ -138,44 +138,31 @@ def data(self):
138138
return d
139139

140140

141-
class NodeSerializer(serializers.ModelSerializer):
142-
143-
"""Serializes a Node model."""
144-
145-
owner = serializers.Field(source='owner.username')
146-
formation = serializers.SlugRelatedField(slug_field='id')
147-
148-
class Meta:
149-
"""Metadata options for a NodeSerializer."""
150-
model = models.Node
151-
read_only_fields = ('created', 'updated')
152-
153-
154-
class BackendSerializer(serializers.ModelSerializer):
141+
class LayerSerializer(serializers.ModelSerializer):
155142

156-
"""Serializes a Backend model."""
143+
"""Serializes a Layer model."""
157144

158145
owner = serializers.Field(source='owner.username')
159146
formation = serializers.SlugRelatedField(slug_field='id')
160-
node = serializers.SlugRelatedField(slug_field='uuid')
147+
flavor = serializers.SlugRelatedField(slug_field='id')
161148

162149
class Meta:
163-
"""Metadata options for a BackendSerializer."""
164-
model = models.Backend
150+
"""Metadata options for a LayerSerializer."""
151+
model = models.Layer
165152
read_only_fields = ('created', 'updated')
166153

167154

168-
class ProxySerializer(serializers.ModelSerializer):
169-
170-
"""Serializes a Proxy model."""
171-
155+
class NodeSerializer(serializers.ModelSerializer):
156+
157+
"""Serializes a Node model."""
158+
172159
owner = serializers.Field(source='owner.username')
173160
formation = serializers.SlugRelatedField(slug_field='id')
174-
node = serializers.SlugRelatedField(slug_field='uuid')
161+
layer = serializers.SlugRelatedField(slug_field='id')
175162

176163
class Meta:
177-
"""Metadata options for a ProxySerializer."""
178-
model = models.Proxy
164+
"""Metadata options for a NodeSerializer."""
165+
model = models.Node
179166
read_only_fields = ('created', 'updated')
180167

181168

api/tests/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ def send_patch(self, path, data='', content_type='application/octet-stream',
2828
Client.patch = send_patch
2929

3030
from .auth import *
31-
from .backend import *
3231
from .build import *
3332
from .config import *
3433
from .container import *
3534
from .flavor import *
3635
from .formation import *
36+
from .key import *
37+
from .layer import *
3738
from .node import *
3839
from .provider import *
39-
from .proxy import *
4040
from .release import *

api/tests/backend.py

Lines changed: 0 additions & 70 deletions
This file was deleted.

api/tests/container.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ def setUp(self):
3636

3737
def test_container_scale(self):
3838
url = '/api/formations'
39-
body = {'id': 'autotest', 'flavor': 'autotest', 'image': 'deis/autotest'}
39+
body = {'id': 'autotest', 'flavor': 'autotest'}
4040
response = self.client.post(url, json.dumps(body), content_type='application/json')
4141
self.assertEqual(response.status_code, 201)
4242
formation_id = response.data['id']
43-
# scale backends
44-
url = '/api/formations/{formation_id}/backends'.format(**locals())
45-
response = self.client.get(url)
46-
self.assertEqual(response.status_code, 200)
47-
self.assertEqual(len(response.data['results']), 0)
48-
url = '/api/formations/{formation_id}/scale'.format(**locals())
49-
body = {'backends': 4}
43+
url = '/api/formations/{formation_id}/layers'.format(**locals())
44+
body = {'id': 'runtime', 'run_list': 'recipe[deis::runtime]'}
45+
response = self.client.post(url, json.dumps(body), content_type='application/json')
46+
self.assertEqual(response.status_code, 201)
47+
# scale runtime layer up
48+
url = '/api/formations/{formation_id}/scale/layers'.format(**locals())
49+
body = {'runtime': 4}
5050
response = self.client.post(url, json.dumps(body), content_type='application/json')
5151
self.assertEqual(response.status_code, 200)
52-
url = '/api/formations/{formation_id}/backends'.format(**locals())
52+
url = '/api/formations/{formation_id}/nodes'.format(**locals())
5353
response = self.client.get(url)
5454
self.assertEqual(response.status_code, 200)
5555
self.assertEqual(len(response.data['results']), 4)
@@ -59,7 +59,7 @@ def test_container_scale(self):
5959
self.assertEqual(response.status_code, 200)
6060
self.assertEqual(len(response.data['results']), 0)
6161
# scale up
62-
url = '/api/formations/{formation_id}/scale'.format(**locals())
62+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
6363
body = {'web': 4, 'worker': 2}
6464
response = self.client.post(url, json.dumps(body), content_type='application/json')
6565
self.assertEqual(response.status_code, 200)
@@ -68,15 +68,15 @@ def test_container_scale(self):
6868
self.assertEqual(response.status_code, 200)
6969
self.assertEqual(len(response.data['results']), 6)
7070
# scale down
71-
url = '/api/formations/{formation_id}/scale'.format(**locals())
71+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
7272
body = {'web': 2, 'worker': 1}
7373
response = self.client.post(url, json.dumps(body), content_type='application/json')
7474
url = '/api/formations/{formation_id}/containers'.format(**locals())
7575
response = self.client.get(url)
7676
self.assertEqual(response.status_code, 200)
7777
self.assertEqual(len(response.data['results']), 3)
7878
# scale down to 0
79-
url = '/api/formations/{formation_id}/scale'.format(**locals())
79+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
8080
body = {'web': 0, 'worker': 0}
8181
response = self.client.post(url, json.dumps(body), content_type='application/json')
8282
self.assertEqual(response.status_code, 200)
@@ -87,17 +87,17 @@ def test_container_scale(self):
8787

8888
def test_container_balance(self):
8989
url = '/api/formations'
90-
body = {'id': 'autotest', 'flavor': 'autotest', 'image': 'deis/autotest'}
90+
body = {'id': 'autotest', 'flavor': 'autotest'}
9191
response = self.client.post(url, json.dumps(body), content_type='application/json')
9292
self.assertEqual(response.status_code, 201)
9393
formation_id = response.data['id']
94-
# scale backends
95-
url = '/api/formations/{formation_id}/backends'.format(**locals())
96-
response = self.client.get(url)
97-
self.assertEqual(response.status_code, 200)
98-
self.assertEqual(len(response.data['results']), 0)
99-
url = '/api/formations/{formation_id}/scale'.format(**locals())
100-
body = {'backends': 2}
94+
url = '/api/formations/{formation_id}/layers'.format(**locals())
95+
body = {'id': 'runtime', 'run_list': 'recipe[deis::runtime]'}
96+
response = self.client.post(url, json.dumps(body), content_type='application/json')
97+
self.assertEqual(response.status_code, 201)
98+
# scale layer
99+
url = '/api/formations/{formation_id}/scale/layers'.format(**locals())
100+
body = {'runtime': 2}
101101
response = self.client.post(url, json.dumps(body), content_type='application/json')
102102
self.assertEqual(response.status_code, 200)
103103
# should start with zero
@@ -106,13 +106,13 @@ def test_container_balance(self):
106106
self.assertEqual(response.status_code, 200)
107107
self.assertEqual(len(response.data['results']), 0)
108108
# scale up
109-
url = '/api/formations/{formation_id}/scale'.format(**locals())
109+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
110110
body = {'web': 8, 'worker': 2}
111111
response = self.client.post(url, json.dumps(body), content_type='application/json')
112112
self.assertEqual(response.status_code, 200)
113-
# scale backends
114-
url = '/api/formations/{formation_id}/scale'.format(**locals())
115-
body = {'backends': 4 }
113+
# scale layer up
114+
url = '/api/formations/{formation_id}/scale/layers'.format(**locals())
115+
body = {'runtime': 4}
116116
response = self.client.post(url, json.dumps(body), content_type='application/json')
117117
self.assertEqual(response.status_code, 200)
118118
# calculate the formation
@@ -136,7 +136,7 @@ def test_container_balance(self):
136136
b_max = max([ len(by_backend[b]) for b in by_backend.keys() ])
137137
self.assertLess(b_max - b_min, 2)
138138
# scale up more
139-
url = '/api/formations/{formation_id}/scale'.format(**locals())
139+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
140140
body = {'web': 6, 'worker': 4}
141141
response = self.client.post(url, json.dumps(body), content_type='application/json')
142142
self.assertEqual(response.status_code, 200)
@@ -161,7 +161,7 @@ def test_container_balance(self):
161161
b_max = max([ len(by_backend[b]) for b in by_backend.keys() ])
162162
self.assertLess(b_max - b_min, 2)
163163
# scale down
164-
url = '/api/formations/{formation_id}/scale'.format(**locals())
164+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
165165
body = {'web': 2, 'worker': 2}
166166
response = self.client.post(url, json.dumps(body), content_type='application/json')
167167
self.assertEqual(response.status_code, 200)

api/tests/formation.py

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ def test_formation(self):
4242
self.assertEqual(response.status_code, 201)
4343
formation_id = response.data['id']
4444
self.assertIn('flavor', response.data)
45-
self.assertIn('image', response.data)
46-
self.assertIn('structure', response.data)
45+
self.assertIn('layers', response.data)
46+
self.assertIn('containers', response.data)
4747
response = self.client.get('/api/formations')
4848
self.assertEqual(response.status_code, 200)
4949
self.assertEqual(len(response.data['results']), 1)
@@ -93,36 +93,29 @@ def test_formation_scale_errors(self):
9393
response = self.client.post(url, json.dumps(body), content_type='application/json')
9494
self.assertEqual(response.status_code, 201)
9595
formation_id = response.data['id']
96-
# scaling containers without backends should throw an error
97-
url = '/api/formations/{formation_id}/scale'.format(**locals())
96+
# scaling containers without a runtime layer should throw an error
97+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
9898
body = {'web': 1}
9999
response = self.client.post(url, json.dumps(body), content_type='application/json')
100100
self.assertEqual(response.status_code, 400)
101-
self.assertEqual(json.loads(response.content), 'Must scale backends > 0 to host containers')
101+
self.assertEqual(json.loads(response.content), 'Must create a "runtime" layer to host containers')
102+
# scaling containers without any runtime nodes should throw an error
103+
url = '/api/formations/{formation_id}/layers'.format(**locals())
104+
body = {'id': 'runtime', 'run_list': 'recipe[deis::runtime]'}
105+
response = self.client.post(url, json.dumps(body), content_type='application/json')
106+
self.assertEqual(response.status_code, 201)
107+
url = '/api/formations/{formation_id}/scale/containers'.format(**locals())
108+
body = {'web': 1}
109+
response = self.client.post(url, json.dumps(body), content_type='application/json')
110+
self.assertEqual(response.status_code, 400)
111+
self.assertEqual(json.loads(response.content), 'Must scale runtime nodes > 0 to host containers')
102112

103113
def test_formation_actions(self):
104114
url = '/api/formations'
105115
body = {'id': 'autotest', 'flavor': 'autotest', 'image': 'deis/autotest'}
106116
response = self.client.post(url, json.dumps(body), content_type='application/json')
107117
self.assertEqual(response.status_code, 201)
108118
formation_id = response.data['id']
109-
# scale up
110-
url = '/api/formations/{formation_id}/scale'.format(**locals())
111-
body = {'backends': 4, 'proxies': 2, 'web': 4, 'worker': 2}
112-
response = self.client.post(url, json.dumps(body), content_type='application/json')
113-
self.assertEqual(response.status_code, 200)
114-
url = '/api/formations/{formation_id}/backends'.format(**locals())
115-
response = self.client.get(url)
116-
self.assertEqual(response.status_code, 200)
117-
self.assertEqual(len(response.data['results']), 4)
118-
url = '/api/formations/{formation_id}/proxies'.format(**locals())
119-
response = self.client.get(url)
120-
self.assertEqual(response.status_code, 200)
121-
self.assertEqual(len(response.data['results']), 2)
122-
url = '/api/formations/{formation_id}/containers'.format(**locals())
123-
response = self.client.get(url)
124-
self.assertEqual(response.status_code, 200)
125-
self.assertEqual(len(response.data['results']), 6)
126119
# test calculate
127120
url = '/api/formations/{formation_id}/calculate'.format(**locals())
128121
response = self.client.post(url)

0 commit comments

Comments
 (0)