import { LongRunningProcess, ProcessState } from './long-running-process.js';
let state, command, runArgs, run_button, output;
const default_command = "date; for i in `seq 30`; do echo $i; sleep 1; done";
function showJournal(unitName, filter_arg) {
if (showJournal.journalctl)
return;
output.textContent = "";
const argv = ["journalctl", "--output=cat", "--unit", unitName, "--follow", "--lines=all", filter_arg];
showJournal.journalctl = cockpit.spawn(argv, { superuser: "require", err: "message" })
.stream(data => output.append(document.createTextNode(data)))
.catch(ex => { output.textContent = JSON.stringify(ex) });
}
function update(process) {
state.textContent = cockpit.format("$0 $1", process.serviceName, process.state);
switch (process.state) {
case ProcessState.INIT:
break;
case ProcessState.STOPPED:
run_button.removeAttribute("disabled");
run_button.textContent = "Start";
break;
case ProcessState.RUNNING:
run_button.removeAttribute("disabled");
run_button.textContent = "Terminate";
showJournal(process.serviceName, "--since=@" + Math.floor(process.startTimestamp / 1000000));
break;
case ProcessState.FAILED:
run_button.removeAttribute("disabled");
run_button.textContent = "Reset";
showJournal(process.serviceName, "--boot");
break;
default:
throw new Error("unexpected process.state: " + process.state);
}
}
cockpit.transport.wait(() => {
state = document.getElementById("state");
command = document.getElementById("command");
runArgs = document.getElementById("sysrun-args");
run_button = document.getElementById("run");
output = document.getElementById("output");
command.value = default_command;
* command to re-attach to. For a single static command this is just the page name,
* but it could also include the command name or path, arguments, or a playbook name,
* etc. if the page is dealing with multiple commands. */
const serviceName = "cockpit-longrunning.service";
const process = new LongRunningProcess(serviceName, update);
* This runs as root, thus will be shared with all privileged Cockpit sessions.
*/
run_button.addEventListener("click", () => {
if (process.state === ProcessState.RUNNING)
process.terminate();
else if (process.state === ProcessState.FAILED)
process.reset();
else {
const runArgsList = runArgs.value.split(" ").filter(i => i);
process.run(["/bin/sh", "-ec", command.value], {}, runArgsList)
.catch(ex => {
state.textContent = "Error: " + ex.toString();
run_button.setAttribute("disabled", "");
});
}
});
});