Merge lp:~blake-rouse/maas/reload-on-version-change into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4396
Proposed branch: lp:~blake-rouse/maas/reload-on-version-change
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 295 lines (+166/-4)
8 files modified
src/maasserver/context_processors.py (+1/-0)
src/maasserver/static/js/angular/directives/tests/test_version_reloader.js (+88/-0)
src/maasserver/static/js/angular/directives/version_reloader.js (+37/-0)
src/maasserver/static/js/angular/factories/general.js (+10/-0)
src/maasserver/static/js/angular/factories/tests/test_general.js (+16/-3)
src/maasserver/templates/maasserver/index.html (+1/-1)
src/maasserver/websockets/handlers/general.py (+6/-0)
src/maasserver/websockets/handlers/tests/test_general.py (+7/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/reload-on-version-change
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+275235@code.launchpad.net

Commit message

Reload the entire page if the region version changes.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/context_processors.py'
2--- src/maasserver/context_processors.py 2015-10-19 17:56:35 +0000
3+++ src/maasserver/context_processors.py 2015-10-21 19:48:17 +0000
4@@ -73,6 +73,7 @@
5 'js/angular/directives/sticky_header.js',
6 'js/angular/directives/placeholder.js',
7 'js/angular/directives/enter_blur.js',
8+ 'js/angular/directives/version_reloader.js',
9 'js/angular/filters/nodes.js',
10 'js/angular/filters/by_fabric.js',
11 'js/angular/filters/by_vlan.js',
12
13=== added file 'src/maasserver/static/js/angular/directives/tests/test_version_reloader.js'
14--- src/maasserver/static/js/angular/directives/tests/test_version_reloader.js 1970-01-01 00:00:00 +0000
15+++ src/maasserver/static/js/angular/directives/tests/test_version_reloader.js 2015-10-21 19:48:17 +0000
16@@ -0,0 +1,88 @@
17+/* Copyright 2015 Canonical Ltd. This software is licensed under the
18+ * GNU Affero General Public License version 3 (see the file LICENSE).
19+ *
20+ * Unit tests for version reloader.
21+ */
22+
23+describe("maasVersionReloader", function() {
24+
25+ // Load the MAAS module.
26+ beforeEach(module("MAAS"));
27+
28+ // Grab the needed angular pieces.
29+ var $q;
30+ beforeEach(inject(function($injector) {
31+ $q = $injector.get("$q");
32+ }));
33+
34+ // Load the GeneralManager, ManagerHelperService, RegionConnection and
35+ // mock the websocket connection.
36+ var GeneralManager, ManagerHelperService, RegionConnection, webSocket;
37+ beforeEach(inject(function($injector) {
38+ GeneralManager = $injector.get("GeneralManager");
39+ RegionConnection = $injector.get("RegionConnection");
40+ ManagerHelperService = $injector.get("ManagerHelperService");
41+
42+ // Mock buildSocket so an actual connection is not made.
43+ webSocket = new MockWebSocket();
44+ spyOn(RegionConnection, "buildSocket").and.returnValue(webSocket);
45+ }));
46+
47+
48+ // Create a new scope before each test.
49+ var $scope;
50+ beforeEach(inject(function($rootScope) {
51+ $scope = $rootScope.$new();
52+ }));
53+
54+ // Return the compiled directive with the items from the scope.
55+ function compileDirective() {
56+ var directive;
57+ var html = [
58+ '<div>',
59+ '<div data-maas-version-reloader></div>',
60+ '</div>'
61+ ].join('');
62+ // Compile the directive.
63+ inject(function($compile) {
64+ directive = $compile(html)($scope);
65+ });
66+ // Perform the digest cycle to finish the compile.
67+ $scope.$digest();
68+ return directive.find("div[data-maas-version-reloader]");
69+ }
70+
71+ it("sets version from GeneralManager", function() {
72+ var directive = compileDirective();
73+ expect($scope.version).toBe(GeneralManager.getData("version"));
74+ });
75+
76+ it("watches version.test onces ManagerHelperService resolves", function() {
77+ var defer = $q.defer();
78+ spyOn(ManagerHelperService, "loadManager").and.returnValue(
79+ defer.promise);
80+ var directive = compileDirective();
81+ spyOn($scope, "$watch");
82+
83+ defer.resolve();
84+ $scope.$digest();
85+
86+ expect($scope.$watch.calls.argsFor(0)[0]).toBe("version.text");
87+ });
88+
89+ it("calls reloadPage when version.text changes", function() {
90+ var defer = $q.defer();
91+ spyOn(ManagerHelperService, "loadManager").and.returnValue(
92+ defer.promise);
93+
94+ var directive = compileDirective();
95+ spyOn($scope, "reloadPage");
96+ defer.resolve();
97+ $scope.$digest();
98+
99+ $scope.version.text = makeName("new");
100+ $scope.$digest();
101+
102+ expect($scope.reloadPage).toHaveBeenCalled();
103+ });
104+});
105
106=== added file 'src/maasserver/static/js/angular/directives/version_reloader.js'
107--- src/maasserver/static/js/angular/directives/version_reloader.js 1970-01-01 00:00:00 +0000
108+++ src/maasserver/static/js/angular/directives/version_reloader.js 2015-10-21 19:48:17 +0000
109@@ -0,0 +1,37 @@
110+/* Copyright 2015 Canonical Ltd. This software is licensed under the
111+ * GNU Affero General Public License version 3 (see the file LICENSE).
112+ *
113+ * Version reloader.
114+ *
115+ * Watches the version reported by the GeneralManager if it changes then
116+ * the entire page is reloaded by-passing the local browser cache.
117+ */
118+
119+
120+angular.module('MAAS').directive('maasVersionReloader', [
121+ '$window', 'GeneralManager', 'ManagerHelperService',
122+ function($window, GeneralManager, ManagerHelperService) {
123+ return {
124+ restrict: "A",
125+ controller: function($scope) {
126+ $scope.version = GeneralManager.getData("version");
127+
128+ // Reload the page by-passing the browser cache.
129+ $scope.reloadPage = function() {
130+ // Force cache reload by passing true.
131+ $window.location.reload(true);
132+ };
133+
134+ ManagerHelperService.loadManager(GeneralManager).then(
135+ function() {
136+ GeneralManager.enableAutoReload(true);
137+ $scope.$watch("version.text",
138+ function(newValue, oldValue) {
139+ if(newValue !== oldValue) {
140+ $scope.reloadPage();
141+ }
142+ });
143+ });
144+ }
145+ };
146+ }]);
147
148=== modified file 'src/maasserver/static/js/angular/factories/general.js'
149--- src/maasserver/static/js/angular/factories/general.js 2015-10-04 20:47:36 +0000
150+++ src/maasserver/static/js/angular/factories/general.js 2015-10-21 19:48:17 +0000
151@@ -73,6 +73,16 @@
152 replaceData: function(oldData, newData) {
153 angular.copy(newData, oldData);
154 }
155+ },
156+ version: {
157+ method: "general.version",
158+ data: { text: null },
159+ loaded: false,
160+ polling: false,
161+ nextPromise: null,
162+ replaceData: function(oldData, newData) {
163+ oldData.text = newData;
164+ }
165 }
166 };
167
168
169=== modified file 'src/maasserver/static/js/angular/factories/tests/test_general.js'
170--- src/maasserver/static/js/angular/factories/tests/test_general.js 2015-10-04 21:01:20 +0000
171+++ src/maasserver/static/js/angular/factories/tests/test_general.js 2015-10-21 19:48:17 +0000
172@@ -51,7 +51,7 @@
173 it("_data has expected keys", function() {
174 expect(Object.keys(GeneralManager._data)).toEqual(
175 ["node_actions", "device_actions", "architectures", "hwe_kernels",
176- "osinfo", "bond_options"]);
177+ "osinfo", "bond_options", "version"]);
178 });
179
180 it("_data.node_actions has correct data", function() {
181@@ -111,6 +111,16 @@
182 expect(angular.isFunction(bond_options.replaceData)).toBe(true);
183 });
184
185+ it("_data.version has correct data", function() {
186+ var version = GeneralManager._data.version;
187+ expect(version.method).toBe("general.version");
188+ expect(version.data).toEqual({ text: null });
189+ expect(version.loaded).toBe(false);
190+ expect(version.polling).toBe(false);
191+ expect(version.nextPromise).toBeNull();
192+ expect(angular.isFunction(version.replaceData)).toBe(true);
193+ });
194+
195 describe("_getInternalData", function() {
196
197 it("raises error for unknown data", function() {
198@@ -146,7 +156,8 @@
199 GeneralManager._data.architectures.loaded = true;
200 GeneralManager._data.hwe_kernels.loaded = true;
201 GeneralManager._data.osinfo.loaded = true;
202- GeneralManager._data.bond_options.loaded = false;
203+ GeneralManager._data.bond_options.loaded = true;
204+ GeneralManager._data.version.loaded = false;
205 expect(GeneralManager.isLoaded()).toBe(false);
206 });
207
208@@ -157,6 +168,7 @@
209 GeneralManager._data.hwe_kernels.loaded = true;
210 GeneralManager._data.osinfo.loaded = true;
211 GeneralManager._data.bond_options.loaded = true;
212+ GeneralManager._data.version.loaded = true;
213 expect(GeneralManager.isLoaded()).toBe(true);
214 });
215 });
216@@ -404,7 +416,7 @@
217 spyOn(GeneralManager, "_loadData").and.returnValue(
218 $q.defer().promise);
219 GeneralManager.loadItems();
220- expect(GeneralManager._loadData.calls.count()).toBe(6);
221+ expect(GeneralManager._loadData.calls.count()).toBe(7);
222 });
223
224 it("resolve defer once all resolve", function(done) {
225@@ -414,6 +426,7 @@
226 $q.defer(),
227 $q.defer(),
228 $q.defer(),
229+ $q.defer(),
230 $q.defer()
231 ];
232 var i = 0;
233
234=== modified file 'src/maasserver/templates/maasserver/index.html'
235--- src/maasserver/templates/maasserver/index.html 2015-09-29 07:21:52 +0000
236+++ src/maasserver/templates/maasserver/index.html 2015-10-21 19:48:17 +0000
237@@ -21,7 +21,7 @@
238
239 {% include "maasserver/js-conf.html" %}
240 </head>
241-<body data-ng-init="site = '{{ global_options.site_name }}'">
242+<body data-ng-init="site = '{{ global_options.site_name }}'" data-maas-version-reloader>
243 <div class="wrapper maas-wrapper">
244 <header class="banner global fixed" role="banner">
245 <nav role="navigation" class="nav-primary nav-right">
246
247=== modified file 'src/maasserver/websockets/handlers/general.py'
248--- src/maasserver/websockets/handlers/general.py 2015-10-04 20:47:36 +0000
249+++ src/maasserver/websockets/handlers/general.py 2015-10-21 19:48:17 +0000
250@@ -34,6 +34,7 @@
251 list_osystem_choices,
252 list_release_choices,
253 )
254+from maasserver.utils.version import get_maas_version_ui
255 from maasserver.websockets.base import Handler
256
257
258@@ -49,6 +50,7 @@
259 'device_actions',
260 'random_hostname',
261 'bond_options',
262+ 'version',
263 ]
264
265 def architectures(self, params):
266@@ -126,3 +128,7 @@
267 "lacp_rates": BOND_LACP_RATE_CHOICES,
268 "xmit_hash_policies": BOND_XMIT_HASH_POLICY_CHOICES,
269 }
270+
271+ def version(self, params):
272+ """Return the MAAS version."""
273+ return get_maas_version_ui()
274
275=== modified file 'src/maasserver/websockets/handlers/tests/test_general.py'
276--- src/maasserver/websockets/handlers/tests/test_general.py 2015-10-04 20:47:36 +0000
277+++ src/maasserver/websockets/handlers/tests/test_general.py 2015-10-21 19:48:17 +0000
278@@ -27,6 +27,7 @@
279 from maasserver.testing.testcase import MAASServerTestCase
280 from maasserver.websockets.handlers import general
281 from maasserver.websockets.handlers.general import GeneralHandler
282+from mock import sentinel
283
284
285 class TestGeneralHandler(MAASServerTestCase):
286@@ -121,3 +122,9 @@
287 "lacp_rates": BOND_LACP_RATE_CHOICES,
288 "xmit_hash_policies": BOND_XMIT_HASH_POLICY_CHOICES,
289 }, handler.bond_options({}))
290+
291+ def test_version(self):
292+ handler = GeneralHandler(factory.make_User(), {})
293+ self.patch_autospec(
294+ general, "get_maas_version_ui").return_value = sentinel.version
295+ self.assertEquals(sentinel.version, handler.version({}))