Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ We suggest to upgrade the SaltStack installation when you are still using a vers
- Keyboard control to apply templates
- Choose between live info and cached info for grains/pillar
- View details of orchestrations and allow to start them
- Act on multiple minions by first selecting them


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

## Minion selection
Pages that show a simple list of minions allow individual minions to be selected.
Use panel button [✔] to show an extra column with checkboxes in the table.
Minions can be selected one-by-one or you can use select-all, select-none by clicking on the column header.
The selection can be inverted by using CTRL-click.
The list of selected minions will be used in the command-box and for commands from a panel-menu.
When the column is hidden, the selection-values are just ignored.

## Command documentation

### Internal documentation
Expand Down
2 changes: 2 additions & 0 deletions saltgui/static/scripts/Character.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export class Character {
Character.WHITE_DOWN_POINTING_TRIANGLE = "\u25BD";
Character.BLACK_DIAMOND = "\u25C6";
Character.BLACK_CIRCLE = "\u25CF";
Character.BALLOT_BOX_UNCHECKED = "\u2610";
Character.BALLOT_BOX_WITH_CHECK = "\u2611";
Character.GEAR = "\u2699";
Character.WARNING_SIGN = "\u26A0" + Character._VARIATION_SELECTOR_16;
Character.HEAVY_CHECK_MARK = "\u2714";
Expand Down
27 changes: 27 additions & 0 deletions saltgui/static/scripts/CommandBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,26 @@ export class CommandBox {
button.disabled = false;
}

static getSelectedMinionList () {
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
if (!selectVisible) {
return null;
}

// only when the selection is visible
const selectMinions = Utils.getStorageItem("session", "select_minions", "");
const lst = selectMinions.split(",").sort();
while (lst.length > 0 && lst[0] === "") {
lst.shift();
}
// and only when there is a selection
if (lst.length == 0) {
return null;
}

return lst.join(",");
}

static showManualRun (pApi) {
const manualRun = document.getElementById("popup-run-command");
manualRun.style.display = "block";
Expand Down Expand Up @@ -477,6 +497,13 @@ export class CommandBox {
CommandBox._populateTemplateCatMenu();
CommandBox._populateTemplateTmplMenu();
CommandBox._populateTestProviders(pApi);

const lst = CommandBox.getSelectedMinionList()
if (lst) {
const targetField = document.getElementById("target");
targetField.value = lst;
TargetType.autoSelectTargetType(lst);
}
}

static _populateTestProviders (pApi) {
Expand Down
10 changes: 7 additions & 3 deletions saltgui/static/scripts/panels/Beacons.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export class BeaconsPanel extends Panel {

this.addTitle("Beacons");
this.addSearchButton();
this.addTable(["-menu-", "Minion", "Status", "Beacons"]);
this.addFilterButton();
this.addTable(["-select-", "-menu-", "Minion", "Status", "Beacons"]);
this.setTableSortable("Minion", "asc");
this.setTableClickable("page");
this.addMsg();
Expand All @@ -20,6 +21,9 @@ export class BeaconsPanel extends Panel {
const wheelKeyListAllPromise = this.api.getWheelKeyListAll();
const localBeaconsListPromise = this.api.getLocalBeaconsList(null);

const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
this.showSelectColumn(selectVisible);

this.nrMinions = 0;

wheelKeyListAllPromise.then((pWheelKeyListAllData) => {
Expand Down Expand Up @@ -104,7 +108,7 @@ export class BeaconsPanel extends Panel {
}

updateOfflineMinion (pMinionId, pMinionsDict) {
super.updateOfflineMinion(pMinionId, pMinionsDict);
super.updateOfflineMinion(pMinionId, pMinionsDict, true);

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

Expand All @@ -116,7 +120,7 @@ export class BeaconsPanel extends Panel {

pMinionData = BeaconsPanel.fixBeaconsMinion(pMinionData);

super.updateMinion(null, pMinionId, pAllMinionsGrains);
super.updateMinion(null, pMinionId, pAllMinionsGrains, true);

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

Expand Down
12 changes: 8 additions & 4 deletions saltgui/static/scripts/panels/Grains.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ export class GrainsPanel extends Panel {

this.addTitle("Grains");
this.addSearchButton();
this.addFilterButton();
this.addHelpButton([
"The content of specific well-known grains can be made visible in",
"columns by configuring their name in the server-side configuration file.",
"See README.md for more details."
]);
this.addWarningField();
this.addTable(["-menu-", "Minion", "Status", "Salt version", "OS version", "Grains"]);
this.addTable(["-select-", "-menu-", "Minion", "Status", "Salt version", "OS version", "Grains"]);

// cannot initialize sorting before all columns are present
// this.setTableSortable("Minion", "asc");
Expand All @@ -26,6 +27,9 @@ export class GrainsPanel extends Panel {
}

onShow () {
const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
this.showSelectColumn(selectVisible);

if (this.previewColumsAdded !== true) {
// collect the list of displayed extra grains
this.previewGrains = Utils.getStorageItemList("session", "preview_grains");
Expand Down Expand Up @@ -82,7 +86,7 @@ export class GrainsPanel extends Panel {

const minionIds = keys.minions.sort();
for (const minionId of minionIds) {
const minionTr = this.addMinion(minionId, this.previewGrains.length);
const minionTr = this.addMinion(minionId, true, this.previewGrains.length);

// preliminary dropdown menu
this._addMenuItemShowGrains(minionTr.dropdownmenu, minionId);
Expand All @@ -101,7 +105,7 @@ export class GrainsPanel extends Panel {
}

updateOfflineMinion (pMinionId, pMinionsDict) {
super.updateOfflineMinion(pMinionId, pMinionsDict);
super.updateOfflineMinion(pMinionId, pMinionsDict, true);

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

Expand All @@ -115,7 +119,7 @@ export class GrainsPanel extends Panel {
}

updateMinion (pMinionData, pMinionId, pAllMinionsGrains) {
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains);
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains, true);

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

Expand Down
12 changes: 8 additions & 4 deletions saltgui/static/scripts/panels/HighState.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class HighStatePanel extends Panel {
this._addMenuItemUseStateHighstate();
this._addMenuItemUseStateApply();
this.addSearchButton();
this.addFilterButton();
this.addPlayPauseButton();
this.addHelpButton([
"This panel shows the latest state.highstate or state.apply job for each minion.",
Expand All @@ -35,7 +36,7 @@ export class HighStatePanel extends Panel {
"Click on an individual state to re-apply only that state."
]);
this.addWarningField();
this.addTable(["-menu-", "Minion", "State", "Latest JID", "Target", "Function", "Start Time", "States"]);
this.addTable(["-select-", "-menu-", "Minion", "State", "Latest JID", "Target", "Function", "Start Time", "States"]);
this.setTableSortable("Minion", "asc");
this.setTableClickable("cmd");
this.addMsg();
Expand All @@ -48,6 +49,9 @@ export class HighStatePanel extends Panel {
onShow () {
const wheelKeyListAllPromise = this.api.getWheelKeyListAll();

const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
this.showSelectColumn(selectVisible);

this.nrMinions = 0;

const cmdList = [];
Expand Down Expand Up @@ -96,14 +100,14 @@ export class HighStatePanel extends Panel {
_addMenuItemStateApply (pMenu, pMinionId) {
pMenu.addMenuItem("Apply state...", () => {
const cmdArr = ["state.apply"];
this.runCommand("", pMinionId, cmdArr);
this.runCommand("", pMinionId, cmdArr, true);
});
}

_addMenuItemStateApplyTest (pMenu, pMinionId) {
pMenu.addMenuItem("Test state...", () => {
const cmdArr = ["state.apply", "test=", true];
this.runCommand("", pMinionId, cmdArr);
this.runCommand("", pMinionId, cmdArr, true);
});
}

Expand Down Expand Up @@ -362,7 +366,7 @@ export class HighStatePanel extends Panel {

// we already have the TR
// but this function also clears the row
this.getElement(trId);
this.getElement(trId, true);

// mark the TR as populated
minionTr.jid = pJobId;
Expand Down
10 changes: 5 additions & 5 deletions saltgui/static/scripts/panels/Keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export class KeysPanel extends Panel {
}

_addAcceptedMinion (pMinionId, pMinionsDict) {
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId));
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);

const minionIdTd = Utils.createTd();
const minionIdSpan = Utils.createSpan("minion-id", pMinionId);
Expand All @@ -309,7 +309,7 @@ export class KeysPanel extends Panel {
}

_addRejectedMinion (pMinionId, pMinionsDict) {
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId));
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);

const minionIdTd = Utils.createTd();
const minionIdSpan = Utils.createSpan("minion-id", pMinionId);
Expand All @@ -334,7 +334,7 @@ export class KeysPanel extends Panel {
}

_addDeniedMinion (pMinionId, pMinionsDict) {
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId));
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);

const minionIdTd = Utils.createTd();
const minionIdSpan = Utils.createSpan("minion-id", pMinionId);
Expand All @@ -359,7 +359,7 @@ export class KeysPanel extends Panel {
}

_addPreMinion (pMinionId, pMinionsDict, pInsertAtTop = false) {
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId));
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);

const minionIdTd = Utils.createTd();
const minionIdSpan = Utils.createSpan("minion-id", pMinionId);
Expand Down Expand Up @@ -392,7 +392,7 @@ export class KeysPanel extends Panel {
}

_addMissingMinion (pMinionId, pMinionsDict) {
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), "UNKNOWN");
const minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);

const minionIdTd = Utils.createTd();
const minionIdSpan = Utils.createSpan("minion-id", pMinionId);
Expand Down
3 changes: 3 additions & 0 deletions saltgui/static/scripts/panels/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ export class LoginPanel extends Panel {
const fullReturn = wheelConfigValuesData.saltgui_full_return;
Utils.setStorageItem("session", "full_return", fullReturn);

Utils.setStorageItem("session", "select_visible", "false");
Utils.setStorageItem("session", "select_minions", ",");

const id = wheelConfigValuesData.id;
const clusterId = wheelConfigValuesData.cluster_id;
const clusterPeers = wheelConfigValuesData.cluster_peers;
Expand Down
14 changes: 9 additions & 5 deletions saltgui/static/scripts/panels/Minions.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ export class MinionsPanel extends Panel {
this._addMenuItemStateApply(this.panelMenu, "*");
this._addMenuItemStateApplyTest(this.panelMenu, "*");
this.addSearchButton();
this.addFilterButton();
this.addWarningField();
this.addTable(["-menu-", "Minion", "Status", "Salt version", "OS version"]);
this.addTable(["-select-", "-menu-", "Minion", "Status", "Salt version", "OS version"]);
this.setTableSortable("Minion", "asc");
this.setTableClickable("cmd");
this.addMsg();
Expand All @@ -42,6 +43,9 @@ export class MinionsPanel extends Panel {

const runnerManageVersionsPromise = this.api.getRunnerManageVersions();

const selectVisible = Utils.getStorageItemBoolean("session", "select_visible", false);
this.showSelectColumn(selectVisible);

this.loadMinionsTxt();

wheelKeyListAllPromise.then((pWheelKeyListAllData) => {
Expand Down Expand Up @@ -180,7 +184,7 @@ export class MinionsPanel extends Panel {
}

updateOfflineMinion (pMinionId, pMinionsDict) {
super.updateOfflineMinion(pMinionId, pMinionsDict);
super.updateOfflineMinion(pMinionId, pMinionsDict, true);

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

Expand All @@ -190,7 +194,7 @@ export class MinionsPanel extends Panel {
}

updateMinion (pMinionData, pMinionId, pAllMinionsGrains) {
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains);
super.updateMinion(pMinionData, pMinionId, pAllMinionsGrains, true);

const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
this._addMenuItemStateApply(minionTr.dropdownmenu, pMinionId);
Expand All @@ -210,14 +214,14 @@ export class MinionsPanel extends Panel {
_addMenuItemStateApply (pMenu, pMinionId) {
pMenu.addMenuItem("Apply state...", () => {
const cmdArr = ["state.apply"];
this.runCommand("", pMinionId, cmdArr);
this.runCommand("", pMinionId, cmdArr, true);
});
}

_addMenuItemStateApplyTest (pMenu, pMinionId) {
pMenu.addMenuItem("Test state...", () => {
const cmdArr = ["state.apply", "test=", true];
this.runCommand("", pMinionId, cmdArr);
this.runCommand("", pMinionId, cmdArr, true);
});
}

Expand Down
8 changes: 4 additions & 4 deletions saltgui/static/scripts/panels/Nodegroups.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class NodegroupsPanel extends Panel {
}

updateOfflineMinion (pMinionId, pMinionsDict) {
super.updateOfflineMinion(pMinionId, pMinionsDict);
super.updateOfflineMinion(pMinionId, pMinionsDict, false);

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

Expand Down Expand Up @@ -121,7 +121,7 @@ export class NodegroupsPanel extends Panel {
Utils.addToolTip(minionSpan, "This minion is listed for this nodegroup,\nbut the minion is unknown", "bottom-left");
this.unknown += 1;
}
minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId));
minionTr = this.getElement(Utils.getIdFromMinionId(pMinionId), false);
minionTr.appendChild(minionTd);
minionTr.appendChild(status);
minionTr.appendChild(Utils.createTd());
Expand Down Expand Up @@ -346,7 +346,7 @@ export class NodegroupsPanel extends Panel {

const minionIds = keys.minions.sort();
for (const minionId of minionIds) {
const minionTr = this.addMinion(minionId);
const minionTr = this.addMinion(minionId, false);

// preliminary dropdown menu
this._addMenuItemStateApplyMinion(minionTr.dropdownmenu, minionId);
Expand All @@ -361,7 +361,7 @@ export class NodegroupsPanel extends Panel {
}

updateMinion (pMinionData, pMinionId, pAllNodegroupsGrains) {
super.updateMinion(pMinionData, pMinionId, pAllNodegroupsGrains);
super.updateMinion(pMinionData, pMinionId, pAllNodegroupsGrains, false);

const minionTr = this.table.querySelector("#" + Utils.getIdFromMinionId(pMinionId));
this._addMenuItemStateApplyMinion(minionTr.dropdownmenu, pMinionId);
Expand Down
Loading
Loading