Skip to content

Commit 22ce331

Browse files
author
Matthew Fisher
committed
Merge pull request #745 from opdemand/better-scheduling-tests
Better scheduling tests
2 parents ef0bd6c + 33eee91 commit 22ce331

4 files changed

Lines changed: 95 additions & 5 deletions

File tree

controller/api/admin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ class ContainerAdmin(admin.ModelAdmin):
6363
in the Django admin.
6464
"""
6565
date_hierarchy = 'created'
66-
list_display = ('short_name', 'owner', 'cluster', 'app', 'state')
67-
list_filter = ('owner', 'cluster', 'app', 'state')
66+
list_display = ('short_name', 'owner', 'app', 'state')
67+
list_filter = ('owner', 'app', 'state')
6868
admin.site.register(Container, ContainerAdmin)
6969

7070

controller/api/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ class Cluster(UuidAuditedModel):
6363
"""
6464

6565
CLUSTER_TYPES = (('mock', 'Mock Cluster'),
66-
('coreos', 'CoreOS Cluster'))
66+
('coreos', 'CoreOS Cluster'),
67+
('faulty', 'Faulty Cluster'))
6768

6869
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
6970
id = models.CharField(max_length=128, unique=True)
70-
type = models.CharField(max_length=16, choices=CLUSTER_TYPES)
71+
type = models.CharField(max_length=16, choices=CLUSTER_TYPES, default='coreos')
7172

7273
domain = models.CharField(max_length=128)
7374
hosts = models.CharField(max_length=256)

controller/api/tests/test_container.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from django.test import TransactionTestCase
1313
from django.test.utils import override_settings
1414

15+
from django_fsm import TransitionNotAllowed
16+
1517
from api.models import Container, App
1618

1719

@@ -30,8 +32,15 @@ def setUp(self):
3032
response = self.client.post('/api/clusters', json.dumps(body),
3133
content_type='application/json')
3234
self.assertEqual(response.status_code, 201)
35+
# create a malicious scheduler as well
36+
body['id'] = 'autotest2'
37+
body['type'] = 'faulty'
38+
response = self.client.post('/api/clusters', json.dumps(body),
39+
content_type='application/json')
40+
self.assertEqual(response.status_code, 201)
3341

34-
def test_container(self):
42+
def test_container_state_good(self):
43+
"""Test that the finite state machine transitions with a good scheduler"""
3544
url = '/api/apps'
3645
body = {'cluster': 'autotest'}
3746
response = self.client.post(url, json.dumps(body), content_type='application/json')
@@ -44,13 +53,62 @@ def test_container(self):
4453
type='web',
4554
num=1)
4655
self.assertEqual(c.state, 'initialized')
56+
# test an illegal transition
57+
self.assertRaises(TransitionNotAllowed, lambda: c.start())
4758
c.create()
4859
self.assertEqual(c.state, 'created')
4960
c.start()
5061
self.assertEqual(c.state, 'up')
62+
c.deploy(App.objects.get(id=app_id).release_set.latest())
63+
self.assertEqual(c.state, 'up')
5164
c.destroy()
5265
self.assertEqual(c.state, 'destroyed')
5366

67+
def test_container_state_bad(self):
68+
"""Test that the finite state machine transitions with a faulty scheduler"""
69+
url = '/api/apps'
70+
body = {'cluster': 'autotest2'}
71+
response = self.client.post(url, json.dumps(body), content_type='application/json')
72+
self.assertEqual(response.status_code, 201)
73+
app_id = response.data['id']
74+
# create a container
75+
c = Container.objects.create(owner=User.objects.get(username='autotest'),
76+
app=App.objects.get(id=app_id),
77+
release=App.objects.get(id=app_id).release_set.latest(),
78+
type='web',
79+
num=1)
80+
self.assertEqual(c.state, 'initialized')
81+
self.assertRaises(Exception, lambda: c.create())
82+
self.assertEqual(c.state, 'initialized')
83+
# test an illegal transition
84+
self.assertRaises(TransitionNotAllowed, lambda: c.start())
85+
self.assertEqual(c.state, 'initialized')
86+
self.assertRaises(
87+
Exception,
88+
lambda: c.deploy(
89+
App.objects.get(id=app_id).release_set.latest()
90+
)
91+
)
92+
self.assertEqual(c.state, 'down')
93+
self.assertRaises(Exception, lambda: c.destroy())
94+
self.assertEqual(c.state, 'down')
95+
self.assertRaises(Exception, lambda: c.run('echo hello world'))
96+
self.assertEqual(c.state, 'down')
97+
98+
def test_container_state_protected(self):
99+
"""Test that you cannot directly modify the state"""
100+
url = '/api/apps'
101+
body = {'cluster': 'autotest'}
102+
response = self.client.post(url, json.dumps(body), content_type='application/json')
103+
self.assertEqual(response.status_code, 201)
104+
app_id = response.data['id']
105+
c = Container.objects.create(owner=User.objects.get(username='autotest'),
106+
app=App.objects.get(id=app_id),
107+
release=App.objects.get(id=app_id).release_set.latest(),
108+
type='web',
109+
num=1)
110+
self.assertRaises(AttributeError, lambda: setattr(c, 'state', 'up'))
111+
54112
def test_container_api(self):
55113
url = '/api/apps'
56114
body = {'cluster': 'autotest'}

controller/scheduler/faulty.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class FaultyClient(object):
2+
"""A faulty scheduler that will always fail"""
3+
4+
def __init__(self, cluster_name, hosts, auth, domain, options):
5+
pass
6+
7+
def setUp(self):
8+
pass
9+
10+
def tearDown(self):
11+
pass
12+
13+
def create(self, name, image, command='', template=None, port=5000):
14+
raise Exception()
15+
16+
def start(self, name):
17+
raise Exception()
18+
19+
def stop(self, name):
20+
raise Exception()
21+
22+
def destroy(self, name):
23+
raise Exception()
24+
25+
def run(self, name, image, command):
26+
raise Exception()
27+
28+
def attach(self, name):
29+
raise Exception()
30+
31+
SchedulerClient = FaultyClient

0 commit comments

Comments
 (0)