Merge lp:~lamont/maas/duplicate-default-key into lp:~maas-committers/maas/trunk
- duplicate-default-key
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | LaMont Jones |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4888 |
Proposed branch: | lp:~lamont/maas/duplicate-default-key |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
328 lines (+122/-37) 8 files modified
src/maasserver/models/domain.py (+20/-11) src/maasserver/models/fabric.py (+19/-9) src/maasserver/models/space.py (+18/-9) src/maasserver/models/tests/test_domain.py (+12/-0) src/maasserver/models/tests/test_fabric.py (+12/-0) src/maasserver/models/tests/test_space.py (+12/-0) src/maasserver/models/tests/test_zone.py (+12/-0) src/maasserver/models/zone.py (+17/-8) |
To merge this branch: | bzr merge lp:~lamont/maas/duplicate-default-key |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+291158@code.launchpad.net |
Commit message
Correctly handle duplicate key id=0 for domain, fabric, space, zone models.
Description of the change
get_default_
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~lamont/maas/duplicate-default-key into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Hit:3 http://
Hit:4 http://
Get:5 http://
Get:6 http://
Get:7 http://
Get:8 http://
Fetched 17.5 MB in 3s (5,112 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu1).
archdetect-deb is already the newest version (1.117ubuntu1).
authbind is already the newest version (2.1.1+nmu1).
bash is already the newest version (4.3-14ubuntu1).
bind9 is already the newest version (1:9.10.
bind9utils is already the newest version (1:9.10.
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
dh-apport is already the newest version (2.20.1-0ubuntu1).
dh-systemd is already the newest version (1.29ubuntu1).
distro-info is already the newest version (0.14build1).
dnsutils is alrea...
MAAS Lander (maas-lander) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Preview Diff
1 | === modified file 'src/maasserver/models/domain.py' | |||
2 | --- src/maasserver/models/domain.py 2016-03-28 13:54:47 +0000 | |||
3 | +++ src/maasserver/models/domain.py 2016-04-07 16:43:29 +0000 | |||
4 | @@ -36,6 +36,7 @@ | |||
5 | 36 | Q, | 36 | Q, |
6 | 37 | ) | 37 | ) |
7 | 38 | from django.db.models.query import QuerySet | 38 | from django.db.models.query import QuerySet |
8 | 39 | from django.db.utils import IntegrityError | ||
9 | 39 | from maasserver import DefaultMeta | 40 | from maasserver import DefaultMeta |
10 | 40 | from maasserver.fields import DomainNameField | 41 | from maasserver.fields import DomainNameField |
11 | 41 | from maasserver.models.cleansave import CleanSave | 42 | from maasserver.models.cleansave import CleanSave |
12 | @@ -106,17 +107,25 @@ | |||
13 | 106 | def get_default_domain(self): | 107 | def get_default_domain(self): |
14 | 107 | """Return the default domain.""" | 108 | """Return the default domain.""" |
15 | 108 | now = datetime.datetime.now() | 109 | now = datetime.datetime.now() |
27 | 109 | domain, created = self.get_or_create( | 110 | try: |
28 | 110 | id=0, | 111 | domain, created = self.get_or_create( |
29 | 111 | defaults={ | 112 | id=0, |
30 | 112 | 'id': 0, | 113 | defaults={ |
31 | 113 | 'name': DEFAULT_DOMAIN_NAME, | 114 | 'id': 0, |
32 | 114 | 'authoritative': True, | 115 | 'name': DEFAULT_DOMAIN_NAME, |
33 | 115 | 'ttl': None, | 116 | 'authoritative': True, |
34 | 116 | 'created': now, | 117 | 'ttl': None, |
35 | 117 | 'updated': now, | 118 | 'created': now, |
36 | 118 | } | 119 | 'updated': now, |
37 | 119 | ) | 120 | } |
38 | 121 | ) | ||
39 | 122 | except IntegrityError as err: | ||
40 | 123 | if (err.args[0].startswith( | ||
41 | 124 | 'duplicate key value violates unique' | ||
42 | 125 | ' constraint "maasserver_domain_pkey"')): | ||
43 | 126 | domain = self.get(id=0) | ||
44 | 127 | else: | ||
45 | 128 | raise(err) | ||
46 | 120 | return domain | 129 | return domain |
47 | 121 | 130 | ||
48 | 122 | def get_domain_or_404(self, specifiers, user, perm): | 131 | def get_domain_or_404(self, specifiers, user, perm): |
49 | 123 | 132 | ||
50 | === modified file 'src/maasserver/models/fabric.py' | |||
51 | --- src/maasserver/models/fabric.py 2016-04-07 13:48:58 +0000 | |||
52 | +++ src/maasserver/models/fabric.py 2016-04-07 16:43:29 +0000 | |||
53 | @@ -22,6 +22,7 @@ | |||
54 | 22 | Manager, | 22 | Manager, |
55 | 23 | ) | 23 | ) |
56 | 24 | from django.db.models.query import QuerySet | 24 | from django.db.models.query import QuerySet |
57 | 25 | from django.db.utils import IntegrityError | ||
58 | 25 | from maasserver import DefaultMeta | 26 | from maasserver import DefaultMeta |
59 | 26 | from maasserver.models.cleansave import CleanSave | 27 | from maasserver.models.cleansave import CleanSave |
60 | 27 | from maasserver.models.interface import Interface | 28 | from maasserver.models.interface import Interface |
61 | @@ -77,15 +78,24 @@ | |||
62 | 77 | def get_default_fabric(self): | 78 | def get_default_fabric(self): |
63 | 78 | """Return the default fabric.""" | 79 | """Return the default fabric.""" |
64 | 79 | now = datetime.datetime.now() | 80 | now = datetime.datetime.now() |
74 | 80 | fabric, created = self.get_or_create( | 81 | try: |
75 | 81 | id=0, | 82 | fabric, created = self.get_or_create( |
76 | 82 | defaults={ | 83 | id=0, |
77 | 83 | 'id': 0, | 84 | defaults={ |
78 | 84 | 'name': None, | 85 | 'id': 0, |
79 | 85 | 'created': now, | 86 | 'name': None, |
80 | 86 | 'updated': now, | 87 | 'created': now, |
81 | 87 | } | 88 | 'updated': now, |
82 | 88 | ) | 89 | } |
83 | 90 | ) | ||
84 | 91 | except IntegrityError as err: | ||
85 | 92 | if (err.args[0].startswith( | ||
86 | 93 | 'duplicate key value violates unique' | ||
87 | 94 | ' constraint "maasserver_fabric_pkey"')): | ||
88 | 95 | fabric = self.get(id=0) | ||
89 | 96 | created = False | ||
90 | 97 | else: | ||
91 | 98 | raise(err) | ||
92 | 89 | if created: | 99 | if created: |
93 | 90 | fabric._create_default_vlan() | 100 | fabric._create_default_vlan() |
94 | 91 | return fabric | 101 | return fabric |
95 | 92 | 102 | ||
96 | === modified file 'src/maasserver/models/space.py' | |||
97 | --- src/maasserver/models/space.py 2016-04-05 20:01:58 +0000 | |||
98 | +++ src/maasserver/models/space.py 2016-04-07 16:43:29 +0000 | |||
99 | @@ -20,6 +20,7 @@ | |||
100 | 20 | Manager, | 20 | Manager, |
101 | 21 | ) | 21 | ) |
102 | 22 | from django.db.models.query import QuerySet | 22 | from django.db.models.query import QuerySet |
103 | 23 | from django.db.utils import IntegrityError | ||
104 | 23 | from maasserver import DefaultMeta | 24 | from maasserver import DefaultMeta |
105 | 24 | from maasserver.models.cleansave import CleanSave | 25 | from maasserver.models.cleansave import CleanSave |
106 | 25 | from maasserver.models.timestampedmodel import TimestampedModel | 26 | from maasserver.models.timestampedmodel import TimestampedModel |
107 | @@ -75,15 +76,23 @@ | |||
108 | 75 | def get_default_space(self): | 76 | def get_default_space(self): |
109 | 76 | """Return the default space.""" | 77 | """Return the default space.""" |
110 | 77 | now = datetime.datetime.now() | 78 | now = datetime.datetime.now() |
120 | 78 | space, _ = self.get_or_create( | 79 | try: |
121 | 79 | id=0, | 80 | space, _ = self.get_or_create( |
122 | 80 | defaults={ | 81 | id=0, |
123 | 81 | 'id': 0, | 82 | defaults={ |
124 | 82 | 'name': None, | 83 | 'id': 0, |
125 | 83 | 'created': now, | 84 | 'name': None, |
126 | 84 | 'updated': now, | 85 | 'created': now, |
127 | 85 | } | 86 | 'updated': now, |
128 | 86 | ) | 87 | } |
129 | 88 | ) | ||
130 | 89 | except IntegrityError as err: | ||
131 | 90 | if (err.args[0].startswith( | ||
132 | 91 | 'duplicate key value violates unique' | ||
133 | 92 | ' constraint "maasserver_space_pkey"')): | ||
134 | 93 | space = self.get(id=0) | ||
135 | 94 | else: | ||
136 | 95 | raise(err) | ||
137 | 87 | return space | 96 | return space |
138 | 88 | 97 | ||
139 | 89 | def get_space_or_404(self, specifiers, user, perm): | 98 | def get_space_or_404(self, specifiers, user, perm): |
140 | 90 | 99 | ||
141 | === modified file 'src/maasserver/models/tests/test_domain.py' | |||
142 | --- src/maasserver/models/tests/test_domain.py 2016-02-11 14:33:51 +0000 | |||
143 | +++ src/maasserver/models/tests/test_domain.py 2016-04-07 16:43:29 +0000 | |||
144 | @@ -13,6 +13,7 @@ | |||
145 | 13 | ValidationError, | 13 | ValidationError, |
146 | 14 | ) | 14 | ) |
147 | 15 | from django.db.models import ProtectedError | 15 | from django.db.models import ProtectedError |
148 | 16 | from django.db.utils import IntegrityError | ||
149 | 16 | from maasserver.enum import NODE_PERMISSION | 17 | from maasserver.enum import NODE_PERMISSION |
150 | 17 | from maasserver.models.config import Config | 18 | from maasserver.models.config import Config |
151 | 18 | from maasserver.models.dnsdata import DNSData | 19 | from maasserver.models.dnsdata import DNSData |
152 | @@ -23,6 +24,7 @@ | |||
153 | 23 | from maasserver.models.staticipaddress import StaticIPAddress | 24 | from maasserver.models.staticipaddress import StaticIPAddress |
154 | 24 | from maasserver.testing.factory import factory | 25 | from maasserver.testing.factory import factory |
155 | 25 | from maasserver.testing.testcase import MAASServerTestCase | 26 | from maasserver.testing.testcase import MAASServerTestCase |
156 | 27 | from maastesting.matchers import MockCalledOnce | ||
157 | 26 | from netaddr import IPAddress | 28 | from netaddr import IPAddress |
158 | 27 | from testtools.matchers import MatchesStructure | 29 | from testtools.matchers import MatchesStructure |
159 | 28 | from testtools.testcase import ExpectedException | 30 | from testtools.testcase import ExpectedException |
160 | @@ -151,6 +153,16 @@ | |||
161 | 151 | self.assertEqual(0, default_domain.id) | 153 | self.assertEqual(0, default_domain.id) |
162 | 152 | self.assertEqual(DEFAULT_DOMAIN_NAME, default_domain.get_name()) | 154 | self.assertEqual(DEFAULT_DOMAIN_NAME, default_domain.get_name()) |
163 | 153 | 155 | ||
164 | 156 | def test_get_default_domain_handles_exception(self): | ||
165 | 157 | default_domain = Domain.objects.get_default_domain() | ||
166 | 158 | func = self.patch(Domain.objects, "get_or_create") | ||
167 | 159 | func.side_effect = IntegrityError( | ||
168 | 160 | 'duplicate key value violates unique constraint ' | ||
169 | 161 | '"maasserver_domain_pkey"') | ||
170 | 162 | domain = Domain.objects.get_default_domain() | ||
171 | 163 | self.assertThat(func, MockCalledOnce()) | ||
172 | 164 | self.assertEqual(default_domain.id, domain.id) | ||
173 | 165 | |||
174 | 154 | def test_invalid_name_raises_exception(self): | 166 | def test_invalid_name_raises_exception(self): |
175 | 155 | self.assertRaises( | 167 | self.assertRaises( |
176 | 156 | ValidationError, | 168 | ValidationError, |
177 | 157 | 169 | ||
178 | === modified file 'src/maasserver/models/tests/test_fabric.py' | |||
179 | --- src/maasserver/models/tests/test_fabric.py 2016-04-07 13:48:58 +0000 | |||
180 | +++ src/maasserver/models/tests/test_fabric.py 2016-04-07 16:43:29 +0000 | |||
181 | @@ -10,6 +10,7 @@ | |||
182 | 10 | PermissionDenied, | 10 | PermissionDenied, |
183 | 11 | ValidationError, | 11 | ValidationError, |
184 | 12 | ) | 12 | ) |
185 | 13 | from django.db.utils import IntegrityError | ||
186 | 13 | from maasserver.enum import ( | 14 | from maasserver.enum import ( |
187 | 14 | INTERFACE_TYPE, | 15 | INTERFACE_TYPE, |
188 | 15 | NODE_PERMISSION, | 16 | NODE_PERMISSION, |
189 | @@ -25,6 +26,7 @@ | |||
190 | 25 | ) | 26 | ) |
191 | 26 | from maasserver.testing.factory import factory | 27 | from maasserver.testing.factory import factory |
192 | 27 | from maasserver.testing.testcase import MAASServerTestCase | 28 | from maasserver.testing.testcase import MAASServerTestCase |
193 | 29 | from maastesting.matchers import MockCalledOnce | ||
194 | 28 | from testtools.matchers import MatchesStructure | 30 | from testtools.matchers import MatchesStructure |
195 | 29 | 31 | ||
196 | 30 | 32 | ||
197 | @@ -192,6 +194,16 @@ | |||
198 | 192 | factory.make_Fabric, | 194 | factory.make_Fabric, |
199 | 193 | name=fabric1.name) | 195 | name=fabric1.name) |
200 | 194 | 196 | ||
201 | 197 | def test_get_default_fabric_handles_exception(self): | ||
202 | 198 | default_fabric = Fabric.objects.get_default_fabric() | ||
203 | 199 | func = self.patch(Fabric.objects, "get_or_create") | ||
204 | 200 | func.side_effect = IntegrityError( | ||
205 | 201 | 'duplicate key value violates unique constraint ' | ||
206 | 202 | '"maasserver_fabric_pkey"') | ||
207 | 203 | fabric = Fabric.objects.get_default_fabric() | ||
208 | 204 | self.assertThat(func, MockCalledOnce()) | ||
209 | 205 | self.assertEqual(default_fabric.id, fabric.id) | ||
210 | 206 | |||
211 | 195 | def test_get_default_fabric_is_idempotent(self): | 207 | def test_get_default_fabric_is_idempotent(self): |
212 | 196 | default_fabric = Fabric.objects.get_default_fabric() | 208 | default_fabric = Fabric.objects.get_default_fabric() |
213 | 197 | default_fabric2 = Fabric.objects.get_default_fabric() | 209 | default_fabric2 = Fabric.objects.get_default_fabric() |
214 | 198 | 210 | ||
215 | === modified file 'src/maasserver/models/tests/test_space.py' | |||
216 | --- src/maasserver/models/tests/test_space.py 2016-04-07 13:48:58 +0000 | |||
217 | +++ src/maasserver/models/tests/test_space.py 2016-04-07 16:43:29 +0000 | |||
218 | @@ -12,6 +12,7 @@ | |||
219 | 12 | ValidationError, | 12 | ValidationError, |
220 | 13 | ) | 13 | ) |
221 | 14 | from django.db.models import ProtectedError | 14 | from django.db.models import ProtectedError |
222 | 15 | from django.db.utils import IntegrityError | ||
223 | 15 | from maasserver.enum import NODE_PERMISSION | 16 | from maasserver.enum import NODE_PERMISSION |
224 | 16 | from maasserver.models.space import ( | 17 | from maasserver.models.space import ( |
225 | 17 | DEFAULT_SPACE_NAME, | 18 | DEFAULT_SPACE_NAME, |
226 | @@ -19,6 +20,7 @@ | |||
227 | 19 | ) | 20 | ) |
228 | 20 | from maasserver.testing.factory import factory | 21 | from maasserver.testing.factory import factory |
229 | 21 | from maasserver.testing.testcase import MAASServerTestCase | 22 | from maasserver.testing.testcase import MAASServerTestCase |
230 | 23 | from maastesting.matchers import MockCalledOnce | ||
231 | 22 | from testtools.matchers import MatchesStructure | 24 | from testtools.matchers import MatchesStructure |
232 | 23 | from testtools.testcase import ExpectedException | 25 | from testtools.testcase import ExpectedException |
233 | 24 | 26 | ||
234 | @@ -141,6 +143,16 @@ | |||
235 | 141 | self.assertEqual(DEFAULT_SPACE_NAME, default_space.get_name()) | 143 | self.assertEqual(DEFAULT_SPACE_NAME, default_space.get_name()) |
236 | 142 | self.assertEqual(DEFAULT_SPACE_NAME, default_space.name) | 144 | self.assertEqual(DEFAULT_SPACE_NAME, default_space.name) |
237 | 143 | 145 | ||
238 | 146 | def test_get_default_space_handles_exception(self): | ||
239 | 147 | default_space = Space.objects.get_default_space() | ||
240 | 148 | func = self.patch(Space.objects, "get_or_create") | ||
241 | 149 | func.side_effect = IntegrityError( | ||
242 | 150 | 'duplicate key value violates unique constraint ' | ||
243 | 151 | '"maasserver_space_pkey"') | ||
244 | 152 | space = Space.objects.get_default_space() | ||
245 | 153 | self.assertThat(func, MockCalledOnce()) | ||
246 | 154 | self.assertEqual(default_space.id, space.id) | ||
247 | 155 | |||
248 | 144 | def test_invalid_name_raises_exception(self): | 156 | def test_invalid_name_raises_exception(self): |
249 | 145 | self.assertRaises( | 157 | self.assertRaises( |
250 | 146 | ValidationError, | 158 | ValidationError, |
251 | 147 | 159 | ||
252 | === modified file 'src/maasserver/models/tests/test_zone.py' | |||
253 | --- src/maasserver/models/tests/test_zone.py 2016-03-28 13:54:47 +0000 | |||
254 | +++ src/maasserver/models/tests/test_zone.py 2016-04-07 16:43:29 +0000 | |||
255 | @@ -5,6 +5,7 @@ | |||
256 | 5 | 5 | ||
257 | 6 | __all__ = [] | 6 | __all__ = [] |
258 | 7 | 7 | ||
259 | 8 | from django.db.utils import IntegrityError | ||
260 | 8 | from maasserver.enum import NODE_TYPE | 9 | from maasserver.enum import NODE_TYPE |
261 | 9 | from maasserver.models.zone import ( | 10 | from maasserver.models.zone import ( |
262 | 10 | DEFAULT_ZONE_NAME, | 11 | DEFAULT_ZONE_NAME, |
263 | @@ -13,6 +14,7 @@ | |||
264 | 13 | from maasserver.testing.factory import factory | 14 | from maasserver.testing.factory import factory |
265 | 14 | from maasserver.testing.testcase import MAASServerTestCase | 15 | from maasserver.testing.testcase import MAASServerTestCase |
266 | 15 | from maasserver.utils.orm import reload_object | 16 | from maasserver.utils.orm import reload_object |
267 | 17 | from maastesting.matchers import MockCalledOnce | ||
268 | 16 | 18 | ||
269 | 17 | 19 | ||
270 | 18 | class TestZoneManager(MAASServerTestCase): | 20 | class TestZoneManager(MAASServerTestCase): |
271 | @@ -27,6 +29,16 @@ | |||
272 | 27 | self.assertEqual( | 29 | self.assertEqual( |
273 | 28 | DEFAULT_ZONE_NAME, Zone.objects.get_default_zone().name) | 30 | DEFAULT_ZONE_NAME, Zone.objects.get_default_zone().name) |
274 | 29 | 31 | ||
275 | 32 | def test_get_default_zone_handles_exception(self): | ||
276 | 33 | default_zone = Zone.objects.get_default_zone() | ||
277 | 34 | func = self.patch(Zone.objects, "get_or_create") | ||
278 | 35 | func.side_effect = IntegrityError( | ||
279 | 36 | 'duplicate key value violates unique constraint ' | ||
280 | 37 | '"maasserver_zone_name_key"') | ||
281 | 38 | zone = Zone.objects.get_default_zone() | ||
282 | 39 | self.assertThat(func, MockCalledOnce()) | ||
283 | 40 | self.assertEqual(default_zone.id, zone.id) | ||
284 | 41 | |||
285 | 30 | 42 | ||
286 | 31 | class TestZone(MAASServerTestCase): | 43 | class TestZone(MAASServerTestCase): |
287 | 32 | """Tests for :class:`Zone`.""" | 44 | """Tests for :class:`Zone`.""" |
288 | 33 | 45 | ||
289 | === modified file 'src/maasserver/models/zone.py' | |||
290 | --- src/maasserver/models/zone.py 2015-12-05 01:43:40 +0000 | |||
291 | +++ src/maasserver/models/zone.py 2016-04-07 16:43:29 +0000 | |||
292 | @@ -18,6 +18,7 @@ | |||
293 | 18 | Manager, | 18 | Manager, |
294 | 19 | TextField, | 19 | TextField, |
295 | 20 | ) | 20 | ) |
296 | 21 | from django.db.utils import IntegrityError | ||
297 | 21 | from maasserver import DefaultMeta | 22 | from maasserver import DefaultMeta |
298 | 22 | from maasserver.enum import NODE_TYPE | 23 | from maasserver.enum import NODE_TYPE |
299 | 23 | from maasserver.models.cleansave import CleanSave | 24 | from maasserver.models.cleansave import CleanSave |
300 | @@ -41,14 +42,22 @@ | |||
301 | 41 | def get_default_zone(self): | 42 | def get_default_zone(self): |
302 | 42 | """Return the default zone.""" | 43 | """Return the default zone.""" |
303 | 43 | now = datetime.datetime.now() | 44 | now = datetime.datetime.now() |
312 | 44 | zone, _ = self.get_or_create( | 45 | try: |
313 | 45 | name=DEFAULT_ZONE_NAME, | 46 | zone, _ = self.get_or_create( |
314 | 46 | defaults={ | 47 | name=DEFAULT_ZONE_NAME, |
315 | 47 | 'name': DEFAULT_ZONE_NAME, | 48 | defaults={ |
316 | 48 | 'created': now, | 49 | 'name': DEFAULT_ZONE_NAME, |
317 | 49 | 'updated': now, | 50 | 'created': now, |
318 | 50 | } | 51 | 'updated': now, |
319 | 51 | ) | 52 | } |
320 | 53 | ) | ||
321 | 54 | except IntegrityError as err: | ||
322 | 55 | if (err.args[0].startswith( | ||
323 | 56 | 'duplicate key value violates unique' | ||
324 | 57 | ' constraint "maasserver_zone_name_key"')): | ||
325 | 58 | zone = self.get(name=DEFAULT_ZONE_NAME) | ||
326 | 59 | else: | ||
327 | 60 | raise(err) | ||
328 | 52 | return zone | 61 | return zone |
329 | 53 | 62 | ||
330 | 54 | 63 |
Looks good. Thanks for the tests.