Merge lp:~devcamcar/django-nova/improve_unittests into lp:django-nova

Proposed by Devin Carlen
Status: Merged
Approved by: Devin Carlen
Approved revision: no longer in the source branch.
Merged at revision: 11
Proposed branch: lp:~devcamcar/django-nova/improve_unittests
Merge into: lp:django-nova
Diff against target: 885 lines (+490/-54)
17 files modified
buildout.cfg (+1/-1)
setup.py (+1/-1)
src/django_nova/forms.py (+3/-3)
src/django_nova/manager.py (+11/-1)
src/django_nova/models.py (+5/-0)
src/django_nova/shortcuts.py (+3/-2)
src/django_nova/tests/__init__.py (+1/-0)
src/django_nova/tests/urls.py (+32/-0)
src/django_nova/tests/view_tests/__init__.py (+3/-0)
src/django_nova/tests/view_tests/base.py (+51/-0)
src/django_nova/tests/view_tests/image_tests.py (+210/-0)
src/django_nova/tests/view_tests/instance_tests.py (+45/-0)
src/django_nova/tests/view_tests/keypair_tests.py (+71/-0)
src/django_nova/testsettings.py (+17/-3)
src/django_nova/views/images.py (+20/-27)
src/django_nova/views/instances.py (+11/-11)
src/django_nova/views/keypairs.py (+5/-5)
To merge this branch: bzr merge lp:~devcamcar/django-nova/improve_unittests
Reviewer Review Type Date Requested Status
Devin Carlen Approve
Review via email: mp+47481@code.launchpad.net

Description of the change

Results of refactoring view tests and adding mox. Still in progress but merging in what's there to date.

To post a comment you must log in.
Revision history for this message
Devin Carlen (devcamcar) wrote :

approve

review: Approve
11. By Devin Carlen

Merged lp:~devcamcar/django-nova/improve_unittests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout.cfg'
2--- buildout.cfg 2011-01-12 20:02:06 +0000
3+++ buildout.cfg 2011-01-25 23:54:53 +0000
4@@ -10,7 +10,7 @@
5
6 [django]
7 recipe = djangorecipe
8-version = 1.2.3
9+version = 1.2.4
10 project = django_nova
11 projectegg = django_nova
12 settings = testsettings
13
14=== modified file 'setup.py'
15--- setup.py 2011-01-12 20:02:06 +0000
16+++ setup.py 2011-01-25 23:54:53 +0000
17@@ -15,7 +15,7 @@
18 author_email = 'devin.carlen@gmail.com',
19 packages = find_packages('src'),
20 package_dir = {'': 'src'},
21- install_requires = ['setuptools'],
22+ install_requires = ['setuptools', 'boto==1.9b', 'mox>=0.5.0'],
23 classifiers = [
24 'Development Status :: 4 - Beta',
25 'Framework :: Django',
26
27=== modified file 'src/django_nova/forms.py'
28--- src/django_nova/forms.py 2011-01-16 03:46:33 +0000
29+++ src/django_nova/forms.py 2011-01-25 23:54:53 +0000
30@@ -49,13 +49,13 @@
31
32 def get_instance_choices(project):
33 choices = [(i.id, i.id) for i in project.get_instances()]
34- if len(choices) == 0:
35+ if not len(choices):
36 choices = [('', 'none available')]
37 return choices
38
39 def get_key_pair_choices(project):
40 choices = [(k.name, k.name) for k in project.get_key_pairs()]
41- if len(choices) == 0:
42+ if not len(choices):
43 choices = [('', 'none available')]
44 return choices
45
46@@ -68,7 +68,7 @@
47 def get_available_volume_choices(project):
48 choices = [(v.id, '%s %s - %dGB' % (v.id, v.displayName, v.size)) for v in \
49 project.get_volumes() if v.status != "in-use"]
50- if len(choices) == 0:
51+ if not len(choices):
52 choices = [('', 'none available')]
53 return choices
54
55
56=== modified file 'src/django_nova/manager.py'
57--- src/django_nova/manager.py 2011-01-15 09:27:24 +0000
58+++ src/django_nova/manager.py 2011-01-25 23:54:53 +0000
59@@ -87,6 +87,16 @@
60 return conn.get_object('UpdateImage', params, boto.ec2.image.Image)
61
62 @wrap_nova_error
63+ def modify_image_attribute(self, image_id, attribute=None, operation=None,
64+ groups='all'):
65+ conn = self.get_nova_connection()
66+ return conn.modify_image_attribute(image_id,
67+ attribute='launchPermission',
68+ operation='remove',
69+ groups='all',)
70+
71+
72+ @wrap_nova_error
73 def run_instances(self, image_id, **kwargs):
74 """
75 Runs instances of the specified image id.
76@@ -201,7 +211,7 @@
77 """
78 Indicates whether a security group with the specified name exists in this project.
79 """
80- return self.get_security_group(name) != None
81+ return self.get_security_group(name) is not None
82
83 @wrap_nova_error
84 def create_security_group(self, name, description):
85
86=== modified file 'src/django_nova/models.py'
87--- src/django_nova/models.py 2011-01-12 20:02:06 +0000
88+++ src/django_nova/models.py 2011-01-25 23:54:53 +0000
89@@ -107,6 +107,11 @@
90 """
91 Creates a Nova User when a new Django User is created.
92 """
93+
94+ # NOTE(devcamcar): If running unit tests, don't use a real endpoint.
95+ if settings.NOVA_DEFAULT_ENDPOINT == 'none':
96+ return
97+
98 if created:
99 nova = get_nova_admin_connection()
100 if not nova.has_user(instance.username):
101
102=== modified file 'src/django_nova/shortcuts.py'
103--- src/django_nova/shortcuts.py 2011-01-17 06:58:19 +0000
104+++ src/django_nova/shortcuts.py 2011-01-25 23:54:53 +0000
105@@ -15,6 +15,7 @@
106 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
107 # License for the specific language governing permissions and limitations
108 # under the License.
109+
110 """
111 Helper methods for commonly used operations.
112 """
113@@ -115,13 +116,13 @@
114 user_has_modify_permissions = False
115
116 # checks global roles, if user is a sysadmin they can modify image attribtues.
117- if user_has_modify_permissions == False:
118+ if not user_has_modify_permissions:
119 for role in nova.get_user_roles(username):
120 if role.role == "sysadmin":
121 user_has_modify_permissions = True
122
123 # checks project roles, if user is a sysadmin they can modify image attribtues.
124- if user_has_modify_permissions == False:
125+ if not user_has_modify_permissions:
126 for role in nova.get_user_roles(username, project_name):
127 if role.role == "sysadmin":
128 user_has_modify_permissions = True
129
130=== added directory 'src/django_nova/tests'
131=== added file 'src/django_nova/tests/__init__.py'
132--- src/django_nova/tests/__init__.py 1970-01-01 00:00:00 +0000
133+++ src/django_nova/tests/__init__.py 2011-01-25 23:54:53 +0000
134@@ -0,0 +1,1 @@
135+from view_tests import *
136\ No newline at end of file
137
138=== added directory 'src/django_nova/tests/templates'
139=== added file 'src/django_nova/tests/templates/base-sidebar.html'
140=== added file 'src/django_nova/tests/urls.py'
141--- src/django_nova/tests/urls.py 1970-01-01 00:00:00 +0000
142+++ src/django_nova/tests/urls.py 2011-01-25 23:54:53 +0000
143@@ -0,0 +1,32 @@
144+# vim: tabstop=4 shiftwidth=4 softtabstop=4
145+
146+# Copyright 2010 United States Government as represented by the
147+# Administrator of the National Aeronautics and Space Administration.
148+# All Rights Reserved.
149+#
150+# Licensed under the Apache License, Version 2.0 (the "License"); you may
151+# not use this file except in compliance with the License. You may obtain
152+# a copy of the License at
153+#
154+# http://www.apache.org/licenses/LICENSE-2.0
155+#
156+# Unless required by applicable law or agreed to in writing, software
157+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
158+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
159+# License for the specific language governing permissions and limitations
160+# under the License.
161+
162+"""
163+URL patterns for testing django-nova views.
164+"""
165+
166+from django.conf.urls.defaults import *
167+from django.conf.urls.defaults import *
168+
169+
170+urlpatterns = patterns('',
171+ url(r'^projects/', include('django_nova.urls.project')),
172+ url(r'^region/', include('django_nova.urls.region')),
173+ url(r'^admin/projects/', include('django_nova.urls.admin_project')),
174+ url(r'^admin/roles/', include('django_nova.urls.admin_roles')),
175+)
176\ No newline at end of file
177
178=== added directory 'src/django_nova/tests/view_tests'
179=== added file 'src/django_nova/tests/view_tests/__init__.py'
180--- src/django_nova/tests/view_tests/__init__.py 1970-01-01 00:00:00 +0000
181+++ src/django_nova/tests/view_tests/__init__.py 2011-01-25 23:54:53 +0000
182@@ -0,0 +1,3 @@
183+from keypair_tests import *
184+from image_tests import *
185+from instance_tests import *
186\ No newline at end of file
187
188=== added file 'src/django_nova/tests/view_tests/base.py'
189--- src/django_nova/tests/view_tests/base.py 1970-01-01 00:00:00 +0000
190+++ src/django_nova/tests/view_tests/base.py 2011-01-25 23:54:53 +0000
191@@ -0,0 +1,51 @@
192+import mox
193+
194+from django import test
195+from django.conf import settings
196+from django.contrib.auth import models as auth_models
197+from django_nova import adminclient
198+from django_nova import manager
199+from django_nova import shortcuts
200+
201+
202+TEST_PROJECT = 'test'
203+TEST_USER = 'test'
204+TEST_REGION = 'test'
205+
206+
207+class BaseProjectViewTests(test.TestCase):
208+ def setUp(self):
209+ project = adminclient.ProjectInfo()
210+ project.projectname = TEST_PROJECT
211+ project.projectManagerId = TEST_USER
212+
213+ self.mox = mox.Mox()
214+ self.user = auth_models.User.objects.create_user(TEST_USER,
215+ 'test@test.com',
216+ password='test')
217+ login = self.client.login(username=TEST_USER, password='test')
218+ self.failUnless(login, 'Unable to login')
219+
220+ self.region = adminclient.RegionInfo(name=TEST_REGION,
221+ endpoint='http://test:8773/')
222+ self.project = manager.ProjectManager(self.user.username,
223+ project,
224+ self.region)
225+ self.mox.StubOutWithMock(shortcuts, 'get_project_or_404')
226+ shortcuts.get_project_or_404(mox.IgnoreArg(),
227+ 'test').AndReturn(self.project)
228+
229+ def tearDown(self):
230+ self.mox.UnsetStubs()
231+
232+ def assertRedirectsNoFollow(self, response, expected_url):
233+ self.assertEqual(response._headers['location'],
234+ ('Location', settings.TESTSERVER + expected_url))
235+ self.assertEqual(response.status_code, 302)
236+
237+ def create_key_pair_choices(self, key_names):
238+ return [(k, k) for k in key_names]
239+
240+ def create_instance_type_choices(self):
241+ return [('m1.medium', 'm1.medium'),
242+ ('m1.large', 'm1.large')]
243
244=== added file 'src/django_nova/tests/view_tests/image_tests.py'
245--- src/django_nova/tests/view_tests/image_tests.py 1970-01-01 00:00:00 +0000
246+++ src/django_nova/tests/view_tests/image_tests.py 2011-01-25 23:54:53 +0000
247@@ -0,0 +1,210 @@
248+import boto.ec2.image
249+import boto.ec2.instance
250+import mox
251+
252+from django.core.urlresolvers import reverse
253+from django_nova import forms
254+from django_nova import shortcuts
255+from django_nova.tests.view_tests.base import BaseProjectViewTests, TEST_PROJECT
256+
257+
258+TEST_IMAGE_ID = 'ami_test'
259+TEST_INSTANCE_ID = 'i-abcdefg'
260+TEST_KEY = 'foo'
261+
262+
263+class ImageViewTests(BaseProjectViewTests):
264+ def setUp(self):
265+ self.ami = boto.ec2.image.Image()
266+ self.ami.id = TEST_IMAGE_ID
267+ setattr(self.ami, 'displayName', TEST_IMAGE_ID)
268+ setattr(self.ami, 'description', TEST_IMAGE_ID)
269+ super(ImageViewTests, self).setUp()
270+
271+ def test_index(self):
272+ self.mox.StubOutWithMock(self.project, 'get_images')
273+ self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
274+ self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
275+
276+ self.project.get_images().AndReturn([])
277+ forms.get_key_pair_choices(self.project).AndReturn([])
278+ forms.get_instance_type_choices().AndReturn([])
279+
280+ self.mox.ReplayAll()
281+
282+ res = self.client.get(reverse('nova_images', args=[TEST_PROJECT]))
283+ self.assertEqual(res.status_code, 200)
284+ self.assertTemplateUsed(res, 'django_nova/images/index.html')
285+ self.assertEqual(len(res.context['image_lists']), 3)
286+
287+ self.mox.VerifyAll()
288+
289+ def test_launch_form(self):
290+ self.mox.StubOutWithMock(self.project, 'get_image')
291+ self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
292+ self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
293+
294+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
295+ forms.get_key_pair_choices(self.project).AndReturn([])
296+ forms.get_instance_type_choices().AndReturn([])
297+
298+ self.mox.ReplayAll()
299+
300+ args = [TEST_PROJECT, TEST_IMAGE_ID]
301+ res = self.client.get(reverse('nova_images_launch', args=args))
302+ self.assertEqual(res.status_code, 200)
303+ self.assertTemplateUsed(res, 'django_nova/images/launch.html')
304+ self.assertEqual(res.context['ami'].id, TEST_IMAGE_ID)
305+
306+ self.mox.VerifyAll()
307+
308+ def test_launch(self):
309+ instance = boto.ec2.instance.Instance()
310+ instance.id = TEST_INSTANCE_ID
311+ instance.image_id = TEST_IMAGE_ID
312+ reservation = boto.ec2.instance.Reservation()
313+ reservation.instances = [instance]
314+
315+ self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
316+ self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
317+ self.mox.StubOutWithMock(self.project, 'run_instances')
318+
319+ forms.get_key_pair_choices(self.project).AndReturn(
320+ self.create_key_pair_choices([TEST_KEY]))
321+ forms.get_instance_type_choices().AndReturn(
322+ self.create_instance_type_choices())
323+ self.project.run_instances(TEST_IMAGE_ID,
324+ addressing_type=mox.IgnoreArg(),
325+ key_name=TEST_KEY,
326+ user_data='',
327+ instance_type='m1.medium',
328+ min_count='1',
329+ max_count='1').AndReturn(reservation)
330+ self.mox.ReplayAll()
331+
332+ url = reverse('nova_images_launch', args=[TEST_PROJECT, TEST_IMAGE_ID])
333+ data = {'key_name': TEST_KEY,
334+ 'count': '1',
335+ 'size': 'm1.medium',
336+ 'user_data': ''}
337+ res = self.client.post(url, data)
338+ self.assertRedirectsNoFollow(res, reverse('nova_instances',
339+ args=[TEST_PROJECT]))
340+ self.mox.VerifyAll()
341+
342+ def test_detail(self):
343+ self.mox.StubOutWithMock(self.project, 'get_images')
344+ self.mox.StubOutWithMock(self.project, 'get_image')
345+ self.mox.StubOutWithMock(shortcuts, 'get_user_image_permissions')
346+ self.mox.StubOutWithMock(forms, 'get_key_pair_choices')
347+ self.mox.StubOutWithMock(forms, 'get_instance_type_choices')
348+
349+ self.project.get_images().AndReturn([self.ami])
350+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
351+ shortcuts.get_user_image_permissions(mox.IgnoreArg(),
352+ TEST_PROJECT).AndReturn(True)
353+ forms.get_key_pair_choices(self.project).AndReturn(
354+ self.create_key_pair_choices([TEST_KEY]))
355+ forms.get_instance_type_choices().AndReturn(
356+ self.create_instance_type_choices())
357+
358+ self.mox.ReplayAll()
359+
360+ res = self.client.get(reverse('nova_images_detail',
361+ args=[TEST_PROJECT, TEST_IMAGE_ID]))
362+ self.assertEqual(res.status_code, 200)
363+ self.assertTemplateUsed(res, 'django_nova/images/index.html')
364+ self.assertEqual(res.context['ami'].id, TEST_IMAGE_ID)
365+
366+ self.mox.VerifyAll()
367+
368+ def test_remove_form(self):
369+ self.mox.StubOutWithMock(self.project, 'get_image')
370+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
371+ self.mox.ReplayAll()
372+
373+ res = self.client.get(reverse('nova_images_remove',
374+ args=[TEST_PROJECT, TEST_IMAGE_ID]))
375+ self.assertEqual(res.status_code, 200)
376+ self.assertTemplateUsed(res, 'django_nova/images/detail_list.html')
377+ self.assertEqual(res.context['ami'].id, TEST_IMAGE_ID)
378+
379+ self.mox.VerifyAll()
380+
381+ def test_remove(self):
382+ self.mox.StubOutWithMock(self.project, 'deregister_image')
383+ self.project.deregister_image(TEST_IMAGE_ID).AndReturn(True)
384+ self.mox.ReplayAll()
385+
386+ res = self.client.post(reverse('nova_images_remove',
387+ args=[TEST_PROJECT, TEST_IMAGE_ID]))
388+ self.assertRedirectsNoFollow(res, reverse('nova_images',
389+ args=[TEST_PROJECT]))
390+
391+ self.mox.VerifyAll()
392+
393+ def test_make_public(self):
394+ self.mox.StubOutWithMock(self.project, 'get_image')
395+ self.mox.StubOutWithMock(self.project, 'modify_image_attribute')
396+
397+ self.ami.is_public = False
398+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
399+ self.project.modify_image_attribute(TEST_IMAGE_ID,
400+ attribute='launchPermission',
401+ operation='add').AndReturn(True)
402+ self.mox.ReplayAll()
403+
404+ res = self.client.post(reverse('nova_images_privacy',
405+ args=[TEST_PROJECT, TEST_IMAGE_ID]))
406+ self.assertRedirectsNoFollow(res, reverse('nova_images_detail',
407+ args=[TEST_PROJECT, TEST_IMAGE_ID]))
408+ self.mox.VerifyAll()
409+
410+ def test_make_private(self):
411+ self.mox.StubOutWithMock(self.project, 'get_image')
412+ self.mox.StubOutWithMock(self.project, 'modify_image_attribute')
413+
414+ self.ami.is_public = True
415+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
416+ self.project.modify_image_attribute(TEST_IMAGE_ID,
417+ attribute='launchPermission',
418+ operation='remove').AndReturn(True)
419+ self.mox.ReplayAll()
420+
421+ args = [TEST_PROJECT, TEST_IMAGE_ID]
422+ res = self.client.post(reverse('nova_images_privacy', args=args))
423+ self.assertRedirectsNoFollow(res, reverse('nova_images_detail',
424+ args=args))
425+ self.mox.VerifyAll()
426+
427+ def test_update_form(self):
428+ self.mox.StubOutWithMock(self.project, 'get_image')
429+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
430+ self.mox.ReplayAll()
431+
432+ args = [TEST_PROJECT, TEST_IMAGE_ID]
433+ res = self.client.get(reverse('nova_images_update', args=args))
434+ self.assertEqual(res.status_code, 200)
435+ self.assertTemplateUsed(res, 'django_nova/images/edit.html')
436+ self.assertEqual(res.context['ami'].id, TEST_IMAGE_ID)
437+
438+ self.mox.VerifyAll()
439+
440+ def test_update(self):
441+ self.mox.StubOutWithMock(self.project, 'get_image')
442+ self.mox.StubOutWithMock(self.project, 'update_image')
443+
444+ self.project.get_image(TEST_IMAGE_ID).AndReturn(self.ami)
445+ self.project.update_image(TEST_IMAGE_ID, 'test', 'test').AndReturn(True)
446+
447+ self.mox.ReplayAll()
448+
449+ args = [TEST_PROJECT, TEST_IMAGE_ID]
450+ data = {'nickname': 'test',
451+ 'description': 'test'}
452+ url = reverse('nova_images_update', args=args)
453+ res = self.client.post(url, data)
454+ expected_url = reverse('nova_images_detail', args=args)
455+ self.assertRedirectsNoFollow(res, expected_url)
456+
457+ self.mox.VerifyAll()
458
459=== added file 'src/django_nova/tests/view_tests/instance_tests.py'
460--- src/django_nova/tests/view_tests/instance_tests.py 1970-01-01 00:00:00 +0000
461+++ src/django_nova/tests/view_tests/instance_tests.py 2011-01-25 23:54:53 +0000
462@@ -0,0 +1,45 @@
463+import boto.ec2.instance
464+import mox
465+
466+from django.core.urlresolvers import reverse
467+from django_nova.tests.view_tests.base import BaseProjectViewTests, TEST_PROJECT
468+
469+
470+TEST_INSTANCE_ID = 'i-abcdefgh'
471+
472+
473+class InstanceViewTests(BaseProjectViewTests):
474+ def test_index(self):
475+ self.mox.StubOutWithMock(self.project, 'get_instances')
476+ self.project.get_instances().AndReturn([])
477+
478+ self.mox.ReplayAll()
479+
480+ res = self.client.get(reverse('nova_instances', args=[TEST_PROJECT]))
481+ self.assertEqual(res.status_code, 200)
482+ self.assertTemplateUsed(res, 'django_nova/instances/index.html')
483+ self.assertEqual(len(res.context['instances']), 0)
484+
485+ self.mox.VerifyAll()
486+
487+ def test_detail(self):
488+ instance = boto.ec2.instance.Instance()
489+ instance.id = TEST_INSTANCE_ID
490+ instance.displayName = instance.id
491+ instance.displayDescription = instance.id
492+
493+ self.mox.StubOutWithMock(self.project, 'get_instance')
494+ self.project.get_instance(instance.id).AndReturn(instance)
495+ self.mox.StubOutWithMock(self.project, 'get_instances')
496+ self.project.get_instances().AndReturn([instance])
497+
498+ self.mox.ReplayAll()
499+
500+ res = self.client.get(reverse('nova_instances_detail',
501+ args=[TEST_PROJECT, TEST_INSTANCE_ID]))
502+ self.assertEqual(res.status_code, 200)
503+ self.assertTemplateUsed(res, 'django_nova/instances/index.html')
504+ self.assertEqual(res.context['selected_instance'].id, instance.id)
505+
506+ self.mox.VerifyAll()
507+
508
509=== added file 'src/django_nova/tests/view_tests/keypair_tests.py'
510--- src/django_nova/tests/view_tests/keypair_tests.py 1970-01-01 00:00:00 +0000
511+++ src/django_nova/tests/view_tests/keypair_tests.py 2011-01-25 23:54:53 +0000
512@@ -0,0 +1,71 @@
513+import boto.ec2.keypair
514+import mox
515+
516+from django.core.urlresolvers import reverse
517+from django_nova.tests.view_tests.base import BaseProjectViewTests, TEST_PROJECT
518+
519+
520+TEST_KEY = 'test_key'
521+
522+
523+class KeyPairViewTests(BaseProjectViewTests):
524+ def test_index(self):
525+ self.mox.StubOutWithMock(self.project, 'get_key_pairs')
526+ self.project.get_key_pairs().AndReturn([])
527+
528+ self.mox.ReplayAll()
529+
530+ response = self.client.get(reverse('nova_keypairs',
531+ args=[TEST_PROJECT]))
532+ self.assertEqual(response.status_code, 200)
533+ self.assertTemplateUsed(response, 'django_nova/keypairs/index.html')
534+ self.assertEqual(len(response.context['keypairs']), 0)
535+
536+ self.mox.VerifyAll()
537+
538+ def test_add_keypair(self):
539+ key = boto.ec2.keypair.KeyPair()
540+ key.name = TEST_KEY
541+
542+ self.mox.StubOutWithMock(self.project, 'create_key_pair')
543+ self.project.create_key_pair(key.name).AndReturn(key)
544+ self.mox.StubOutWithMock(self.project, 'has_key_pair')
545+ self.project.has_key_pair(key.name).AndReturn(False)
546+
547+ self.mox.ReplayAll()
548+
549+ url = reverse('nova_keypairs_add', args=[TEST_PROJECT])
550+ data = {'js': '0', 'name': key.name}
551+ res = self.client.post(url,
552+ data)
553+ self.assertEqual(res.status_code, 200)
554+ self.assertEqual(res['Content-Type'], 'application/binary')
555+
556+ self.mox.VerifyAll()
557+
558+ def test_delete_keypair(self):
559+ self.mox.StubOutWithMock(self.project, 'delete_key_pair')
560+ self.project.delete_key_pair(TEST_KEY).AndReturn(None)
561+
562+ self.mox.ReplayAll()
563+
564+ data = {'key_name': TEST_KEY}
565+ url = reverse('nova_keypairs_delete', args=[TEST_PROJECT])
566+ res = self.client.post(url, data)
567+ self.assertRedirectsNoFollow(res, reverse('nova_keypairs',
568+ args=[TEST_PROJECT]))
569+
570+ self.mox.VerifyAll()
571+
572+ def test_download_keypair(self):
573+ material = 'abcdefgh'
574+ session = self.client.session
575+ session['key.%s' % TEST_KEY] = material
576+ session.save()
577+
578+ res = self.client.get(reverse('nova_keypairs_download',
579+ args=['test', TEST_KEY]))
580+ self.assertEqual(res.status_code, 200)
581+ self.assertEqual(res['Content-Type'], 'application/binary')
582+ self.assertContains(res, material)
583+
584
585=== modified file 'src/django_nova/testsettings.py'
586--- src/django_nova/testsettings.py 2011-01-12 20:02:06 +0000
587+++ src/django_nova/testsettings.py 2011-01-25 23:54:53 +0000
588@@ -1,5 +1,19 @@
589+import os
590+
591+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
592+DEBUG = True
593+TESTSERVER = 'http://testserver'
594 DATABASE_ENGINE = 'sqlite3'
595 DATABASE_NAME = '/tmp/django-nova.db'
596-INSTALLED_APPS = ['django_nova']
597-ROOT_URLCONF = ['django_nova.urls']
598-
599+INSTALLED_APPS = ['django.contrib.auth',
600+ 'django.contrib.contenttypes',
601+ 'django.contrib.sessions',
602+ 'django_nova']
603+ROOT_URLCONF = 'django_nova.tests.urls'
604+TEMPLATE_DIRS = (
605+ os.path.join(ROOT_PATH, 'tests', 'templates')
606+)
607+NOVA_DEFAULT_ENDPOINT = 'none'
608+NOVA_DEFAULT_REGION = 'test'
609+NOVA_ACCESS_KEY = 'test'
610+NOVA_SECRET_KEY = 'test'
611
612=== modified file 'src/django_nova/views/images.py'
613--- src/django_nova/views/images.py 2011-01-24 23:17:58 +0000
614+++ src/django_nova/views/images.py 2011-01-25 23:54:53 +0000
615@@ -30,8 +30,8 @@
616 from django.shortcuts import redirect, render_to_response
617 from django_nova import exceptions
618 from django_nova import forms
619+from django_nova import shortcuts
620 from django_nova.exceptions import handle_nova_error
621-from django_nova.shortcuts import get_project_or_404, get_user_image_permissions
622
623
624 def _image_lists(images, project_id):
625@@ -52,7 +52,7 @@
626 @login_required
627 @handle_nova_error
628 def index(request, project_id):
629- project = get_project_or_404(request, project_id)
630+ project = shortcuts.get_project_or_404(request, project_id)
631 images = project.get_images()
632
633 return render_to_response('django_nova/images/index.html', {
634@@ -66,7 +66,7 @@
635 @login_required
636 @handle_nova_error
637 def launch(request, project_id, image_id):
638- project = get_project_or_404(request, project_id)
639+ project = shortcuts.get_project_or_404(request, project_id)
640
641 if request.method == 'POST':
642 form = forms.LaunchInstanceForm(project, request.POST)
643@@ -107,14 +107,15 @@
644 @login_required
645 @handle_nova_error
646 def detail(request, project_id, image_id):
647- project = get_project_or_404(request, project_id)
648+ project = shortcuts.get_project_or_404(request, project_id)
649 images = project.get_images()
650
651 ami = project.get_image(image_id)
652+ can_modify = shortcuts.get_user_image_permissions(request.user.username,
653+ project_id)
654
655 if not ami:
656 raise http.Http404()
657-
658 return render_to_response('django_nova/images/index.html', {
659 'form': forms.LaunchInstanceForm(project),
660 'update_form': forms.UpdateImageForm(ami),
661@@ -123,14 +124,14 @@
662 'images': images,
663 'image_lists': _image_lists(images, project_id),
664 'ami': ami,
665- 'can_modify': get_user_image_permissions(request.user.username, project_id),
666+ 'can_modify': can_modify,
667 }, context_instance = template.RequestContext(request))
668
669
670 @login_required
671 @handle_nova_error
672 def remove(request, project_id, image_id):
673- project = get_project_or_404(request, project_id)
674+ project = shortcuts.get_project_or_404(request, project_id)
675
676 if request.method == 'POST':
677 try:
678@@ -159,34 +160,27 @@
679 @login_required
680 @handle_nova_error
681 def privacy(request, project_id, image_id):
682- project = get_project_or_404(request, project_id)
683- conn = project.get_nova_connection()
684+ project = shortcuts.get_project_or_404(request, project_id)
685
686 if request.method == 'POST':
687 ami = project.get_image(image_id)
688
689 if ami.is_public:
690- # TODO(devcamcar): create a wrapper in manager.ProjectManager
691- # for modifying image attributes.
692 try:
693- conn.modify_image_attribute(image_id,
694- attribute='launchPermission',
695- operation='remove',
696- groups='all',)
697- except boto.exception.EC2ResponseError, e:
698+ project.modify_image_attribute(image_id,
699+ attribute='launchPermission',
700+ operation='remove')
701+ except exceptions.NovaApiError, e:
702 messages.error(request,
703- 'Unable to make image private: %s - %s' %
704- (e.code, e.message,))
705+ 'Unable to make image private: %s' % e.message)
706 else:
707 try:
708- conn.modify_image_attribute(image_id,
709- attribute='launchPermission',
710- operation='add',
711- groups='all')
712- except boto.exception.EC2ResponseError, e:
713+ project.modify_image_attribute(image_id,
714+ attribute='launchPermission',
715+ operation='add')
716+ except exceptions.NovaApiError, e:
717 messages.error(request,
718- 'Unable to make image public: %s - %s' %
719- (e.code, e.message,))
720+ 'Unable to make image public: %s' % e.message)
721
722 return redirect('nova_images_detail', project_id, image_id)
723
724@@ -194,7 +188,7 @@
725 @login_required
726 @handle_nova_error
727 def update(request, project_id, image_id):
728- project = get_project_or_404(request, project_id)
729+ project = shortcuts.get_project_or_404(request, project_id)
730 ami = project.get_image(image_id)
731
732 if request.method == 'POST':
733@@ -221,7 +215,6 @@
734 'form': form,
735 'region': project.region,
736 'project': project,
737- 'project_list': project_list,
738 'ami': ami,
739 }, context_instance = template.RequestContext(request))
740 else:
741
742=== modified file 'src/django_nova/views/instances.py'
743--- src/django_nova/views/instances.py 2011-01-18 23:07:26 +0000
744+++ src/django_nova/views/instances.py 2011-01-25 23:54:53 +0000
745@@ -27,14 +27,14 @@
746 from django.shortcuts import redirect, render_to_response
747 from django_nova import exceptions
748 from django_nova import forms as nova_forms
749+from django_nova import shortcuts
750 from django_nova.exceptions import handle_nova_error
751-from django_nova.shortcuts import get_project_or_404
752
753
754 @login_required
755 @handle_nova_error
756 def index(request, project_id):
757- project = get_project_or_404(request, project_id)
758+ project = shortcuts.get_project_or_404(request, project_id)
759 instances = sorted(project.get_instances(), key=lambda k: k.public_dns_name)
760
761 return render_to_response('django_nova/instances/index.html', {
762@@ -48,7 +48,7 @@
763 @login_required
764 @handle_nova_error
765 def detail(request, project_id, instance_id):
766- project = get_project_or_404(request, project_id)
767+ project = shortcuts.get_project_or_404(request, project_id)
768 instance = project.get_instance(instance_id)
769 instances = sorted(project.get_instances(), key=lambda k: k.public_dns_name)
770
771@@ -68,7 +68,7 @@
772 @login_required
773 @handle_nova_error
774 def performance(request, project_id, instance_id):
775- project = get_project_or_404(request, project_id)
776+ project = shortcuts.get_project_or_404(request, project_id)
777 instance = project.get_instance(instance_id)
778
779 if not instance:
780@@ -88,7 +88,7 @@
781 if not request.user.is_authenticated():
782 return http.HttpResponseForbidden()
783
784- project = get_project_or_404(request, project_id)
785+ project = shortcuts.get_project_or_404(request, project_id)
786 instances = sorted(project.get_instances(), key=lambda k: k.public_dns_name)
787
788 return render_to_response('django_nova/instances/_instances_list.html', {
789@@ -103,7 +103,7 @@
790 if not request.user.is_authenticated():
791 return http.HttpResponseForbidden()
792
793- project = get_project_or_404(request, project_id)
794+ project = shortcuts.get_project_or_404(request, project_id)
795 instance = project.get_instance(instance_id)
796 instances = sorted(project.get_instances(), key=lambda k: k.public_dns_name)
797
798@@ -117,7 +117,7 @@
799 @login_required
800 @handle_nova_error
801 def terminate(request, project_id):
802- project = get_project_or_404(request, project_id)
803+ project = shortcuts.get_project_or_404(request, project_id)
804
805 if request.method == 'POST':
806 instance_id = request.POST['instance_id']
807@@ -138,7 +138,7 @@
808 @login_required
809 @handle_nova_error
810 def console(request, project_id, instance_id):
811- project = get_project_or_404(request, project_id)
812+ project = shortcuts.get_project_or_404(request, project_id)
813 conn = project.get_nova_connection()
814 console = conn.get_console_output(instance_id)
815 response = http.HttpResponse(mimetype='text/plain')
816@@ -151,7 +151,7 @@
817 @login_required
818 @handle_nova_error
819 def graph(request, project_id, instance_id, graph_name):
820- project = get_project_or_404(request, project_id)
821+ project = shortcuts.get_project_or_404(request, project_id)
822 graph = project.get_instance_graph(instance_id, graph_name)
823
824 if graph is None:
825@@ -166,10 +166,10 @@
826 @login_required
827 @handle_nova_error
828 def update(request, project_id, instance_id):
829- project = get_project_or_404(request, project_id)
830+ project = shortcuts.get_project_or_404(request, project_id)
831 instance = project.get_instance(instance_id)
832
833- if instance is None:
834+ if not instance:
835 raise http.Http404()
836
837 if request.method == 'POST':
838
839=== modified file 'src/django_nova/views/keypairs.py'
840--- src/django_nova/views/keypairs.py 2011-01-18 23:07:26 +0000
841+++ src/django_nova/views/keypairs.py 2011-01-25 23:54:53 +0000
842@@ -27,14 +27,14 @@
843 from django.shortcuts import redirect, render_to_response
844 from django_nova import exceptions
845 from django_nova import forms
846+from django_nova import shortcuts
847 from django_nova.exceptions import handle_nova_error
848-from django_nova.shortcuts import get_project_or_404
849
850
851 @login_required
852 @handle_nova_error
853 def index(request, project_id, download_key=None):
854- project = get_project_or_404(request, project_id)
855+ project = shortcuts.get_project_or_404(request, project_id)
856 keypairs = project.get_key_pairs()
857
858 return render_to_response('django_nova/keypairs/index.html', {
859@@ -48,7 +48,7 @@
860 @login_required
861 @handle_nova_error
862 def add(request, project_id):
863- project = get_project_or_404(request, project_id)
864+ project = shortcuts.get_project_or_404(request, project_id)
865
866 if request.method == 'POST':
867 form = forms.CreateKeyPairForm(project, request.POST)
868@@ -87,7 +87,7 @@
869 @login_required
870 @handle_nova_error
871 def delete(request, project_id):
872- project = get_project_or_404(request, project_id)
873+ project = shortcuts.get_project_or_404(request, project_id)
874
875 if request.method == 'POST':
876 key_name = request.POST['key_name']
877@@ -108,7 +108,7 @@
878 @handle_nova_error
879 def download(request, project_id, key_name):
880 # Ensure the project exists.
881- get_project_or_404(request, project_id)
882+ shortcuts.get_project_or_404(request, project_id)
883
884 try:
885 material = request.session.pop('key.%s' % key_name)

Subscribers

People subscribed via source and target branches

to all changes:
to status/vote changes: