Merge ~caleb-ellis/maas:deploy-in-table into maas:master

Proposed by Caleb Ellis
Status: Merged
Approved by: Caleb Ellis
Approved revision: 2d2239f136ea777b86dcbb1c7fc31f4a27c97be7
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~caleb-ellis/maas:deploy-in-table
Merge into: maas:master
Diff against target: 241 lines (+81/-23)
4 files modified
src/maasserver/static/js/angular/directives/machines_table.js (+25/-3)
src/maasserver/static/js/angular/directives/tests/test_machines_table.js (+45/-9)
src/maasserver/static/partials/machines-table.html (+10/-10)
src/maasserver/static/partials/pod-details.html (+1/-1)
Reviewer Review Type Date Requested Status
Lee Trager (community) Approve
Andres Rodriguez (community) Needs Information
Anthony Dillon Approve
Blake Rouse Pending
Review via email: mp+365793@code.launchpad.net

Commit message

LP: #1825143 - Display default OS/release deployment in in-table action menu

Description of the change

## Done
- Display default OS/release deployment in in-table action menu
- Removed in-table actions from pod details page (was causing errors if refreshing the browser at this page, because not all the machine data is passed through in this view alone)

## QA
- Check that deploying a machine has the correct default OS and release selected

## Screenshot
https://user-images.githubusercontent.com/25733845/55886580-f0d81280-5ba3-11e9-9882-67771d200656.png

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

This is not a review, but just a quick question, shouldn't the backend be doing a failsafe in which if the UI doesn't send this info, its already set? Or is the issue because the UI is setting blank fields and sending blank fields causes this?

Revision history for this message
Caleb Ellis (caleb-ellis) wrote :

I don't believe the backend falls back on inferring os/release from defaults if none are provided to the deploy method, so the issue was originally that these were not provided by the in-table deploy action (which I've added in this MP).

Revision history for this message
Anthony Dillon (ya-bo-ng) wrote :

Code and QA looks good to me. +1

review: Approve
Revision history for this message
Lee Trager (ltrager) wrote :

This is actually a backend error. What happened is the UI asked the region to deploy over the websocket and didn't specify an osystem or distro series. The osystem and distro series are both set to '' which the UI shows as /. I've posted a fix[1] to the websocket so a osystem and distro series are always set, like the API.

[1] https://code.launchpad.net/~ltrager/maas/+git/maas/+merge/366158

review: Disapprove
Revision history for this message
Caleb Ellis (caleb-ellis) wrote :

Fair enough - I can remove the part where default params are passed to the deploy method via the UI, but I think displaying the default os/release in the menu is still helpful to the user.

Revision history for this message
Andres Rodriguez (andreserl) wrote :

is The commit message still valid? Since Lee has submitted a branch to fix this in the backend I don’t understand why this would be relevant for the UI anymore?

review: Needs Information
Revision history for this message
Caleb Ellis (caleb-ellis) wrote :

This branch is simply just to change the text from "Deploy..." to e.g "Deploy Ubuntu 18.04..." - not the most urgent, but the work's already done so why not have the UI nicety?

Revision history for this message
Andres Rodriguez (andreserl) wrote :

Caleb,

Maybe I’m missing something but i thought the UI already does show the OS being deployed?

Revision history for this message
Andres Rodriguez (andreserl) wrote :

In fact it’s always shown it?

Revision history for this message
Caleb Ellis (caleb-ellis) wrote :

You're right it does in the main action menu dropdown when you choose deploy, and in the status message, but it doesn't for the in-table action.

Revision history for this message
Andres Rodriguez (andreserl) wrote :

So just to confirm, if for whatever reason the OS is set to other than not default, the in table action would show that ? E.g. the machine does have a node.os field which could be forced to something different than the default, and would deploying that show it?

review: Needs Information
Revision history for this message
Caleb Ellis (caleb-ellis) wrote :

The in-table deploy action only displays whatever is set as default in settings. If you wanted to deploy a machine using non-default os/release you would have to do that via the top-right action menu that shows the different dropdowns for os/release/kernel. The only visible difference in this MP is that "Deploy..." becomes "Deploy {{ default_os/default_release }}..."

Revision history for this message
Lee Trager (ltrager) wrote :

Thanks for the update and the explanation. This LGTM!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
~caleb-ellis/maas:deploy-in-table updated
2d2239f... by Caleb Ellis

fix tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/static/js/angular/directives/machines_table.js b/src/maasserver/static/js/angular/directives/machines_table.js
2index 710d9ea..672fb66 100644
3--- a/src/maasserver/static/js/angular/directives/machines_table.js
4+++ b/src/maasserver/static/js/angular/directives/machines_table.js
5@@ -18,7 +18,7 @@ function maasMachinesTable(
6 actionOption: "=",
7 ngDisabled: "&",
8 machineHasError: "&",
9- hideCheckboxes: "=?",
10+ hideActions: "=?",
11 onListingChange: "&",
12 onCheckAll: "&",
13 onCheck: "=",
14@@ -71,7 +71,8 @@ function maasMachinesTable(
15 allViewableChecked: false,
16 machines,
17 filteredMachines: machines,
18- osinfo: GeneralManager.getData("osinfo")
19+ osinfo: GeneralManager.getData("osinfo"),
20+ machineActions: GeneralManager.getData("machine_actions")
21 };
22
23 $scope.statusMenuActions = [
24@@ -584,7 +585,28 @@ function maasMachinesTable(
25 };
26
27 $scope.getActionTitle = actionName => {
28- const machineActions = GeneralManager.getData('machine_actions');
29+ const { table } = $scope;
30+ const { machineActions, osinfo } = table;
31+
32+ // Display default OS and release if in-table action is "deploy"
33+ if (actionName === "deploy" && osinfo) {
34+ const {
35+ osystems,
36+ releases,
37+ default_osystem,
38+ default_release
39+ } = osinfo;
40+ const os = osystems && osystems.find(os => os[0] === default_osystem);
41+ const release = releases && releases.find(
42+ release => release[0] === `${default_osystem}/${default_release}`
43+ );
44+ if (os && release) {
45+ return `Deploy ${os[1]} ${release[1]}...`;
46+ }
47+ return `Deploy ${default_osystem}/${default_release}...`;
48+ }
49+
50+ // Otherwise, just display the action's title
51 if (machineActions.length) {
52 return machineActions
53 .find(action => action.name === actionName)
54diff --git a/src/maasserver/static/js/angular/directives/tests/test_machines_table.js b/src/maasserver/static/js/angular/directives/tests/test_machines_table.js
55index a7dd821..c1e7f2b 100644
56--- a/src/maasserver/static/js/angular/directives/tests/test_machines_table.js
57+++ b/src/maasserver/static/js/angular/directives/tests/test_machines_table.js
58@@ -46,6 +46,19 @@ describe("maasMachinesTable", function() {
59 return machine;
60 }
61
62+ // Make OS choice.
63+ function makeOS() {
64+ const name = makeName("os");
65+ return [name, name.toUpperCase()];
66+ }
67+
68+ // Make release choice for OS.
69+ function makeRelease(os) {
70+ const release = makeName("release");
71+ const osRelease = os[0] + "/" + release;
72+ return [osRelease, release];
73+ }
74+
75 // Return the compiled directive with the items from the scope.
76 function compileDirective(design) {
77 var directive;
78@@ -78,7 +91,8 @@ describe("maasMachinesTable", function() {
79 allViewableChecked: false,
80 machines: MachinesManager.getItems(),
81 filteredMachines: MachinesManager.getItems(),
82- osinfo: GeneralManager.getData("osinfo")
83+ osinfo: GeneralManager.getData("osinfo"),
84+ machineActions: GeneralManager.getData("machine_actions")
85 });
86 expect(scope.table.machines).toBe(MachinesManager.getItems());
87 });
88@@ -764,16 +778,38 @@ describe("maasMachinesTable", function() {
89 it("returns the correct action title, given an action name", () => {
90 const directive = compileDirective();
91 const scope = directive.isolateScope();
92- const actions = [
93- { title: "this action title", name: "this_action" },
94- { title: "other action title", name: "other_action" }
95- ];
96+ scope.table = {
97+ machineActions: [
98+ { title: "this action title", name: "this_action" },
99+ { title: "other action title", name: "other_action" }
100+ ]
101+ };
102
103- spyOn(GeneralManager, "getData")
104- .and.returnValue(actions);
105+ expect(scope.getActionTitle(scope.table.machineActions[0].name))
106+ .toEqual(scope.table.machineActions[0].title);
107+ });
108+
109+ it("returns the default OS and release if action is 'deploy'", () => {
110+ const directive = compileDirective();
111+ const scope = directive.isolateScope();
112+ const [defaultOS, otherOS] = [makeOS(), makeOS()];
113+ const [defaultRelease, otherRelease]
114+ = [makeRelease(defaultOS), makeRelease(otherOS)];
115+
116+ scope.table = {
117+ osinfo: {
118+ default_osystem: defaultOS[0],
119+ default_release: defaultRelease[0].split("/")[1],
120+ osystems: [defaultOS, otherOS],
121+ releases: [defaultRelease, otherRelease]
122+ },
123+ machineActions: [
124+ { title: "Deploy...", name: "deploy" }
125+ ]
126+ };
127
128- expect(scope.getActionTitle(actions[0].name))
129- .toEqual(actions[0].title);
130+ expect(scope.getActionTitle("deploy"))
131+ .toEqual(`Deploy ${defaultOS[1]} ${defaultRelease[1]}...`);
132 });
133 });
134
135diff --git a/src/maasserver/static/partials/machines-table.html b/src/maasserver/static/partials/machines-table.html
136index 16a1748..abd1366 100644
137--- a/src/maasserver/static/partials/machines-table.html
138+++ b/src/maasserver/static/partials/machines-table.html
139@@ -2,7 +2,7 @@
140 <thead>
141 <tr class="p-table__header p-table__row" data-ng-if="$first">
142 <th class="p-table__col--name p-double-row u-align--left">
143- <div class="p-double-row__checkbox" data-ng-if="!hideCheckboxes">
144+ <div class="p-double-row__checkbox" data-ng-if="!hideActions">
145 <input class="checkbox" type="checkbox" data-ng-click="toggleCheckAll()" data-ng-checked="table.allViewableChecked" id="check-all" data-ng-disabled="ngDisabled()" />
146 <label class="p-checkbox--action" for="check-all" ng-class="getAllCheckboxClass(table.filteredMachines)"></label>
147 </div>
148@@ -73,7 +73,7 @@
149 'is-grouped': group.label !== 'none'
150 }">
151 <td class="p-table__col--name p-double-row" aria-label="FQDN" data-ng-if="table.column === 'fqdn' || table.column === 'ip_address'">
152- <div class="p-double-row__checkbox" data-ng-if="!hideCheckboxes">
153+ <div class="p-double-row__checkbox" data-ng-if="!hideActions">
154 <input type="checkbox" data-ng-click="toggleChecked(node)" data-ng-checked="node.$selected" id="{$ node.fqdn $}" data-ng-disabled="ngDisable()" />
155 <label class="p-checkbox--action" for="{$ node.fqdn $}" ng-class="getCheckboxClass(node)"></label>
156 </div>
157@@ -101,7 +101,7 @@
158 </div>
159 </td>
160 <td class="p-table__col--name" aria-label="MAC" data-ng-if="table.column === 'pxe_mac'">
161- <div class="u-float--left" data-ng-if="!hideCheckboxes">
162+ <div class="u-float--left" data-ng-if="!hideActions">
163 <input class="checkbox" type="checkbox" data-ng-click="toggleChecked(node)" data-ng-checked="node.$selected" id="{$ node.fqdn $}" data-ng-disabled="ngDisable()" />
164 <label class="p-checkbox--action checkbox-label" for="{$ node.fqdn $}" ng-class="getCheckboxClass(node)"></label>
165 </div>
166@@ -110,7 +110,7 @@
167 </td>
168 <td class="p-table__col--power p-double-row" aria-label="Power state">
169 <span class="p-table-menu">
170- <div data-ng-click="toggleMenu(node.system_id + '-power')" class="p-double-row__icon-container">
171+ <div data-ng-click="!hideActions && toggleMenu(node.system_id + '-power')" class="p-double-row__icon-container">
172 <i
173 title="{$ node.power_state $}"
174 data-ng-class="{
175@@ -131,7 +131,7 @@
176 <span title="{$ node.power_type $}">{$ node.power_type $}</span>
177 </div>
178 </div>
179- <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br3" data-ng-click="toggleMenu(node.system_id + '-power')"></button>
180+ <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br3" data-ng-click="toggleMenu(node.system_id + '-power')" data-ng-if="!hideActions"></button>
181 <span class="p-table-menu__dropdown" data-ng-show="openMenu === node.system_id + '-power'" data-ng-if="!node.powerTransition">
182 <div class="p-table-menu__title--icon">Take action:</div>
183 <button
184@@ -167,7 +167,7 @@
185 </td>
186 <td class="p-table__col--status p-double-row" aria-label="Status, Events" title="{$ getStatusText(node) $}">
187 <span class="p-table-menu">
188- <div class="p-double-row__icon-container" data-ng-click="toggleMenu(node.system_id + '-status')">
189+ <div class="p-double-row__icon-container" data-ng-click="!hideActions && toggleMenu(node.system_id + '-status')">
190 <i data-ng-if="showSpinner(node)" class="p-icon--spinner u-animation--spin"></i>
191 <i data-ng-if="showNodeStatus(node)" data-maas-script-status="script-status" data-script-status="node.other_test_status" aria-label="{$ node.other_test_status_tooltip $}"></i>
192 <span class="p-tooltip p-tooltip--top-left" data-ng-if="showFailedTestWarning(node)">
193@@ -184,7 +184,7 @@
194 <span>{$ getStatusMessage(node) $}</span>
195 </div>
196 </div>
197- <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br3" data-ng-click="toggleMenu(node.system_id + '-status')"></button>
198+ <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br3" data-ng-click="toggleMenu(node.system_id + '-status')" data-ng-if="!hideActions"></button>
199 <span class="p-table-menu__dropdown" data-ng-show="openMenu === node.system_id + '-status'">
200 <div class="p-table-menu__title">Take action:</div>
201 <div class="p-contextual-menu__group" data-ng-if="getStatusActions(node).length">
202@@ -225,7 +225,7 @@
203 <span>{$ node.tags.join(', ') $}</span>
204 </div>
205 </div>
206- <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br2" data-ng-click="toggleMenu(node.system_id + '-owner')"></button>
207+ <button class="p-table-menu__toggle p-icon--contextual-menu u-hide--br2" data-ng-click="toggleMenu(node.system_id + '-owner')" data-ng-if="!hideActions"></button>
208 <span class="p-table-menu__dropdown" data-ng-if="openMenu === node.system_id + '-owner'">
209 <div class="p-table-menu__title">Take action:</div>
210 <button
211@@ -266,7 +266,7 @@
212 </div>
213 </div>
214 <button
215- data-ng-if="node.actions.indexOf('set-pool') !== -1"
216+ data-ng-if="node.actions.indexOf('set-pool') !== -1 && !hideActions"
217 data-ng-click="toggleMenu(node.system_id + '-pool')"
218 class="p-table-menu__toggle p-icon--contextual-menu"
219 >
220@@ -301,7 +301,7 @@
221 </div>
222 </div>
223 <button
224- data-ng-if="node.actions.indexOf('set-zone') !== -1"
225+ data-ng-if="node.actions.indexOf('set-zone') !== -1 && !hideActions"
226 data-ng-click="toggleMenu(node.system_id + '-zone')"
227 class="p-table-menu__toggle p-icon--contextual-menu"
228 >
229diff --git a/src/maasserver/static/partials/pod-details.html b/src/maasserver/static/partials/pod-details.html
230index 6558e4a..bcfc763 100644
231--- a/src/maasserver/static/partials/pod-details.html
232+++ b/src/maasserver/static/partials/pod-details.html
233@@ -646,7 +646,7 @@
234 <section class="p-strip">
235 <div class="row">
236 <div class="col-12" data-ng-if="pod.composed_machines_count">
237- <maas-machines-table search="machinesSearch" hide-checkboxes="true" pools="pools" zones="zones"></maas-machines-table>
238+ <maas-machines-table search="machinesSearch" hide-actions="true" pools="pools" zones="zones"></maas-machines-table>
239 </div>
240 </div>
241 <div class="row">

Subscribers

People subscribed via source and target branches