Skip to content

Commit ae3560e

Browse files
author
Erwin Dondorp
committed
Also allow selection of keys and nodegroups
1 parent 9a2ff35 commit ae3560e

12 files changed

Lines changed: 524 additions & 144 deletions

File tree

docs/README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ We suggest to upgrade the SaltStack installation when you are still using a vers
4949
- Keyboard control to apply templates
5050
- Choose between live info and cached info for grains/pillar
5151
- View details of orchestrations and allow to start them
52-
- Act on multiple minions by first selecting them
52+
- Act on multiple minions/keys/nodegroups by first selecting them
5353

5454

5555
## Quick start using PAM as authentication method
@@ -401,12 +401,15 @@ Each issue has its own dropdown-menu, which typically contains:
401401
But note that there might be more possible solutions, some of which may actually be more preferred.
402402
* A navigation-command to go to a page for more details.
403403

404-
## Minion selection
404+
## Row selection
405405
Pages that show a simple list of minions allow individual minions to be selected.
406+
The Keys page allows individual keys to be selected.
407+
The NodeGroups page allows individual nodegroups and/or minions to be selected.
408+
406409
Use panel button [] to show an extra column with checkboxes in the table.
407-
Minions can be selected one-by-one or you can use select-all, select-none by clicking on the column header.
410+
Rows can be selected one-by-one or you can use select-all, select-none by clicking on the column header.
408411
The selection can be inverted by using CTRL-click.
409-
The list of selected minions will be used in the command-box and for commands from a panel-menu.
412+
The list of selected rows will be used in the command-box and for commands from a panel-menu.
410413
When the column is hidden, the selection-values are just ignored.
411414

412415
## Command documentation

saltgui/static/scripts/CommandBox.js

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -423,24 +423,89 @@ export class CommandBox {
423423
button.disabled = false;
424424
}
425425

426-
static getSelectedMinionList () {
426+
static _getNodegroupsSelection () {
427+
const allNodeGroups = Utils.getStorageItemObject("session", "nodegroups");
428+
const allNodeGroupsKeys = Object.keys(allNodeGroups);
429+
430+
let ret = "";
431+
const lst_nodegroups = Utils.getStorageItem("session", "select_nodegroups", null);
432+
if (lst_nodegroups) {
433+
for (const nodegroup of lst_nodegroups.split(",")) {
434+
if (nodegroup === "null") {
435+
ret += " or not("
436+
let grplst = "";
437+
for (const grp of allNodeGroupsKeys) {
438+
grplst += " or N@" + grp;
439+
}
440+
ret += grplst.substring(4) + ")";
441+
} else if (nodegroup) {
442+
ret += " or N@" + nodegroup;
443+
}
444+
}
445+
}
446+
return ret;
447+
}
448+
449+
static _getMinionSelection () {
450+
let ret = "";
451+
const lst_minions = Utils.getStorageItem("session", "select_minions", null);
452+
if (lst_minions) {
453+
let minionlist = "";
454+
for (const minion of lst_minions.split(",")) {
455+
if (minion) {
456+
minionlist += "," + minion;
457+
}
458+
}
459+
if (minionlist) {
460+
// substring removes the extra ","
461+
ret += " or L@" + minionlist.substring(1);
462+
}
463+
}
464+
return ret;
465+
}
466+
467+
static getSelectedItemList (pSessionKeys) {
427468
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
428469
if (!selectVisible) {
429470
return null;
430471
}
431472

432-
// only when the selection is visible
433-
const selectMinions = Utils.getStorageItem("session", "select_minions", "");
434-
const lst = selectMinions.split(",").sort();
435-
while (lst.length > 0 && lst[0] === "") {
436-
lst.shift();
473+
let target = "";
474+
475+
if (pSessionKeys.includes("select_nodegroups")) {
476+
target += CommandBox._getNodegroupsSelection();
437477
}
438-
// and only when there is a selection
439-
if (lst.length == 0) {
478+
479+
if (pSessionKeys.includes("select_minions")) {
480+
target += CommandBox._getMinionSelection();
481+
}
482+
483+
if (pSessionKeys.includes("select_keys")) {
484+
const lst_keys = Utils.getStorageItem("session", "select_keys", null);
485+
if (lst_keys) {
486+
let keylist = "";
487+
for (const key of lst_keys.split(",")) {
488+
if (key) {
489+
keylist += "," + key;
490+
}
491+
}
492+
// substring removes the extra ","
493+
target += " or " + keylist.substring(1);
494+
}
495+
}
496+
497+
// remove the extra " or "
498+
target = target.substring(4);
499+
if (target.startsWith("L@")) {
500+
// simplify when we only have the list of minions
501+
target = target.substring(2);
502+
}
503+
504+
if (target === "") {
440505
return null;
441506
}
442507

443-
return lst.join(",");
508+
return target;
444509
}
445510

446511
static showManualRun (pApi) {
@@ -498,7 +563,26 @@ export class CommandBox {
498563
CommandBox._populateTemplateTmplMenu();
499564
CommandBox._populateTestProviders(pApi);
500565

501-
const lst = CommandBox.getSelectedMinionList()
566+
let lst = null;
567+
// different pages have different selection-types
568+
// but run-command is available from every page
569+
switch (window.location.hash) {
570+
case "#minions":
571+
case "#grains":
572+
case "#schedules":
573+
case "#pillars":
574+
case "#beacons":
575+
case "#highstate":
576+
lst = CommandBox.getSelectedItemList(["select_minions"]);
577+
break;
578+
case "#keys":
579+
lst = CommandBox.getSelectedItemList(["select_keys"]);
580+
break;
581+
case "#nodegroups":
582+
lst = CommandBox.getSelectedItemList(["select_minions", "select_nodegroups"]);
583+
break;
584+
}
585+
502586
if (lst) {
503587
const targetField = document.getElementById("target");
504588
targetField.value = lst;

saltgui/static/scripts/panels/Beacons.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {Utils} from "../Utils.js";
66
export class BeaconsPanel extends Panel {
77

88
constructor () {
9-
super("beacons");
9+
super("beacons", ["select_minions"]);
1010

1111
this.addTitle("Beacons");
1212
this.addSearchButton();
@@ -18,12 +18,11 @@ export class BeaconsPanel extends Panel {
1818
}
1919

2020
onShow () {
21+
super.onShow();
22+
2123
const wheelKeyListAllPromise = this.api.getWheelKeyListAll();
2224
const localBeaconsListPromise = this.api.getLocalBeaconsList(null);
2325

24-
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
25-
this.showSelectColumn(selectVisible);
26-
2726
this.nrMinions = 0;
2827

2928
wheelKeyListAllPromise.then((pWheelKeyListAllData) => {
@@ -108,7 +107,7 @@ export class BeaconsPanel extends Panel {
108107
}
109108

110109
updateOfflineMinion (pMinionId, pMinionsDict) {
111-
super.updateOfflineMinion(pMinionId, pMinionsDict, true);
110+
super.updateOfflineMinion(pMinionId, pMinionsDict);
112111

113112
const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
114113

@@ -120,7 +119,7 @@ export class BeaconsPanel extends Panel {
120119

121120
pMinionData = BeaconsPanel.fixBeaconsMinion(pMinionData);
122121

123-
super.updateMinion(null, pMinionId, pAllMinionsGrains, true);
122+
super.updateMinion(null, pMinionId, pAllMinionsGrains);
124123

125124
const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
126125

saltgui/static/scripts/panels/Grains.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {Utils} from "../Utils.js";
77
export class GrainsPanel extends Panel {
88

99
constructor () {
10-
super("grains");
10+
super("grains", ["select_minions"]);
1111

1212
this.addTitle("Grains");
1313
this.addSearchButton();
@@ -27,8 +27,7 @@ export class GrainsPanel extends Panel {
2727
}
2828

2929
onShow () {
30-
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
31-
this.showSelectColumn(selectVisible);
30+
super.onShow();
3231

3332
if (this.previewColumsAdded !== true) {
3433
// collect the list of displayed extra grains
@@ -86,7 +85,7 @@ export class GrainsPanel extends Panel {
8685

8786
const minionIds = keys.minions.sort();
8887
for (const minionId of minionIds) {
89-
const minionTr = this.addMinion(minionId, true, this.previewGrains.length);
88+
const minionTr = this.addMinion(minionId, this.previewGrains.length);
9089

9190
// preliminary dropdown menu
9291
this._addMenuItemShowGrains(minionTr.dropdownmenu, minionId);
@@ -105,7 +104,7 @@ export class GrainsPanel extends Panel {
105104
}
106105

107106
updateOfflineMinion (pMinionId, pMinionsDict) {
108-
super.updateOfflineMinion(pMinionId, pMinionsDict, true);
107+
super.updateOfflineMinion(pMinionId, pMinionsDict);
109108

110109
const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
111110

@@ -119,7 +118,7 @@ export class GrainsPanel extends Panel {
119118
}
120119

121120
updateMinion (pMinionData, pMinionId, pAllMinionsGrains) {
122-
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains, true);
121+
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains);
123122

124123
const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
125124

saltgui/static/scripts/panels/HighState.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {Utils} from "../Utils.js";
1212
export class HighStatePanel extends Panel {
1313

1414
constructor () {
15-
super("highstate");
15+
super("highstate", ["select_minions"]);
1616

1717
// only consider this number of latest highstate jobs
1818
this._maxShowHighstates = Utils.getStorageItem("session", "max_show_highstates", 10);
@@ -47,10 +47,9 @@ export class HighStatePanel extends Panel {
4747
}
4848

4949
onShow () {
50-
const wheelKeyListAllPromise = this.api.getWheelKeyListAll();
50+
super.onShow();
5151

52-
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
53-
this.showSelectColumn(selectVisible);
52+
const wheelKeyListAllPromise = this.api.getWheelKeyListAll();
5453

5554
this.nrMinions = 0;
5655

@@ -100,14 +99,14 @@ export class HighStatePanel extends Panel {
10099
_addMenuItemStateApply (pMenu, pMinionId) {
101100
pMenu.addMenuItem("Apply state...", () => {
102101
const cmdArr = ["state.apply"];
103-
this.runCommand("", pMinionId, cmdArr, true);
102+
this.runCommand("", pMinionId, cmdArr, ["select_minions"]);
104103
});
105104
}
106105

107106
_addMenuItemStateApplyTest (pMenu, pMinionId) {
108107
pMenu.addMenuItem("Test state...", () => {
109108
const cmdArr = ["state.apply", "test=", true];
110-
this.runCommand("", pMinionId, cmdArr, true);
109+
this.runCommand("", pMinionId, cmdArr, ["select_minions"]);
111110
});
112111
}
113112

@@ -366,7 +365,7 @@ export class HighStatePanel extends Panel {
366365

367366
// we already have the TR
368367
// but this function also clears the row
369-
this.getElement(trId, true);
368+
this.getElement(trId, "select_minions", minionId);
370369

371370
// mark the TR as populated
372371
minionTr.jid = pJobId;

0 commit comments

Comments
 (0)