Merge lp:~gz/pyjuju/0.6_maas_tags_really_backport into lp:pyjuju/0.6

Proposed by Martin Packman on 2013-04-03
Status: Merged
Merged at revision: 599
Proposed branch: lp:~gz/pyjuju/0.6_maas_tags_really_backport
Merge into: lp:pyjuju/0.6
Diff against target: 220 lines (+85/-17)
5 files modified
juju/providers/maas/maas.py (+16/-6)
juju/providers/maas/provider.py (+2/-2)
juju/providers/maas/tests/test_launch.py (+23/-4)
juju/providers/maas/tests/test_maas.py (+16/-1)
juju/providers/maas/tests/test_provider.py (+28/-4)
To merge this branch: bzr merge lp:~gz/pyjuju/0.6_maas_tags_really_backport
Reviewer Review Type Date Requested Status
Martin Packman (community) Approve on 2013-04-03
Review via email: mp+156887@code.launchpad.net

Description of the change

Backport sane handling of the maas-tags constraint

The history here is messy, this backport covers both the following merge proposals:
<https://code.launchpad.net/~hazmat/juju/maas-tags-redux/+merge/148876>
<https://code.launchpad.net/~hazmat/juju/maas-with-tags/+merge/149586>

To post a comment you must log in.
Martin Packman (gz) wrote :

Test suite passes with change.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'juju/providers/maas/maas.py'
2--- juju/providers/maas/maas.py 2012-11-06 16:38:38 +0000
3+++ juju/providers/maas/maas.py 2013-04-03 15:49:24 +0000
4@@ -47,17 +47,25 @@
5 return match.group("system_id")
6
7
8-def _int_str(value):
9+def _int_str(value, k, c):
10 """Convert value to integer then string"""
11 return str(int(value))
12
13
14+def _str(value, k, c):
15+ return str(value)
16+
17+
18+def _raw(value, k, c):
19+ return c.data.get(k)
20+
21+
22 class MAASClient(MAASOAuthConnection):
23
24 _handled_constraints = (
25- ("maas-name", "name", str),
26- ("maas-tags", "tags", str),
27- ("arch", "arch", str),
28+ ("maas-name", "name", _str),
29+ ("maas-tags", "tags", _raw),
30+ ("arch", "arch", _str),
31 ("cpu", "cpu_count", _int_str),
32 ("mem", "mem", _int_str),
33 )
34@@ -140,7 +148,7 @@
35 for key_from, key_to, translate in self._handled_constraints:
36 value = constraints.get(key_from, None)
37 if value is not None:
38- params[key_to] = translate(value)
39+ params[key_to] = translate(value, key_from, constraints)
40 return self.post("api/1.0/nodes/", params)
41
42 def start_node(self, resource_uri, ubuntu_series, user_data):
43@@ -154,7 +162,9 @@
44 """
45 assert isinstance(user_data, str), (
46 "User data must be a byte string.")
47- params = {"op": "start", "distro_series": ubuntu_series, "user_data": b64encode(user_data)}
48+ params = {"op": "start",
49+ "distro_series": ubuntu_series,
50+ "user_data": b64encode(user_data)}
51 return self.post(resource_uri, params)
52
53 def stop_node(self, resource_uri):
54
55=== modified file 'juju/providers/maas/provider.py'
56--- juju/providers/maas/provider.py 2012-11-14 18:27:09 +0000
57+++ juju/providers/maas/provider.py 2013-04-03 15:49:24 +0000
58@@ -45,7 +45,7 @@
59 if tag not in self.tag_names:
60 raise ValueError("tag %r does not exist" % (tag,))
61 tags.add(tag)
62- return tag_expression
63+ return tags
64
65
66 class MachineProvider(MachineProviderBase):
67@@ -79,7 +79,7 @@
68 tags_info = yield self.maas_client.list_tags()
69 handler = _TagHandler(tags_info)
70 cs.register("maas-tags", converter=handler.convert,
71- comparer=handler.compare)
72+ comparer=handler.compare)
73 returnValue(cs)
74
75 def get_serialization_data(self):
76
77=== modified file 'juju/providers/maas/tests/test_launch.py'
78--- juju/providers/maas/tests/test_launch.py 2012-09-28 11:50:35 +0000
79+++ juju/providers/maas/tests/test_launch.py 2013-04-03 15:49:24 +0000
80@@ -3,9 +3,11 @@
81
82 """Tests for juju.providers.maas.launch"""
83
84+import json
85+
86 from StringIO import StringIO
87 from twisted.internet import defer
88-from twisted.internet.defer import inlineCallbacks
89+from twisted.internet.defer import inlineCallbacks, succeed
90
91 from juju.errors import ProviderError
92 from juju.lib.mocker import ANY
93@@ -108,7 +110,7 @@
94 "values")
95
96 @inlineCallbacks
97- def test_launch_with_name_constraint(self):
98+ def test_launch_with_constraints(self):
99 # Try to launch a particular machine by its name using the
100 # "maas-name" constraint.
101
102@@ -116,8 +118,25 @@
103 target_node = NODE_JSON[1]
104 self.assertEqual("moon", target_node["hostname"])
105 machine_id = "foo"
106- provider = self._get_provider(FakeMAASHTTPConnection)
107- constraints = {"maas-name": "moon", "ubuntu-series": "splendid"}
108+
109+ test = self
110+
111+ class FakeWithTags(FakeMAASHTTPConnection):
112+
113+ def acquire_node(self):
114+ test.assertIn("clawed|furry", self.data)
115+ return super(FakeWithTags, self).acquire_node()
116+
117+ def list_tags(self):
118+ return succeed(json.dumps([
119+ {'name': 'furry', 'definition': 'fuzzy', 'comment': ''},
120+ {'name': 'clawed', 'definition': 'curvy', 'comment': ''}
121+ ]))
122+
123+ provider = self._get_provider(FakeWithTags)
124+ cs = yield provider.get_constraint_set()
125+ constraints = cs.parse(["maas-name=moon", "maas-tags=clawed|furry"])
126+ constraints = constraints.with_series('splendid')
127 machine_data = {"machine-id": machine_id, "constraints": constraints}
128 machine_list = yield provider.start_machine(machine_data)
129
130
131=== modified file 'juju/providers/maas/tests/test_maas.py'
132--- juju/providers/maas/tests/test_maas.py 2012-11-06 16:38:38 +0000
133+++ juju/providers/maas/tests/test_maas.py 2013-04-03 15:49:24 +0000
134@@ -11,6 +11,7 @@
135 from twisted.web.error import Error
136
137 from juju.errors import ProviderError
138+from juju.providers.maas import MachineProvider
139 from juju.providers.maas.maas import extract_system_id, MAASClient
140 from juju.providers.maas.tests.testing import (
141 CONFIG, FakeMAASHTTPConnection,
142@@ -383,9 +384,23 @@
143 mem = client.post.params_used.get("mem")
144 self.assertEqual("2048", mem)
145
146+ @inlineCallbacks
147 def test_acquire_node_handles_arbitrary_tag_query(self):
148+ mock_client = self.mocker.patch(MAASClient(CONFIG))
149+ mock_client.list_tags()
150+ self.mocker.result(succeed([
151+ {'name': 'red', 'definition': '', 'comment': ''},
152+ {'name': 'white', 'definition': '', 'comment': ''},
153+ {'name': 'blue', 'definition': '', 'comment': ''}]))
154+ self.mocker.replay()
155+
156+ provider = MachineProvider("mymaas", CONFIG)
157+ provider.maas_client = mock_client
158+ cs = yield provider.get_constraint_set()
159+ constraints = cs.parse(["maas-tags=red&!white|blue"])
160+ constraints = constraints.with_series('splendid')
161+
162 client = self.set_up_client_with_fake()
163- constraints = {"maas-tags": "red&!white|blue"}
164 client.acquire_node(constraints)
165
166 tags = client.post.params_used.get("tags")
167
168=== modified file 'juju/providers/maas/tests/test_provider.py'
169--- juju/providers/maas/tests/test_provider.py 2012-11-14 18:26:15 +0000
170+++ juju/providers/maas/tests/test_provider.py 2013-04-03 15:49:24 +0000
171@@ -7,6 +7,9 @@
172
173 from juju.errors import ConstraintError, MachinesNotFound, ProviderError
174 from juju.lib.mocker import ANY
175+from juju.lib import serializer
176+from juju.machine.constraints import Constraints
177+
178 from juju.providers.maas import MachineProvider
179 from juju.providers.maas.maas import MAASClient
180 from juju.providers.maas.tests.testing import (
181@@ -183,14 +186,35 @@
182 {'name': "clawed", 'definition': "HAS claws", 'comment': ""},
183 ]))
184 self.mocker.replay()
185+
186 provider = MachineProvider("maasiv", CONFIG)
187 provider.maas_client = mock_client
188 cs = yield provider.get_constraint_set()
189 bear = cs.parse(["maas-tags=clawed, furry"])
190- bear.can_satisfy(bear)
191- self.assertEqual("clawed, furry", bear["maas-tags"])
192- err = self.assertRaises(ConstraintError,
193+
194+ # Incomplete constraints (no series) can't satisify
195+ self.assertFalse(bear.can_satisfy(bear))
196+
197+ self.assertEqual(set(["clawed", "furry"]), bear["maas-tags"])
198+
199+ err = self.assertRaises(
200+ ConstraintError,
201 cs.parse, ["maas-tags=furry, bouncy"])
202- self.assertEqual("Bad 'maas-tags' constraint 'furry, bouncy': "
203+
204+ self.assertEqual(
205+ "Bad 'maas-tags' constraint 'furry, bouncy': "
206 "tag 'bouncy' does not exist",
207 str(err))
208+
209+ bear = bear.with_series("precise")
210+
211+ # Ensure we can roundtrip through serialization.
212+ raw = serializer.dump(bear.data)
213+ grizzly = cs.load(serializer.load(raw))
214+
215+ self.assertTrue(grizzly.can_satisfy(bear))
216+ rodent = cs.parse(
217+ ["maas-tags=clawed"]).with_series("raring")
218+ self.assertFalse(rodent.can_satisfy(grizzly))
219+ self.assertTrue(grizzly.can_satisfy(
220+ rodent.with_series("precise")))

Subscribers

People subscribed via source and target branches