Skip to content

Commit f856c67

Browse files
committed
Fixed #167 -- allow underscore in slug-type field regexes.
1 parent 09e6d34 commit f856c67

3 files changed

Lines changed: 35 additions & 30 deletions

File tree

api/tests/flavor.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""
23
Unit tests for the Deis api app.
34
@@ -31,7 +32,9 @@ def test_flavor(self):
3132
Test that a user can create, read, update and delete a node flavor
3233
"""
3334
url = '/api/flavors'
34-
body = {'id': 'autotest', 'provider': 'autotest',
35+
# Ensure that dashes and underscores are allowed in id, per Django's
36+
# definition of a SlugField.
37+
body = {'id': 'auto_test-1', 'provider': 'autotest',
3538
'params': json.dumps({'region': 'us-west-2', 'instance_size': 'm1.medium'})}
3639
response = self.client.post(url, json.dumps(body), content_type='application/json')
3740
self.assertEqual(response.status_code, 201)
@@ -59,7 +62,7 @@ def test_flavor_update(self):
5962
'zone': 'any',
6063
'image': 'i-1234567'
6164
}
62-
body = {'id': 'autotest', 'provider': 'autotest', 'params': json.dumps(params)}
65+
body = {'id': 'auto_test', 'provider': 'autotest', 'params': json.dumps(params)}
6366
response = self.client.post(url, json.dumps(body), content_type='application/json')
6467
self.assertEqual(response.status_code, 201)
6568
flavor_id = response.data['id']

api/tests/formation.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_formation(self):
4040
Test that a user can create, read, update and delete a node formation
4141
"""
4242
url = '/api/formations'
43-
body = {'id': 'autotest', 'domain': 'localhost.localdomain'}
43+
body = {'id': 'auto_test-1', 'domain': 'localhost.localdomain'}
4444
response = self.client.post(url, json.dumps(body), content_type='application/json')
4545
self.assertEqual(response.status_code, 201)
4646
formation_id = response.data['id'] # noqa
@@ -78,7 +78,9 @@ def test_formation_cm(self):
7878
self.assertFalse(os.path.exists(path))
7979

8080
def test_formation_id(self):
81-
body = {'id': 'autotest', 'domain': 'localhost.localdomain'}
81+
# Ensure that dashes and underscores are allowed in id, per Django's
82+
# definition of a SlugField.
83+
body = {'id': 'auto_test-1', 'domain': 'localhost.localdomain'}
8284
response = self.client.post('/api/formations', json.dumps(body),
8385
content_type='application/json')
8486
self.assertEqual(response.status_code, 201)

api/urls.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -323,79 +323,79 @@
323323
url(r'^keys/?',
324324
views.KeyViewSet.as_view({'get': 'list', 'post': 'create'})),
325325
# provider
326-
url(r'^providers/(?P<id>[a-z0-9-]+)/?',
326+
url(r'^providers/(?P<id>[-_\w]+)/?',
327327
views.ProviderViewSet.as_view({
328328
'get': 'retrieve', 'patch': 'partial_update', 'delete': 'destroy'})),
329329
url(r'^providers/?',
330330
views.ProviderViewSet.as_view({'get': 'list', 'post': 'create'})),
331331
# flavor
332-
url(r'^flavors/(?P<id>[a-z0-9-]+)/?',
332+
url(r'^flavors/(?P<id>[-_\w]+)/?',
333333
views.FlavorViewSet.as_view({
334334
'get': 'retrieve', 'patch': 'partial_update', 'delete': 'destroy'})),
335335
url(r'^flavors/?',
336336
views.FlavorViewSet.as_view({'get': 'list', 'post': 'create'})),
337337
# formation infrastructure
338-
url(r'^formations/(?P<id>[a-z0-9-]+)/layers/(?P<layer>[a-z0-9-]+)/?',
338+
url(r'^formations/(?P<id>[-_\w]+)/layers/(?P<layer>[-_\w]+)/?',
339339
views.FormationLayerViewSet.as_view({
340340
'get': 'retrieve', 'patch': 'partial_update', 'delete': 'destroy'})),
341-
url(r'^formations/(?P<id>[a-z0-9-]+)/layers/?',
341+
url(r'^formations/(?P<id>[-_\w]+)/layers/?',
342342
views.FormationLayerViewSet.as_view({'get': 'list', 'post': 'create'})),
343-
url(r'^formations/(?P<id>[a-z0-9-]+)/nodes/(?P<node>[a-z0-9-]+)/?',
343+
url(r'^formations/(?P<id>[-_\w]+)/nodes/(?P<node>[-_\w]+)/?',
344344
views.FormationNodeViewSet.as_view({
345345
'get': 'retrieve', 'delete': 'destroy'})),
346-
url(r'^formations/(?P<id>[a-z0-9-]+)/nodes/?',
346+
url(r'^formations/(?P<id>[-_\w]+)/nodes/?',
347347
views.FormationNodeViewSet.as_view({'get': 'list'})),
348348
# formation actions
349-
url(r'^formations/(?P<id>[a-z0-9-]+)/scale/?',
349+
url(r'^formations/(?P<id>[-_\w]+)/scale/?',
350350
views.FormationViewSet.as_view({'post': 'scale'})),
351-
url(r'^formations/(?P<id>[a-z0-9-]+)/balance/?',
351+
url(r'^formations/(?P<id>[-_\w]+)/balance/?',
352352
views.FormationViewSet.as_view({'post': 'balance'})),
353-
url(r'^formations/(?P<id>[a-z0-9-]+)/calculate/?',
353+
url(r'^formations/(?P<id>[-_\w]+)/calculate/?',
354354
views.FormationViewSet.as_view({'post': 'calculate'})),
355-
url(r'^formations/(?P<id>[a-z0-9-]+)/converge/?',
355+
url(r'^formations/(?P<id>[-_\w]+)/converge/?',
356356
views.FormationViewSet.as_view({'post': 'converge'})),
357357
# formation base endpoint
358-
url(r'^formations/(?P<id>[a-z0-9-]+)/?',
358+
url(r'^formations/(?P<id>[-_\w]+)/?',
359359
views.FormationViewSet.as_view({
360360
'get': 'retrieve', 'patch': 'partial_update', 'delete': 'destroy'})),
361361
url(r'^formations/?',
362362
views.FormationViewSet.as_view({'get': 'list', 'post': 'create'})),
363363
# application release components
364-
url(r'^apps/(?P<id>[a-z0-9-]+)/config/?',
364+
url(r'^apps/(?P<id>[-_\w]+)/config/?',
365365
views.AppConfigViewSet.as_view({'get': 'retrieve', 'post': 'create'})),
366-
url(r'^apps/(?P<id>[a-z0-9-]+)/builds/(?P<uuid>[a-z0-9-]+)/?',
366+
url(r'^apps/(?P<id>[-_\w]+)/builds/(?P<uuid>[-_\w]+)/?',
367367
views.AppBuildViewSet.as_view({'get': 'retrieve'})),
368-
url(r'^apps/(?P<id>[a-z0-9-]+)/builds/?',
368+
url(r'^apps/(?P<id>[-_\w]+)/builds/?',
369369
views.AppBuildViewSet.as_view({'get': 'list', 'post': 'create'})),
370-
url(r'^apps/(?P<id>[a-z0-9-]+)/releases/(?P<version>[0-9]+)/?',
370+
url(r'^apps/(?P<id>[-_\w]+)/releases/(?P<version>[0-9]+)/?',
371371
views.AppReleaseViewSet.as_view({'get': 'retrieve'})),
372-
url(r'^apps/(?P<id>[a-z0-9-]+)/releases/?',
372+
url(r'^apps/(?P<id>[-_\w]+)/releases/?',
373373
views.AppReleaseViewSet.as_view({'get': 'list'})),
374374
# application infrastructure
375-
url(r'^apps/(?P<id>[a-z0-9-]+)/containers/(?P<type>[a-z0-9-]+)/(?P<num>[a-z0-9-]+)/?',
375+
url(r'^apps/(?P<id>[-_\w]+)/containers/(?P<type>[-_\w]+)/(?P<num>[-_\w]+)/?',
376376
views.AppContainerViewSet.as_view({'get': 'retrieve'})),
377-
url(r'^apps/(?P<id>[a-z0-9-]+)/containers/(?P<type>[a-z0-9-.]+)/?',
377+
url(r'^apps/(?P<id>[-_\w]+)/containers/(?P<type>[-_\w.]+)/?',
378378
views.AppContainerViewSet.as_view({'get': 'list'})),
379-
url(r'^apps/(?P<id>[a-z0-9-]+)/containers/?',
379+
url(r'^apps/(?P<id>[-_\w]+)/containers/?',
380380
views.AppContainerViewSet.as_view({'get': 'list'})),
381381
# application actions
382-
url(r'^apps/(?P<id>[a-z0-9-]+)/scale/?',
382+
url(r'^apps/(?P<id>[-_\w]+)/scale/?',
383383
views.AppViewSet.as_view({'post': 'scale'})),
384-
url(r'^apps/(?P<id>[a-z0-9-]+)/logs/?',
384+
url(r'^apps/(?P<id>[-_\w]+)/logs/?',
385385
views.AppViewSet.as_view({'post': 'logs'})),
386-
url(r'^apps/(?P<id>[a-z0-9-]+)/run/?',
386+
url(r'^apps/(?P<id>[-_\w]+)/run/?',
387387
views.AppViewSet.as_view({'post': 'run'})),
388-
url(r'^apps/(?P<id>[a-z0-9-]+)/calculate/?',
388+
url(r'^apps/(?P<id>[-_\w]+)/calculate/?',
389389
views.AppViewSet.as_view({'post': 'calculate'})),
390390
# apps base endpoint
391-
url(r'^apps/(?P<id>[a-z0-9-]+)/?',
391+
url(r'^apps/(?P<id>[-_\w]+)/?',
392392
views.AppViewSet.as_view({'get': 'retrieve', 'delete': 'destroy'})),
393393
url(r'^apps/?',
394394
views.AppViewSet.as_view({'get': 'list', 'post': 'create'})),
395395
# nodes
396-
url(r'^nodes/(?P<node>[a-z0-9-]+)/converge/?',
396+
url(r'^nodes/(?P<node>[-_\w]+)/converge/?',
397397
views.NodeViewSet.as_view({'post': 'converge'})),
398-
url(r'^nodes/(?P<node>[a-z0-9-]+)/?',
398+
url(r'^nodes/(?P<node>[-_\w]+)/?',
399399
views.NodeViewSet.as_view({
400400
'get': 'retrieve', 'delete': 'destroy'})),
401401
url(r'^nodes/?',

0 commit comments

Comments
 (0)