Merge lp:~rvb/maas/expose-version-api into lp:~maas-committers/maas/trunk
- expose-version-api
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Raphaël Badin | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 3794 | ||||
Proposed branch: | lp:~rvb/maas/expose-version-api | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Diff against target: |
496 lines (+197/-164) 5 files modified
src/maasserver/api/tests/test_version.py (+7/-0) src/maasserver/api/version.py (+7/-0) src/maasserver/context_processors.py (+2/-2) src/maasserver/utils/tests/test_version.py (+125/-107) src/maasserver/utils/version.py (+56/-55) |
||||
To merge this branch: | bzr merge lp:~rvb/maas/expose-version-api | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+255357@code.launchpad.net |
Commit message
Expose the version and the subversion of the running MAAS on the API.
Description of the change
Note that I'm doing a bit more caching in version.py than would be expected: I want to cache things at the low level so that calls to display the version in the UI and calls to return the version in the API call the API backend only once but I also want to cache the result of the (tiny) processing done by get_maas_
Christian Reis (kiko) wrote : | # |
Blake Rouse (blake-rouse) wrote : | # |
No complaints. Only think the simple_cache decorator would be better in its own file.
Raphaël Badin (rvb) wrote : | # |
Thanks for the review!
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~rvb/maas/expose-version-api into lp:maas failed. Below is the output from the failed tests.
Ign http://
Get:1 http://
Get:2 http://
Ign http://
Ign http://
Get:3 http://
Hit http://
Get:4 http://
Get:5 http://
Get:6 http://
Hit http://
Get:7 http://
Get:8 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:9 http://
Get:10 http://
Get:11 http://
Get:12 http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,621 kB in 3s (526 kB/s)
Reading package lists...
sudo DEBIAN_
--
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~rvb/maas/expose-version-api into lp:maas failed. Below is the output from the failed tests.
Ign http://
Hit http://
Hit http://
Ign http://
Ign http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Reading package lists...
sudo DEBIAN_
--
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~rvb/maas/expose-version-api into lp:maas failed. Below is the output from the failed tests.
Ign http://
Get:1 http://
Get:2 http://
Ign http://
Ign http://
Hit http://
Get:3 http://
Hit http://
Get:4 http://
Get:5 http://
Hit http://
Get:6 http://
Get:7 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:8 http://
Get:9 http://
Hit http://
Hit http://
Get:10 http://
Get:11 http://
Get:12 http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,621 kB in 3s (524 kB/s)
Reading package lists...
sudo DEBIAN_
--
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.
Gavin Panella (allenap) wrote : | # |
Not a review, but a few comments (and one in the diff):
* Is "subversion" the best term. People often talk about major and minor
versions.
* The distutils.version module might be of interest.
* One of the explicit reasons for the capabilities views was to
*discourage* use of version numbers when testing for features. Is this
therefore a regression? What's the use case?
Raphaël Badin (rvb) wrote : | # |
Hey Gavin
> Not a review, but a few comments (and one in the diff):
> * Is "subversion" the best term. People often talk about major and minor
> versions.
AFAIK, major and minor are used for something different: "1.8.0" → major: 1, minor: 8. Here we really want version/subversion I think.
> * One of the explicit reasons for the capabilities views was to
> *discourage* use of version numbers when testing for features. Is this
> therefore a regression? What's the use case?
The capabilities are the thing other tools like Juju should use to check for functionality but some times it's useful (mostly when debugging) to be able to know exactly what the version is in order to, say, figure out if a particular bug fix is present.
Preview Diff
1 | === modified file 'src/maasserver/api/tests/test_version.py' |
2 | --- src/maasserver/api/tests/test_version.py 2014-08-18 13:23:21 +0000 |
3 | +++ src/maasserver/api/tests/test_version.py 2015-04-08 15:11:40 +0000 |
4 | @@ -21,6 +21,7 @@ |
5 | from django.core.urlresolvers import reverse |
6 | from maasserver.api.version import API_CAPABILITIES_LIST |
7 | from maasserver.testing.testcase import MAASServerTestCase |
8 | +from maasserver.utils import version as version_module |
9 | |
10 | |
11 | class TestFindingResources(MAASServerTestCase): |
12 | @@ -31,6 +32,10 @@ |
13 | '/api/1.0/version/', reverse('version')) |
14 | |
15 | def test_GET_returns_details(self): |
16 | + mock_apt = self.patch(version_module, "get_version_from_apt") |
17 | + mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" |
18 | + self.patch(version_module, "_cache", {}) |
19 | + |
20 | response = self.client.get(reverse('version')) |
21 | self.assertEqual(httplib.OK, response.status_code) |
22 | |
23 | @@ -38,5 +43,7 @@ |
24 | self.assertEqual( |
25 | { |
26 | 'capabilities': API_CAPABILITIES_LIST, |
27 | + 'version': '1.8.0', |
28 | + 'subversion': 'alpha4+bzr356', |
29 | }, |
30 | parsed_result) |
31 | |
32 | === modified file 'src/maasserver/api/version.py' |
33 | --- src/maasserver/api/version.py 2014-09-17 02:17:35 +0000 |
34 | +++ src/maasserver/api/version.py 2015-04-08 15:11:40 +0000 |
35 | @@ -20,6 +20,7 @@ |
36 | |
37 | from django.http import HttpResponse |
38 | from maasserver.api.support import AnonymousOperationsHandler |
39 | +from maasserver.utils.version import get_maas_version_subversion |
40 | |
41 | # MAAS capabilities. See docs/capabilities.rst for documentation. |
42 | CAP_NETWORKS_MANAGEMENT = 'networks-management' |
43 | @@ -39,6 +40,8 @@ |
44 | This returns a JSON dictionary with information about this |
45 | MAAS instance. |
46 | { |
47 | + 'version': '1.8.0', |
48 | + 'subversion': 'alpha10+bzr3750', |
49 | 'capabilities': ['capability1', 'capability2', ...] |
50 | } |
51 | """ |
52 | @@ -46,8 +49,12 @@ |
53 | create = update = delete = None |
54 | |
55 | def read(self, request): |
56 | + version, subversion = get_maas_version_subversion() |
57 | version_info = { |
58 | 'capabilities': API_CAPABILITIES_LIST, |
59 | + 'version': version, |
60 | + 'subversion': subversion, |
61 | + |
62 | } |
63 | return HttpResponse( |
64 | version_info, mimetype='application/json; charset=utf-8', |
65 | |
66 | === modified file 'src/maasserver/context_processors.py' |
67 | --- src/maasserver/context_processors.py 2015-04-02 14:18:18 +0000 |
68 | +++ src/maasserver/context_processors.py 2015-04-08 15:11:40 +0000 |
69 | @@ -23,7 +23,7 @@ |
70 | from maasserver.models import Config |
71 | from maasserver.utils.version import ( |
72 | get_maas_doc_version, |
73 | - get_maas_version, |
74 | + get_maas_version_ui, |
75 | ) |
76 | |
77 | |
78 | @@ -88,6 +88,6 @@ |
79 | 'site_name': Config.objects.get_config('maas_name'), |
80 | }, |
81 | 'debug': settings.DEBUG, |
82 | - 'version': get_maas_version(), |
83 | + 'version': get_maas_version_ui(), |
84 | 'doc_version': get_maas_doc_version(), |
85 | } |
86 | |
87 | === modified file 'src/maasserver/utils/tests/test_version.py' |
88 | --- src/maasserver/utils/tests/test_version.py 2015-03-30 19:38:57 +0000 |
89 | +++ src/maasserver/utils/tests/test_version.py 2015-04-08 15:11:40 +0000 |
90 | @@ -63,64 +63,6 @@ |
91 | version.get_version_from_apt(version.REGION_PACKAGE_NAME)) |
92 | |
93 | |
94 | -class TestFormatVersion(MAASTestCase): |
95 | - |
96 | - scenarios = [ |
97 | - ("with ~", { |
98 | - "version": "1.8.0~alpha4+bzr356-0ubuntu1", |
99 | - "output": "1.8.0 (alpha4+bzr356)", |
100 | - }), |
101 | - ("without ~", { |
102 | - "version": "1.8.0+bzr356-0ubuntu1", |
103 | - "output": "1.8.0 (+bzr356)", |
104 | - }), |
105 | - ("without ~ or +", { |
106 | - "version": "1.8.0-0ubuntu1", |
107 | - "output": "1.8.0", |
108 | - }), |
109 | - ] |
110 | - |
111 | - def test__returns_formatted_version(self): |
112 | - self.assertEquals(self.output, version.format_version(self.version)) |
113 | - |
114 | - |
115 | -class TestGetMAASRegionPackageVersion(MAASTestCase): |
116 | - |
117 | - def test__returns_value_from_global(self): |
118 | - self.patch(version, "MAAS_VERSION", sentinel.maas_version) |
119 | - self.assertIs( |
120 | - sentinel.maas_version, version.get_maas_region_package_version()) |
121 | - |
122 | - def test__calls_get_version_from_apt_if_global_not_set(self): |
123 | - self.patch(version, "MAAS_VERSION", None) |
124 | - mock_apt = self.patch(version, "get_version_from_apt") |
125 | - version.get_maas_region_package_version() |
126 | - self.assertThat( |
127 | - mock_apt, MockCalledOnceWith(version.REGION_PACKAGE_NAME)) |
128 | - |
129 | - def test__calls_format_version_with_version_from_apt(self): |
130 | - self.patch(version, "MAAS_VERSION", None) |
131 | - current_ver = "1.8.0~alpha4+bzr356-0ubuntu1" |
132 | - mock_apt = self.patch(version, "get_version_from_apt") |
133 | - mock_apt.return_value = current_ver |
134 | - mock_format = self.patch(version, "format_version") |
135 | - mock_format.return_value = sentinel.format |
136 | - self.expectThat( |
137 | - version.get_maas_region_package_version(), Is(sentinel.format)) |
138 | - self.expectThat( |
139 | - mock_format, MockCalledOnceWith(current_ver)) |
140 | - |
141 | - def test__sets_global_value(self): |
142 | - self.patch(version, "MAAS_VERSION", None) |
143 | - current_ver = "1.8.0~alpha4+bzr356-0ubuntu1" |
144 | - mock_apt = self.patch(version, "get_version_from_apt") |
145 | - mock_apt.return_value = current_ver |
146 | - mock_format = self.patch(version, "format_version") |
147 | - mock_format.return_value = sentinel.format |
148 | - version.get_maas_region_package_version() |
149 | - self.assertIs(sentinel.format, version.MAAS_VERSION) |
150 | - |
151 | - |
152 | class TestGetMAASBranch(MAASTestCase): |
153 | |
154 | def test__returns_None_if_Branch_is_None(self): |
155 | @@ -139,61 +81,137 @@ |
156 | self.assertIsNone(version.get_maas_branch()) |
157 | |
158 | |
159 | -class TestGetMAASVersion(MAASTestCase): |
160 | - |
161 | - def test__returns_version_from_get_maas_region_package_version(self): |
162 | - mock_version = self.patch(version, "get_maas_region_package_version") |
163 | - mock_version.return_value = sentinel.version |
164 | - self.assertIs(sentinel.version, version.get_maas_version()) |
165 | - |
166 | - def test__returns_unknown_if_version_is_empty_and_not_bzr_branch(self): |
167 | - mock_version = self.patch(version, "get_maas_region_package_version") |
168 | - mock_version.return_value = "" |
169 | - mock_branch = self.patch(version, "get_maas_branch") |
170 | - mock_branch.return_value = None |
171 | - self.assertEquals("unknown", version.get_maas_version()) |
172 | - |
173 | - def test__returns_from_source_and_revno_from_branch(self): |
174 | - mock_version = self.patch(version, "get_maas_region_package_version") |
175 | - mock_version.return_value = "" |
176 | - revno = random.randint(1, 5000) |
177 | - mock_branch = self.patch(version, "get_maas_branch") |
178 | - mock_branch.return_value.revno.return_value = revno |
179 | - self.assertEquals( |
180 | - "from source (+bzr%s)" % revno, version.get_maas_version()) |
181 | - |
182 | - |
183 | -class TestGetMAASMainVersion(MAASTestCase): |
184 | - |
185 | - def test__returns_main_version_from_package_version_with_space(self): |
186 | - mock_version = self.patch(version, "get_maas_region_package_version") |
187 | - mock_version.return_value = "1.8.0 (alpha4+bzr356)" |
188 | - self.assertEquals("1.8.0", version.get_maas_main_version()) |
189 | - |
190 | - def test__returns_main_version_from_package_version_without_space(self): |
191 | - mock_version = self.patch(version, "get_maas_region_package_version") |
192 | - mock_version.return_value = "1.8.0" |
193 | - self.assertEquals("1.8.0", version.get_maas_main_version()) |
194 | - |
195 | - def test__returns_empty_if_version_is_empty(self): |
196 | - mock_version = self.patch(version, "get_maas_region_package_version") |
197 | - mock_version.return_value = "" |
198 | - self.assertEquals("", version.get_maas_main_version()) |
199 | - |
200 | - |
201 | -class TestGetMAASDocVersion(MAASTestCase): |
202 | +class TestExtractVersionSubversion(MAASTestCase): |
203 | + |
204 | + scenarios = [ |
205 | + ("with ~", { |
206 | + "version": "1.8.0~alpha4+bzr356-0ubuntu1", |
207 | + "output": ("1.8.0", "alpha4+bzr356"), |
208 | + }), |
209 | + ("without ~", { |
210 | + "version": "1.8.0+bzr356-0ubuntu1", |
211 | + "output": ("1.8.0", "+bzr356"), |
212 | + }), |
213 | + ("without ~ or +", { |
214 | + "version": "1.8.0-0ubuntu1", |
215 | + "output": ("1.8.0", ""), |
216 | + }), |
217 | + ] |
218 | + |
219 | + def test__returns_version_subversion(self): |
220 | + self.assertEquals( |
221 | + self.output, version.extract_version_subversion(self.version)) |
222 | + |
223 | + |
224 | +class TestVersionTestCase(MAASTestCase): |
225 | + """MAASTestCase that resets the cache used by utility methods.""" |
226 | + |
227 | + def setUp(self): |
228 | + super(TestVersionTestCase, self).setUp() |
229 | + self.patch(version, "_cache", {}) |
230 | + |
231 | + |
232 | +class TestGetMAASPackageVersion(TestVersionTestCase): |
233 | + |
234 | + def test__calls_get_version_from_apt(self): |
235 | + mock_apt = self.patch(version, "get_version_from_apt") |
236 | + mock_apt.return_value = sentinel.version |
237 | + self.expectThat( |
238 | + version.get_maas_package_version(), Is(sentinel.version)) |
239 | + self.expectThat( |
240 | + mock_apt, MockCalledOnceWith(version.REGION_PACKAGE_NAME)) |
241 | + |
242 | + |
243 | +class TestGetMAASVersionSubversion(TestVersionTestCase): |
244 | + |
245 | + def test__returns_package_version(self): |
246 | + mock_apt = self.patch(version, "get_version_from_apt") |
247 | + mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" |
248 | + self.assertEquals( |
249 | + ("1.8.0", "alpha4+bzr356"), version.get_maas_version_subversion()) |
250 | + |
251 | + def test__returns_unknown_if_version_is_empty_and_not_bzr_branch(self): |
252 | + mock_version = self.patch(version, "get_version_from_apt") |
253 | + mock_version.return_value = "" |
254 | + mock_branch = self.patch(version, "get_maas_branch") |
255 | + mock_branch.return_value = None |
256 | + self.assertEquals( |
257 | + ("unknown", ""), version.get_maas_version_subversion()) |
258 | + |
259 | + def test__returns_from_source_and_revno_from_branch(self): |
260 | + mock_version = self.patch(version, "get_version_from_apt") |
261 | + mock_version.return_value = "" |
262 | + revno = random.randint(1, 5000) |
263 | + mock_branch = self.patch(version, "get_maas_branch") |
264 | + mock_branch.return_value.revno.return_value = revno |
265 | + self.assertEquals( |
266 | + ("from source (+bzr%s)" % revno, ""), |
267 | + version.get_maas_version_subversion()) |
268 | + |
269 | + |
270 | +class TestGetMAASVersionUI(TestVersionTestCase): |
271 | + |
272 | + def test__returns_package_version(self): |
273 | + mock_apt = self.patch(version, "get_version_from_apt") |
274 | + mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" |
275 | + self.assertEquals( |
276 | + "1.8.0 (alpha4+bzr356)", version.get_maas_version_ui()) |
277 | + |
278 | + def test__returns_unknown_if_version_is_empty_and_not_bzr_branch(self): |
279 | + mock_version = self.patch(version, "get_version_from_apt") |
280 | + mock_version.return_value = "" |
281 | + mock_branch = self.patch(version, "get_maas_branch") |
282 | + mock_branch.return_value = None |
283 | + self.assertEquals("unknown", version.get_maas_version_ui()) |
284 | + |
285 | + def test__returns_from_source_and_revno_from_branch(self): |
286 | + mock_version = self.patch(version, "get_version_from_apt") |
287 | + mock_version.return_value = "" |
288 | + revno = random.randint(1, 5000) |
289 | + mock_branch = self.patch(version, "get_maas_branch") |
290 | + mock_branch.return_value.revno.return_value = revno |
291 | + self.assertEquals( |
292 | + "from source (+bzr%s)" % revno, version.get_maas_version_ui()) |
293 | + |
294 | + |
295 | +class TestGetMAASDocVersion(TestVersionTestCase): |
296 | |
297 | def test__returns_doc_version_with_greater_than_1_decimals(self): |
298 | - mock_version = self.patch(version, "get_maas_main_version") |
299 | - mock_version.return_value = "1.8.0" |
300 | + mock_apt = self.patch(version, "get_version_from_apt") |
301 | + mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" |
302 | self.assertEquals("docs1.8", version.get_maas_doc_version()) |
303 | |
304 | def test__returns_doc_version_with_equal_to_1_decimals(self): |
305 | - mock_version = self.patch(version, "get_maas_main_version") |
306 | - mock_version.return_value = "1.8" |
307 | + mock_apt = self.patch(version, "get_version_from_apt") |
308 | + mock_apt.return_value = "1.8~alpha4+bzr356-0ubuntu1" |
309 | self.assertEquals("docs1.8", version.get_maas_doc_version()) |
310 | |
311 | def test__returns_just_doc_if_version_is_empty(self): |
312 | - mock_version = self.patch(version, "get_maas_main_version") |
313 | - mock_version.return_value = "" |
314 | + mock_apt = self.patch(version, "get_version_from_apt") |
315 | + mock_apt.return_value = "" |
316 | self.assertEquals("docs", version.get_maas_doc_version()) |
317 | + |
318 | + |
319 | +class TestVersionMethodsCached(TestVersionTestCase): |
320 | + |
321 | + scenarios = [ |
322 | + ("get_maas_package_version", dict(method="get_maas_package_version")), |
323 | + ("get_maas_version_subversion", dict( |
324 | + method="get_maas_version_subversion")), |
325 | + ("get_maas_version_ui", dict(method="get_maas_version_ui")), |
326 | + ("get_maas_doc_version", dict(method="get_maas_doc_version")), |
327 | + ] |
328 | + |
329 | + def test_method_is_cached(self): |
330 | + mock_apt = self.patch(version, "get_version_from_apt") |
331 | + mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" |
332 | + cached_method = getattr(version, self.method) |
333 | + first_return_value = cached_method() |
334 | + second_return_value = cached_method() |
335 | + # The return value is not empty (full unit tests have been performed |
336 | + # earlier). |
337 | + self.assertNotIn(first_return_value, [b'', u'', None]) |
338 | + self.assertEqual(first_return_value, second_return_value) |
339 | + # Apt has only been called once. |
340 | + self.expectThat( |
341 | + mock_apt, MockCalledOnceWith(version.REGION_PACKAGE_NAME)) |
342 | |
343 | === modified file 'src/maasserver/utils/version.py' |
344 | --- src/maasserver/utils/version.py 2015-03-30 17:54:35 +0000 |
345 | +++ src/maasserver/utils/version.py 2015-04-08 15:11:40 +0000 |
346 | @@ -14,7 +14,8 @@ |
347 | __metaclass__ = type |
348 | __all__ = [ |
349 | "get_maas_doc_version", |
350 | - "get_maas_version", |
351 | + "get_maas_version_subversion", |
352 | + "get_maas_version_ui", |
353 | ] |
354 | |
355 | import apt_pkg |
356 | @@ -29,9 +30,6 @@ |
357 | # Initialize apt_pkg. |
358 | apt_pkg.init() |
359 | |
360 | -# Holds the version of maas. |
361 | -MAAS_VERSION = None |
362 | - |
363 | # Name of maas package to get version from. |
364 | REGION_PACKAGE_NAME = "maas-region-controller-min" |
365 | |
366 | @@ -50,34 +48,16 @@ |
367 | return "" |
368 | |
369 | |
370 | -def format_version(version): |
371 | - """Format `version` into a better looking string for the UI.""" |
372 | +def extract_version_subversion(version): |
373 | + """Return a tuple (version, subversion) from the given apt version.""" |
374 | if "~" in version: |
375 | main_version, extra = version.split("~", 1) |
376 | - return "%s (%s)" % (main_version, extra.split("-", 1)[0]) |
377 | + return main_version, extra.split("-", 1)[0] |
378 | elif "+" in version: |
379 | main_version, extra = version.split("+", 1) |
380 | - return "%s (+%s)" % (main_version, extra.split("-", 1)[0]) |
381 | + return main_version, "+" + extra.split("-", 1)[0] |
382 | else: |
383 | - return version.split("-", 1)[0] |
384 | - |
385 | - |
386 | -def get_maas_region_package_version(): |
387 | - """Return the dpkg version for `REGION_PACKAGE_NAME`. |
388 | - |
389 | - Lazy loads the version. Once loaded it will not be loaded again. |
390 | - This is to speed up the call to this method and also to require the |
391 | - region to be restarted to see the new version. |
392 | - """ |
393 | - global MAAS_VERSION |
394 | - if MAAS_VERSION is None: |
395 | - MAAS_VERSION = get_version_from_apt(REGION_PACKAGE_NAME) |
396 | - # Possibly this returned an empty string, meaning it's not installed |
397 | - # and no need to call again. |
398 | - if MAAS_VERSION: |
399 | - # It is a valid version so set the correct format. |
400 | - MAAS_VERSION = format_version(MAAS_VERSION) |
401 | - return MAAS_VERSION |
402 | + return version.split("-", 1)[0], '' |
403 | |
404 | |
405 | def get_maas_branch(): |
406 | @@ -90,41 +70,62 @@ |
407 | return None |
408 | |
409 | |
410 | -def get_maas_version(): |
411 | - """Return the version string for the running MAAS region.""" |
412 | - # MAAS is installed from package, return the version string. |
413 | - version = get_maas_region_package_version() |
414 | - if version: |
415 | - return version |
416 | +_cache = {} |
417 | + |
418 | + |
419 | +# A very simply memoize function: when we switch to Django 1.7 we should use |
420 | +# Django's lru_cache method. |
421 | +def simple_cache(fun): |
422 | + def wrapped(*args, **kwargs): |
423 | + key = hash(repr(fun) + repr(args) + repr(kwargs)) |
424 | + if not key in _cache: |
425 | + _cache[key] = fun(*args, **kwargs) |
426 | + return _cache[key] |
427 | + |
428 | + wrapped.__doc__ = "%s %s" % (fun.__doc__, "(cached)") |
429 | + return wrapped |
430 | + |
431 | + |
432 | +@simple_cache |
433 | +def get_maas_package_version(): |
434 | + """Return the apt version for the main MAAS package.""" |
435 | + return get_version_from_apt(REGION_PACKAGE_NAME) |
436 | + |
437 | + |
438 | +@simple_cache |
439 | +def get_maas_version_subversion(): |
440 | + """Return a tuple with the MAAS version and the MAAS subversion.""" |
441 | + apt_version = get_maas_package_version() |
442 | + if apt_version: |
443 | + return extract_version_subversion(apt_version) |
444 | else: |
445 | # Get the branch information |
446 | branch = get_maas_branch() |
447 | if branch is None: |
448 | # Not installed not in branch, then no way to identify. This should |
449 | # not happen, but just in case. |
450 | - return "unknown" |
451 | - else: |
452 | - return "from source (+bzr%s)" % branch.revno() |
453 | - |
454 | - |
455 | -def get_maas_main_version(): |
456 | - """Return the main version for the running MAAS region.""" |
457 | - # MAAS is installed from package, return the version string. |
458 | - version = get_maas_region_package_version() |
459 | - if version: |
460 | - if " " in version: |
461 | - return version.split(" ")[0] |
462 | - else: |
463 | - return version |
464 | - else: |
465 | - return "" |
466 | - |
467 | - |
468 | + return "unknown", '' |
469 | + else: |
470 | + return "from source (+bzr%s)" % branch.revno(), '' |
471 | + |
472 | + |
473 | +@simple_cache |
474 | +def get_maas_version_ui(): |
475 | + """Return the version string for the running MAAS region. |
476 | + |
477 | + The returned string is suitable to display in the UI. |
478 | + """ |
479 | + version, subversion = get_maas_version_subversion() |
480 | + return "%s (%s)" % (version, subversion) if subversion else version |
481 | + |
482 | + |
483 | +@simple_cache |
484 | def get_maas_doc_version(): |
485 | """Return the doc version for the running MAAS region.""" |
486 | - main_version = get_maas_main_version() |
487 | doc_prefix = 'docs' |
488 | - if not main_version: |
489 | + apt_version = get_maas_package_version() |
490 | + if apt_version: |
491 | + version, _ = extract_version_subversion(apt_version) |
492 | + return doc_prefix + '.'.join(version.split('.')[:2]) |
493 | + else: |
494 | return doc_prefix |
495 | - else: |
496 | - return doc_prefix + '.'.join(main_version.split('.')[:2]) |
Is there any chance this could be backported to 1.7?