Merge ~bjornt/maas:peer-proxy-ui into maas:master
- Git
- lp:~bjornt/maas
- peer-proxy-ui
- Merge into master
Status: | Merged |
---|---|
Approved by: | Björn Tillenius |
Approved revision: | 4b3a4a04c6ae0f0afc967f301d873f130e1d4f28 |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~bjornt/maas:peer-proxy-ui |
Merge into: | maas:master |
Diff against target: |
582 lines (+410/-14) 10 files modified
Makefile (+1/-0) src/maasserver/forms/__init__.py (+11/-2) src/maasserver/static/js/angular/directives/proxy_settings.js (+41/-0) src/maasserver/static/js/angular/directives/tests/test_proxy_settings.js (+190/-0) src/maasserver/static/partials/proxy-settings.html (+48/-0) src/maasserver/templates/maasserver/settings.html (+38/-4) src/maasserver/views/combo.py (+1/-0) src/maasserver/views/settings.py (+22/-4) src/maasserver/views/tests/test_settings.py (+45/-2) src/maastesting/karma.conf.js (+13/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Andres Rodriguez (community) | Needs Fixing | ||
Review via email: mp+327591@code.launchpad.net |
Commit message
Change the proxy settings UI to enable configuring a peer proxy.
The network part of the settings page was split into "proxy", "ntp", and "dns", since it was getting too big.
Description of the change
The UI for setting proxy uses angular, so that the widget gets a bit more dynamic and shows the field for proxy URL only when needed. It still renders the required input fields so that the django form still is used to update the proxy settings. Converting it fully to angular was too much work.
Note that the single Javascript test I added is disabled. I couldn't get the tests to work. I'm proposing this for merge anyway, so that the rest of the code can be reviewed, and for someone else to figure out how to get the Javascript tests to work.
The problem I had with the Javascript tests is that the scope doesn't seem to be connected to the template. Inside the template, all scope variables are empty for some reason.
Note also that the UI needs some love to make it look nicer. I wanted to get some general feedback fore spending time on that, though.
Lee Trager (ltrager) wrote : | # |
Andres Rodriguez (andreserl) wrote : | # |
Maria's design and preference is what we have, but I'll talk to her
tomorrow!
On Fri, Jul 21, 2017 at 1:45 AM Lee Trager <email address hidden> wrote:
> I really like splitting NTP and DNS into different sections, it makes the
> page much easier to read. I think we may want to use a drop down to select
> the proxy mode. The text field would be disabled for don't use and
> built-in. I'd ask Maria from design this before reworking incase I'm wrong.
>
> I poked around and can't figure out why MAAS.templates is currently broken
> and wasn't able to come up with anything, Blake might know.
>
> Diff comments:
>
> > diff --git
> a/src/maasserve
> b/src/maasserve
> > new file mode 100644
> > index 0000000..0850058
> > --- /dev/null
> > +++ b/src/maasserve
> > @@ -0,0 +1,43 @@
> > +/* Copyright 2018 Canonical Ltd. This software is licensed under the
>
> Pulling code from the future? ;)
>
> > + * GNU Affero General Public License version 3 (see the file LICENSE).
> > + *
> > + * Proxy settings directive.
> > +*/
> > +
> > +angular.
> > + '$sce', 'ConfigsManager', 'ManagerHelperS
> > + function($sce, ConfigsManager, ManagerHelperSe
> > + return {
> > + restrict: "E",
> > + scope: {},
> > + templateUrl: 'static/
> > + controller: function($scope, $rootScope, $element,
> $document) {
> > + $scope.loading = true;
> > + $scope.
> > + var managers = [ConfigsManager];
> > + ManagerHelperSe
> > + $scope, managers)
> > + $scope.loading = false;
> > + $scope.httpProxy = ConfigsManager.
> > + "http_proxy");
> > + $scope.
> ConfigsManager.
> > + "enable_
> > + $scope.usePeerProxy =
> ConfigsManager.
> > + "use_peer_proxy");
> > + if ($scope.
> > + if ($scope.
> > + if ($scope.
> > + $scope.proxy_type = "peer-proxy";
> > + } else {
> > + $scope.proxy_type = "external-proxy";
> > + }
> > + } else {
> > + $scope.proxy_type = "builtin-proxy";
> > + }
> > + } else {
> > + $scope.proxy_type = "no-proxy";
> > + }
> > + });
> > + }
> > + };
> > + }]);
> > diff --git
> a/src/maasserve
> b/src/maasserve
Blake Rouse (blake-rouse) wrote : | # |
Looks like your using "{{ }}" in the angular directives in the HTML. I am very surprised that it works, since we set the template tag parser differently in MAAS so it works with Django. "{{ }}" is also used by Django, so we change it to "{$ $}".
@Lee - The issue is that you need the new dependency. So if you do "make clean && make" you would get the new dependency.
Blake Rouse (blake-rouse) wrote : | # |
Also looks like you have debugger statement in JS test.
./src/maasserve
62: Unexpected 'debugger'.
62: Line contains a call to debugger.
Makefile:336: recipe for target 'lint-js' failed
make: *** [lint-js] Error 123
Andres Rodriguez (andreserl) wrote : | # |
A few inline fixes wrt wording.
Björn Tillenius (bjornt) wrote : | # |
> Looks like your using "{{ }}" in the angular directives in the HTML. I am very
> surprised that it works, since we set the template tag parser differently in
> MAAS so it works with Django. "{{ }}" is also used by Django, so we change it
> to "{$ $}".
>
> @Lee - The issue is that you need the new dependency. So if you do "make clean
> && make" you would get the new dependency.
Oh. Yeah, it seems to work with {{ }} as well, but I've changed it to {$ $} now. I was hoping that it would be the cause for the tests not working, but I still can't get the tests to work.
Björn Tillenius (bjornt) wrote : | # |
> Also looks like you have debugger statement in JS test.
>
> ./src/maasserve
> 62: Unexpected 'debugger'.
> 62: Line contains a call to debugger.
> Makefile:336: recipe for target 'lint-js' failed
> make: *** [lint-js] Error 123
Fixed. I tried to debug the tests, but had no luck doing so.
Björn Tillenius (bjornt) wrote : | # |
I addressed all the inlines comments. Will work on adding more Javascript tests, since Blake provided a patch to get the tests working.
Björn Tillenius (bjornt) wrote : | # |
I've pushed the Javascript tests now, so it's ready for re-review.
Blake Rouse (blake-rouse) wrote : | # |
Looks good other then the "{{}}" which should be fixed before landing this.
Björn Tillenius (bjornt) wrote : | # |
I replaced {{ }} with {$ $}. I also addressed the review comments from design as well.
MAAS Lander (maas-lander) wrote : | # |
LANDING
-b peer-proxy-ui lp:~bjornt/maas into -b master lp:~maas-committers/maas
STATUS: FAILED BUILD
LOG: http://
- 4b3a4a0... by Björn Tillenius
-
Format imports.
Preview Diff
1 | diff --git a/Makefile b/Makefile |
2 | index 488fa82..9bbab61 100644 |
3 | --- a/Makefile |
4 | +++ b/Makefile |
5 | @@ -187,6 +187,7 @@ define karma-deps |
6 | karma-opera-launcher@0.3.0 |
7 | karma-phantomjs-launcher@0.2.3 |
8 | karma-failed-reporter@0.0.3 |
9 | + karma-ng-html2js-preprocessor@1.0.0 |
10 | phantomjs@2.1.7 |
11 | endef |
12 | |
13 | diff --git a/src/maasserver/forms/__init__.py b/src/maasserver/forms/__init__.py |
14 | index a7314d0..35832d6 100644 |
15 | --- a/src/maasserver/forms/__init__.py |
16 | +++ b/src/maasserver/forms/__init__.py |
17 | @@ -1418,12 +1418,21 @@ class MAASForm(ConfigForm): |
18 | enable_analytics = get_config_field('enable_analytics') |
19 | |
20 | |
21 | -class NetworkForm(ConfigForm): |
22 | - """Settings page, Network section.""" |
23 | +class ProxyForm(ConfigForm): |
24 | + """Settings page, Proxy section.""" |
25 | enable_http_proxy = get_config_field('enable_http_proxy') |
26 | + use_peer_proxy = get_config_field('use_peer_proxy') |
27 | http_proxy = get_config_field('http_proxy') |
28 | + |
29 | + |
30 | +class DNSForm(ConfigForm): |
31 | + """Settings page, DNS section.""" |
32 | upstream_dns = get_config_field('upstream_dns') |
33 | dnssec_validation = get_config_field('dnssec_validation') |
34 | + |
35 | + |
36 | +class NTPForm(ConfigForm): |
37 | + """Settings page, NTP section.""" |
38 | ntp_servers = get_config_field('ntp_servers') |
39 | ntp_external_only = get_config_field('ntp_external_only') |
40 | |
41 | diff --git a/src/maasserver/static/js/angular/directives/proxy_settings.js b/src/maasserver/static/js/angular/directives/proxy_settings.js |
42 | new file mode 100644 |
43 | index 0000000..3e97777 |
44 | --- /dev/null |
45 | +++ b/src/maasserver/static/js/angular/directives/proxy_settings.js |
46 | @@ -0,0 +1,41 @@ |
47 | +/* Copyright 2017 Canonical Ltd. This software is licensed under the |
48 | + * GNU Affero General Public License version 3 (see the file LICENSE). |
49 | + * |
50 | + * Proxy settings directive. |
51 | +*/ |
52 | + |
53 | +angular.module('MAAS').directive('maasProxySettings', [ |
54 | + '$sce', 'ConfigsManager', 'ManagerHelperService', 'JSONService', |
55 | + function($sce, ConfigsManager, ManagerHelperService, JSONService) { |
56 | + return { |
57 | + restrict: "E", |
58 | + scope: {}, |
59 | + templateUrl: 'static/partials/proxy-settings.html', |
60 | + controller: function($scope, $rootScope, $element, $document) { |
61 | + $scope.loading = true; |
62 | + ManagerHelperService.loadManager( |
63 | + $scope, ConfigsManager).then(function() { |
64 | + $scope.loading = false; |
65 | + $scope.httpProxy = ConfigsManager.getItemFromList( |
66 | + "http_proxy"); |
67 | + $scope.enableHttpProxy = ConfigsManager.getItemFromList( |
68 | + "enable_http_proxy"); |
69 | + $scope.usePeerProxy = ConfigsManager.getItemFromList( |
70 | + "use_peer_proxy"); |
71 | + if ($scope.enableHttpProxy.value) { |
72 | + if ($scope.httpProxy.value) { |
73 | + if ($scope.usePeerProxy.value) { |
74 | + $scope.proxy_type = "peer-proxy"; |
75 | + } else { |
76 | + $scope.proxy_type = "external-proxy"; |
77 | + } |
78 | + } else { |
79 | + $scope.proxy_type = "builtin-proxy"; |
80 | + } |
81 | + } else { |
82 | + $scope.proxy_type = "no-proxy"; |
83 | + } |
84 | + }); |
85 | + } |
86 | + }; |
87 | + }]); |
88 | diff --git a/src/maasserver/static/js/angular/directives/tests/test_proxy_settings.js b/src/maasserver/static/js/angular/directives/tests/test_proxy_settings.js |
89 | new file mode 100644 |
90 | index 0000000..ce06777 |
91 | --- /dev/null |
92 | +++ b/src/maasserver/static/js/angular/directives/tests/test_proxy_settings.js |
93 | @@ -0,0 +1,190 @@ |
94 | +/* Copyright 2017 Canonical Ltd. This software is licensed under the |
95 | + * GNU Affero General Public License version 3 (see the file LICENSE). |
96 | + * |
97 | + * Unit tests for MAAS proxy settings directive. |
98 | + */ |
99 | + |
100 | +describe("maasProxySettings", function() { |
101 | + |
102 | + // Load the MAAS module. |
103 | + beforeEach(module("MAAS")); |
104 | + // Make the templates available. |
105 | + beforeEach(module("MAAS.templates")); |
106 | + |
107 | + // Get required angular pieces and create a new scope before each test. |
108 | + var $scope, $compile, $q, ConfigsManager, ManagerHelperService; |
109 | + beforeEach(inject(function($rootScope, $injector) { |
110 | + $scope = $rootScope.$new(); |
111 | + $compile = $injector.get("$compile"); |
112 | + $q = $injector.get("$q"); |
113 | + ConfigsManager = $injector.get("ConfigsManager"); |
114 | + ManagerHelperService = $injector.get("ManagerHelperService"); |
115 | + })); |
116 | + |
117 | + // Create the config options. |
118 | + var httpProxy, enableHttpProxy, usePeerProxy; |
119 | + beforeEach(function() { |
120 | + httpProxy = { |
121 | + name: 'http_proxy', |
122 | + value: '' |
123 | + }; |
124 | + enableHttpProxy = { |
125 | + name: 'enable_http_proxy', |
126 | + value: true |
127 | + }; |
128 | + usePeerProxy = { |
129 | + name: 'use_peer_proxy', |
130 | + value: false |
131 | + }; |
132 | + ConfigsManager._items = [httpProxy, enableHttpProxy, usePeerProxy]; |
133 | + }); |
134 | + |
135 | + // Return the compiled directive. |
136 | + function compileDirective() { |
137 | + var loadManagerDefer = $q.defer(); |
138 | + spyOn(ManagerHelperService, "loadManager").and.returnValue( |
139 | + loadManagerDefer.promise); |
140 | + |
141 | + var html = "<div><maas-proxy-settings></maas-proxy-settings></div>"; |
142 | + var directive = $compile(html)($scope); |
143 | + $scope.$digest(); |
144 | + loadManagerDefer.resolve(); |
145 | + $scope.$digest(); |
146 | + |
147 | + return angular.element( |
148 | + directive.find("maas-proxy-settings")); |
149 | + } |
150 | + |
151 | + it("no-proxy without http proxy", function() { |
152 | + enableHttpProxy.value = false; |
153 | + usePeerProxy.value = false; |
154 | + httpProxy.value = ''; |
155 | + var directive = compileDirective( |
156 | + '<maas-proxy-settings></maas-proxy-settings>'); |
157 | + var scope = directive.isolateScope(); |
158 | + var enableProxyField = angular.element(directive.find( |
159 | + "#id_proxy-enable_http_proxy")); |
160 | + var httpProxyField = angular.element(directive.find( |
161 | + "#id_proxy-http_proxy")); |
162 | + var usePeerProxyField = angular.element(directive.find( |
163 | + "#id_proxy-use_peer_proxy")); |
164 | + expect(scope.proxy_type).toBe("no-proxy"); |
165 | + expect(enableProxyField.attr("value")).toBe("False"); |
166 | + expect(httpProxyField.attr("value")).toBe(undefined); |
167 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
168 | + }); |
169 | + |
170 | + it("no-proxy with http_proxy set", function() { |
171 | + enableHttpProxy.value = false; |
172 | + usePeerProxy.value = false; |
173 | + httpProxy.value = 'http://proxy.example.com/'; |
174 | + var directive = compileDirective( |
175 | + '<maas-proxy-settings></maas-proxy-settings>'); |
176 | + var scope = directive.isolateScope(); |
177 | + var enableProxyField = angular.element(directive.find( |
178 | + "#id_proxy-enable_http_proxy")); |
179 | + var httpProxyField = angular.element(directive.find( |
180 | + "#id_proxy-http_proxy")); |
181 | + var usePeerProxyField = angular.element(directive.find( |
182 | + "#id_proxy-use_peer_proxy")); |
183 | + expect(scope.proxy_type).toBe("no-proxy"); |
184 | + expect(enableProxyField.attr("value")).toBe("False"); |
185 | + expect(httpProxyField.attr("value")).toBe(undefined); |
186 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
187 | + }); |
188 | + |
189 | + it("no-proxy with use_peer_proxy set", function() { |
190 | + enableHttpProxy.value = false; |
191 | + usePeerProxy.value = true; |
192 | + httpProxy.value = 'http://peer-proxy.example.com/'; |
193 | + var directive = compileDirective( |
194 | + '<maas-proxy-settings></maas-proxy-settings>'); |
195 | + var scope = directive.isolateScope(); |
196 | + var enableProxyField = angular.element(directive.find( |
197 | + "#id_proxy-enable_http_proxy")); |
198 | + var httpProxyField = angular.element(directive.find( |
199 | + "#id_proxy-http_proxy")); |
200 | + var usePeerProxyField = angular.element(directive.find( |
201 | + "#id_proxy-use_peer_proxy")); |
202 | + expect(scope.proxy_type).toBe("no-proxy"); |
203 | + expect(enableProxyField.attr("value")).toBe("False"); |
204 | + expect(httpProxyField.attr("value")).toBe(undefined); |
205 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
206 | + }); |
207 | + |
208 | + it("builtin-proxy", function() { |
209 | + enableHttpProxy.value = true; |
210 | + usePeerProxy.value = false; |
211 | + httpProxy.value = ''; |
212 | + var directive = compileDirective( |
213 | + '<maas-proxy-settings></maas-proxy-settings>'); |
214 | + var scope = directive.isolateScope(); |
215 | + var enableProxyField = angular.element(directive.find( |
216 | + "#id_proxy-enable_http_proxy")); |
217 | + var httpProxyField = angular.element(directive.find( |
218 | + "#id_proxy-http_proxy")); |
219 | + var usePeerProxyField = angular.element(directive.find( |
220 | + "#id_proxy-use_peer_proxy")); |
221 | + expect(scope.proxy_type).toBe("builtin-proxy"); |
222 | + expect(enableProxyField.attr("value")).toBe("True"); |
223 | + expect(httpProxyField.attr("value")).toBe(undefined); |
224 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
225 | + }); |
226 | + |
227 | + it("builtin-proxy with use_peer_proxy set", function() { |
228 | + enableHttpProxy.value = true; |
229 | + usePeerProxy.value = true; |
230 | + httpProxy.value = ''; |
231 | + var directive = compileDirective( |
232 | + '<maas-proxy-settings></maas-proxy-settings>'); |
233 | + var scope = directive.isolateScope(); |
234 | + var enableProxyField = angular.element(directive.find( |
235 | + "#id_proxy-enable_http_proxy")); |
236 | + var httpProxyField = angular.element(directive.find( |
237 | + "#id_proxy-http_proxy")); |
238 | + var usePeerProxyField = angular.element(directive.find( |
239 | + "#id_proxy-use_peer_proxy")); |
240 | + expect(scope.proxy_type).toBe("builtin-proxy"); |
241 | + expect(enableProxyField.attr("value")).toBe("True"); |
242 | + expect(httpProxyField.attr("value")).toBe(undefined); |
243 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
244 | + }); |
245 | + |
246 | + it("external-proxy set", function() { |
247 | + enableHttpProxy.value = true; |
248 | + usePeerProxy.value = false; |
249 | + httpProxy.value = 'http://proxy.example.com/'; |
250 | + var directive = compileDirective( |
251 | + '<maas-proxy-settings></maas-proxy-settings>'); |
252 | + var scope = directive.isolateScope(); |
253 | + var enableProxyField = angular.element(directive.find( |
254 | + "#id_proxy-enable_http_proxy")); |
255 | + var httpProxyField = angular.element(directive.find( |
256 | + "#id_proxy-http_proxy")); |
257 | + var usePeerProxyField = angular.element(directive.find( |
258 | + "#id_proxy-use_peer_proxy")); |
259 | + expect(scope.proxy_type).toBe("external-proxy"); |
260 | + expect(enableProxyField.attr("value")).toBe("True"); |
261 | + expect(httpProxyField.attr("value")).toBe("http://proxy.example.com/"); |
262 | + expect(usePeerProxyField.attr("value")).toBe("False"); |
263 | + }); |
264 | + |
265 | + it("peer-proxy set", function() { |
266 | + enableHttpProxy.value = true; |
267 | + usePeerProxy.value = true; |
268 | + httpProxy.value = 'http://proxy.example.com/'; |
269 | + var directive = compileDirective( |
270 | + '<maas-proxy-settings></maas-proxy-settings>'); |
271 | + var scope = directive.isolateScope(); |
272 | + var enableProxyField = angular.element(directive.find( |
273 | + "#id_proxy-enable_http_proxy")); |
274 | + var httpProxyField = angular.element(directive.find( |
275 | + "#id_proxy-http_proxy")); |
276 | + var usePeerProxyField = angular.element(directive.find( |
277 | + "#id_proxy-use_peer_proxy")); |
278 | + expect(scope.proxy_type).toBe("peer-proxy"); |
279 | + expect(enableProxyField.attr("value")).toBe("True"); |
280 | + expect(httpProxyField.attr("value")).toBe("http://proxy.example.com/"); |
281 | + expect(usePeerProxyField.attr("value")).toBe("True"); |
282 | + }); |
283 | +}); |
284 | diff --git a/src/maasserver/static/partials/proxy-settings.html b/src/maasserver/static/partials/proxy-settings.html |
285 | new file mode 100644 |
286 | index 0000000..a3ee21b |
287 | --- /dev/null |
288 | +++ b/src/maasserver/static/partials/proxy-settings.html |
289 | @@ -0,0 +1,48 @@ |
290 | +<li class="help-msg"> |
291 | +<div> |
292 | + <label>HTTP proxy used by MAAS to download images, and by provisioned machines for APT packages.</label> |
293 | +</div> |
294 | +<div> |
295 | + <input type="radio" ng-model="proxy_type" name="maas_proxy" |
296 | + id="maas_no_proxy" value="no-proxy"> |
297 | + <label for="maas_no_proxy">Don't use a proxy</label> |
298 | +</div> |
299 | +<div> |
300 | + <input type="radio" ng-model="proxy_type" name="maas_proxy" |
301 | + id="maas_builtin_proxy" value="builtin-proxy"> |
302 | + <label for="maas_builtin_proxy">MAAS Built-in</label> |
303 | +</div> |
304 | +<div> |
305 | + <input type="radio" ng-model="proxy_type" name="maas_proxy" id="maas_external_proxy" value="external-proxy"> |
306 | + <label for="maas_external_proxy">External</label> |
307 | + <input type="url" ng-if="proxy_type == 'external-proxy'" |
308 | + id="id_proxy-http_proxy" name="proxy-http_proxy" |
309 | + ng-model="httpProxy.value" value="{$ httpProxy.value $}"> |
310 | + <span ng-if="proxy_type == 'external-proxy'" class="help u-display--block"> |
311 | + <small> |
312 | + Enter the external proxy URL MAAS will use to download images and |
313 | + machines to download APT packages. |
314 | + </small> |
315 | + </span> |
316 | +</div> |
317 | +<div> |
318 | + <input type="radio" ng-model="proxy_type" name="maas_proxy" id="maas_peer_proxy" value="peer-proxy"> |
319 | + <label for="maas_peer_proxy">Peer</label> |
320 | + <input type="url" ng-if="proxy_type == 'peer-proxy'" |
321 | + id="id_proxy-http_proxy" name="proxy-http_proxy" |
322 | + ng-model="httpProxy.value" value="{$ httpProxy.value $}"> |
323 | + <span ng-if="proxy_type == 'peer-proxy'" class="help u-display--block"> |
324 | + <small> |
325 | + Enter the external proxy URL that the MAAS built-in proxy will use |
326 | + as an upstream cache peer. Machines will be configured to use MAAS' |
327 | + built-in proxy to download APT packages. |
328 | + </small> |
329 | + </span> |
330 | +</div> |
331 | +<input type="hidden" id="id_proxy-enable_http_proxy" |
332 | + name="proxy-enable_http_proxy" |
333 | + value="{$ proxy_type == 'no-proxy' ? 'False' : 'True' $}" > |
334 | +<input type="hidden" id="id_proxy-use_peer_proxy" |
335 | + name="proxy-use_peer_proxy" |
336 | + value="{$ proxy_type == 'peer-proxy' ? 'True' : 'False' $}" > |
337 | +</li> |
338 | diff --git a/src/maasserver/templates/maasserver/settings.html b/src/maasserver/templates/maasserver/settings.html |
339 | index 9c82b3d..2f87f22 100644 |
340 | --- a/src/maasserver/templates/maasserver/settings.html |
341 | +++ b/src/maasserver/templates/maasserver/settings.html |
342 | @@ -5,6 +5,8 @@ |
343 | {% block title %}Settings{% endblock %} |
344 | {% block page-title %}Settings{% endblock %} |
345 | |
346 | +{% block ng-app %}data-ng-app="MAAS"{% endblock %} |
347 | + |
348 | {% block head %} |
349 | {% endblock %} |
350 | |
351 | @@ -157,14 +159,46 @@ |
352 | </div> |
353 | </div> |
354 | <div class="eight-col u-border--bottom"> |
355 | - <div id="network" class="eight-col"> |
356 | - <h2>Network Configuration</h2> |
357 | + <div id="proxy" class="eight-col"> |
358 | + <h2>Proxy</h2> |
359 | + <span class="u-text--loading" data-ng-if="loading"><i class="icon icon--loading u-animation--spin"></i> Loading...</span> |
360 | + |
361 | + <form action="{% url 'settings' %}" method="post"> |
362 | + {% csrf_token %} |
363 | + <ul> |
364 | + <maas-proxy-settings data-ng-if="!loading"></maas-proxy-settings> |
365 | + </ul> |
366 | + <input type="hidden" name="proxy_submit" value="1" /> |
367 | + <button type="submit" class="button--positive button--inline u-float--right">Save</button> |
368 | + </form> |
369 | + </div> |
370 | + </div> |
371 | + <div class="eight-col u-border--bottom"> |
372 | + <div id="dns" class="eight-col"> |
373 | + <h2>DNS</h2> |
374 | + <form action="{% url 'settings' %}" method="post"> |
375 | + {% csrf_token %} |
376 | + <ul> |
377 | + {% for field in dns_form %} |
378 | + {% include "maasserver/form_field.html" %} |
379 | + {% endfor %} |
380 | + </ul> |
381 | + <input type="hidden" name="dns_submit" value="1" /> |
382 | + <button type="submit" class="button--positive button--inline u-float--right">Save</button> |
383 | + </form> |
384 | + </div> |
385 | + </div> |
386 | + <div class="eight-col u-border--bottom"> |
387 | + <div id="ntp" class="eight-col"> |
388 | + <h2>NTP</h2> |
389 | <form action="{% url 'settings' %}" method="post"> |
390 | {% csrf_token %} |
391 | <ul> |
392 | - {% for field in network_form %} {% include "maasserver/form_field.html" %} {% endfor %} |
393 | + {% for field in ntp_form %} |
394 | + {% include "maasserver/form_field.html" %} |
395 | + {% endfor %} |
396 | </ul> |
397 | - <input type="hidden" name="network_submit" value="1" /> |
398 | + <input type="hidden" name="ntp_submit" value="1" /> |
399 | <button type="submit" class="button--positive button--inline u-float--right">Save</button> |
400 | </form> |
401 | </div> |
402 | diff --git a/src/maasserver/views/combo.py b/src/maasserver/views/combo.py |
403 | index b1d6615..55e2d2d 100644 |
404 | --- a/src/maasserver/views/combo.py |
405 | +++ b/src/maasserver/views/combo.py |
406 | @@ -119,6 +119,7 @@ MERGE_VIEWS = { |
407 | "js/angular/directives/placeholder.js", |
408 | "js/angular/directives/pod_parameters.js", |
409 | "js/angular/directives/power_parameters.js", |
410 | + "js/angular/directives/proxy_settings.js", |
411 | "js/angular/directives/release_name.js", |
412 | "js/angular/directives/release_options.js", |
413 | "js/angular/directives/script_select.js", |
414 | diff --git a/src/maasserver/views/settings.py b/src/maasserver/views/settings.py |
415 | index 2a410fa..6549d34 100644 |
416 | --- a/src/maasserver/views/settings.py |
417 | +++ b/src/maasserver/views/settings.py |
418 | @@ -33,12 +33,14 @@ from maasserver.exceptions import CannotDeleteUserException |
419 | from maasserver.forms import ( |
420 | CommissioningForm, |
421 | DeployForm, |
422 | + DNSForm, |
423 | EditUserForm, |
424 | GlobalKernelOptsForm, |
425 | MAASForm, |
426 | NetworkDiscoveryForm, |
427 | - NetworkForm, |
428 | NewUserCreationForm, |
429 | + NTPForm, |
430 | + ProxyForm, |
431 | StorageSettingsForm, |
432 | ThirdPartyDriversForm, |
433 | UbuntuForm, |
434 | @@ -211,8 +213,22 @@ def settings(request): |
435 | return response |
436 | |
437 | # Process the network form. |
438 | - network_form, response = process_form( |
439 | - request, NetworkForm, reverse('settings'), 'network', |
440 | + proxy_form, response = process_form( |
441 | + request, ProxyForm, reverse('settings'), 'proxy', |
442 | + "Configuration updated.") |
443 | + if response is not None: |
444 | + return response |
445 | + |
446 | + # Process the DNS form. |
447 | + dns_form, response = process_form( |
448 | + request, DNSForm, reverse('settings'), 'dns', |
449 | + "Configuration updated.") |
450 | + if response is not None: |
451 | + return response |
452 | + |
453 | + # Process the NTP form. |
454 | + ntp_form, response = process_form( |
455 | + request, NTPForm, reverse('settings'), 'ntp', |
456 | "Configuration updated.") |
457 | if response is not None: |
458 | return response |
459 | @@ -279,7 +295,9 @@ def settings(request): |
460 | 'show_license_keys': show_license_keys, |
461 | 'license_keys': license_keys, |
462 | 'maas_form': maas_form, |
463 | - 'network_form': network_form, |
464 | + 'proxy_form': proxy_form, |
465 | + 'dns_form': dns_form, |
466 | + 'ntp_form': ntp_form, |
467 | 'network_discovery_form': network_discovery_form, |
468 | 'third_party_drivers_form': third_party_drivers_form, |
469 | 'storage_settings_form': storage_settings_form, |
470 | diff --git a/src/maasserver/views/tests/test_settings.py b/src/maasserver/views/tests/test_settings.py |
471 | index 1f6a941..c7ba9b0 100644 |
472 | --- a/src/maasserver/views/tests/test_settings.py |
473 | +++ b/src/maasserver/views/tests/test_settings.py |
474 | @@ -107,7 +107,7 @@ class SettingsTest(MAASServerTestCase): |
475 | self.assertEqual( |
476 | new_name, Config.objects.get_config('maas_name')) |
477 | |
478 | - def test_settings_network_POST(self): |
479 | + def test_proxy_proxy_POST(self): |
480 | # Disable boot source cache signals. |
481 | self.addCleanup(bootsources.signals.enable) |
482 | bootsources.signals.disable() |
483 | @@ -116,13 +116,56 @@ class SettingsTest(MAASServerTestCase): |
484 | response = self.client.post( |
485 | reverse('settings'), |
486 | get_prefixed_form_data( |
487 | - prefix='network', |
488 | + prefix='proxy', |
489 | data={ |
490 | 'http_proxy': new_proxy, |
491 | + 'enable_http_proxy': True, |
492 | + 'use_peer_proxy': True, |
493 | })) |
494 | self.assertEqual( |
495 | http.client.FOUND, response.status_code, response.content) |
496 | self.assertEqual(new_proxy, Config.objects.get_config('http_proxy')) |
497 | + self.assertTrue(Config.objects.get_config('enable_http_proxy')) |
498 | + self.assertTrue(Config.objects.get_config('use_peer_proxy')) |
499 | + |
500 | + def test_settings_dns_POST(self): |
501 | + # Disable boot source cache signals. |
502 | + self.addCleanup(bootsources.signals.enable) |
503 | + bootsources.signals.disable() |
504 | + self.client_log_in(as_admin=True) |
505 | + new_upstream = "8.8.8.8" |
506 | + response = self.client.post( |
507 | + reverse('settings'), |
508 | + get_prefixed_form_data( |
509 | + prefix='dns', |
510 | + data={ |
511 | + 'upstream_dns': new_upstream, |
512 | + 'dnssec_validation': 'no', |
513 | + })) |
514 | + self.assertEqual( |
515 | + http.client.FOUND, response.status_code, response.content) |
516 | + self.assertEqual( |
517 | + new_upstream, Config.objects.get_config('upstream_dns')) |
518 | + self.assertEqual('no', Config.objects.get_config('dnssec_validation')) |
519 | + |
520 | + def test_settings_ntp_POST(self): |
521 | + # Disable boot source cache signals. |
522 | + self.addCleanup(bootsources.signals.enable) |
523 | + bootsources.signals.disable() |
524 | + self.client_log_in(as_admin=True) |
525 | + new_servers = "ntp.example.com" |
526 | + response = self.client.post( |
527 | + reverse('settings'), |
528 | + get_prefixed_form_data( |
529 | + prefix='ntp', |
530 | + data={ |
531 | + 'ntp_servers': new_servers, |
532 | + 'ntp_external_only': True, |
533 | + })) |
534 | + self.assertEqual( |
535 | + http.client.FOUND, response.status_code, response.content) |
536 | + self.assertEqual(new_servers, Config.objects.get_config('ntp_servers')) |
537 | + self.assertTrue(Config.objects.get_config('ntp_external_only')) |
538 | |
539 | def test_settings_commissioning_POST(self): |
540 | self.client_log_in(as_admin=True) |
541 | diff --git a/src/maastesting/karma.conf.js b/src/maastesting/karma.conf.js |
542 | index 66fe913..33e5f5f 100644 |
543 | --- a/src/maastesting/karma.conf.js |
544 | +++ b/src/maastesting/karma.conf.js |
545 | @@ -24,7 +24,8 @@ module.exports = function(config) { |
546 | '../../src/maasserver/static/js/angular/maas.js', |
547 | '../../src/maasserver/static/js/angular/testing/*.js', |
548 | '../../src/maasserver/static/js/angular/*/*.js', |
549 | - '../../src/maasserver/static/js/angular/*/tests/test_*.js' |
550 | + '../../src/maasserver/static/js/angular/*/tests/test_*.js', |
551 | + '../../src/maasserver/static/partials/*.html' |
552 | ], |
553 | |
554 | |
555 | @@ -36,8 +37,17 @@ module.exports = function(config) { |
556 | // preprocess matching files before serving them to the browser |
557 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor |
558 | preprocessors: { |
559 | + '../../src/maasserver/static/partials/*.html': ['ng-html2js'] |
560 | }, |
561 | |
562 | + ngHtml2JsPreprocessor: { |
563 | + // If your build process changes the path to your templates, |
564 | + // use stripPrefix and prependPrefix to adjust it. |
565 | + stripPrefix: ".*src/maasserver/", |
566 | + |
567 | + // the name of the Angular module to create |
568 | + moduleName: 'MAAS.templates' |
569 | + }, |
570 | |
571 | // test results reporter to use |
572 | // possible values: 'dots', 'progress' |
573 | @@ -79,7 +89,8 @@ module.exports = function(config) { |
574 | 'karma-firefox-launcher', |
575 | 'karma-opera-launcher', |
576 | 'karma-phantomjs-launcher', |
577 | - 'karma-failed-reporter' |
578 | + 'karma-failed-reporter', |
579 | + 'karma-ng-html2js-preprocessor' |
580 | ] |
581 | }); |
582 | }; |
I really like splitting NTP and DNS into different sections, it makes the page much easier to read. I think we may want to use a drop down to select the proxy mode. The text field would be disabled for don't use and built-in. I'd ask Maria from design this before reworking incase I'm wrong.
I poked around and can't figure out why MAAS.templates is currently broken and wasn't able to come up with anything, Blake might know.