Add the task log: recent tasks with status, Enter shows the log
l on the main screen opens "Tasks", the recent cluster tasks newest
first. l on the info screen shows only that guest's tasks. Columns:
start, duration (or "running"), node, type, VMID ("-" for node
tasks), user and status. A failed task gets a "!" in the leading
column. Enter opens the task's log in a plain-text widget, so the
output is never parsed as markup.
`task list -o json` has no start or end times, so the list comes from
`/cluster/tasks`. The upid is validated (it must start with "UPID:")
before it goes in as a positional argument.
Review fixes:
- A finished task without a start time no longer crashes the app; its
duration shows "-".
- "running" now means there is no endtime. A finished task with an
empty status shows "unknown" and is flagged.
Read-only live check: 25 tasks listed, and the log of the newest
(vzdelsnapshot 104) ends with TASK OK.
Closes #10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #25.
This commit is contained in:
1 parent
eec65e0585
commit
1ed5e5069b
6 files changed
+546
No files matched your search
@@ -1295,3 +1295,48 @@ def test_take_snapshot_refuses_description_that_looks_like_an_option(fake):
|
||||
{"vmid": 104, "node": "mainframe", "type": "lxc"}, "snap1", "-y"
|
||||
)
|
||||
assert fake.calls == []
|
||||
|
||||
|
||||
# --- issue #10: task log (spec: "Task log (issue #10)" > cli.py) ------------------------
|
||||
|
||||
UPID = "UPID:mainframe:0001:00A:68F:qmstart:108:root@pam:"
|
||||
|
||||
|
||||
def test_tasks_argv_is_cluster_tasks_json(fake): # tasks(): api get /cluster/tasks
|
||||
fake.result = ("[]", "", 0)
|
||||
assert cli.tasks() == []
|
||||
assert fake.argv == ["cv4pve-cli", "api", "get", "/cluster/tasks", "-o", "json"]
|
||||
|
||||
|
||||
def test_tasks_newest_first_including_running_without_endtime(
|
||||
fake,
|
||||
): # tasks(): newest first
|
||||
raw = [
|
||||
{"upid": "a", "starttime": 100, "endtime": 150, "status": "OK"},
|
||||
{"upid": "c", "starttime": 300}, # running: no endtime, no status
|
||||
{"upid": "b", "starttime": 200, "endtime": None},
|
||||
]
|
||||
fake.result = (json.dumps(raw), "", 0)
|
||||
assert [t["upid"] for t in cli.tasks()] == ["c", "b", "a"]
|
||||
|
||||
|
||||
def test_tasks_failure_raises_clierror(monkeypatch): # failure surfaces as CliError
|
||||
FakeRun(monkeypatch, "Error: boom", returncode=1)
|
||||
with pytest.raises(cli.CliError):
|
||||
cli.tasks()
|
||||
|
||||
|
||||
def test_task_log_argv_and_returns_text(fake): # task_log(): task log <upid>
|
||||
fake.result = ("starting\nTASK OK\n", "", 0)
|
||||
out = cli.task_log(UPID)
|
||||
assert fake.argv == ["cv4pve-cli", "task", "log", UPID]
|
||||
assert "TASK OK" in out
|
||||
|
||||
|
||||
@pytest.mark.parametrize("bad", ["-y", "--help", "", "108", "x UPID:a"])
|
||||
def test_task_log_rejects_non_upid_without_calling_subprocess(
|
||||
fake, bad
|
||||
): # ValueError unless UPID:
|
||||
with pytest.raises(ValueError):
|
||||
cli.task_log(bad)
|
||||
assert fake.calls == []
|
||||
Reference in new issue
Block a user