SIGN IN SIGN UP

22106 job plugin: Model the section as a tagged union

The section was a dict of TypedDicts whose keys were all optional, so
every consumer had to guess which of them were set: "running" and
"running_start_time" described the running instances, "exit_code",
"start_time" and "metrics" the last completed run, and nothing tied the
two groups together. Each mk-job file now becomes either a RunningJob or
a CompletedJob, and a job maps to the list of its files. What is optional
is optional because the agent may really not have sent it.

Parsing a file as a whole instead of line by line also means that a
garbled field no longer decides what happens to the rest of the file:
_as() maps anything unparsable to None, so a missing /usr/bin/time or the
job's own stderr merged into the file (mk-job.aix) can no longer take a
metric down with it. _parse_header replaces the endswith("running")
guesswork with a regex for the ".<pid>running" suffix that mk-job
actually writes.

Two latent bugs go with it:

- The metrics of a completed run were dropped whenever the agent listed
  the running file first, because setdefault() returned the existing job
  while the metrics dict of the new one was written to. The agent uses
  "find", which does not sort, so this was a coin flip per job. Covered
  by the werk and pinned by test_parse_order.

- A job whose own name ends in "running" was taken for a running file.
  Werked behavior is restored, not changed: before this series such a job
  was quarantined and then promoted back, which happened to produce the
  right result.

Everything the services report is otherwise unchanged, including the
summary line. Only the order of the detail lines differs: the metrics now
follow the exit code as a block, ahead of the start time and the job age.

CMK-35333

Change-Id: I2dc8e22c4184a0443f587dae55ed93e5b9be8bc8
A
Andreas Hasenkopf committed
3558921803f92d4b35b19304698fc6abb2669359
Parent: 803a7fb
Committed by Jenkins <jenkins@review.lan.tribe29.com> on 8/25/2026, 8:06:04 AM