Skip to content

Runs you did not start

Most tools that sit on top of Argo are worth something only once you have moved your workflows into them. dagweave does not need you to move anything. The connector watches every Workflow object in the namespaces its ArgoConnection covers, whatever created it.

When a status report arrives carrying no dispatch command from dagweave, it is somebody else’s run. dagweave stores it rather than dropping it, and marks it adopted. The rest of this page is what that gets you, and where an adopted run stops behaving like a run dagweave sent.

Anything that creates a Workflow in a watched namespace:

  • CronWorkflow children. Argo’s own cron controller creates the object on schedule, and no dagweave trigger is involved.
  • argo submit and kubectl create -f. Someone at a terminal.
  • CI jobs, operators, anything else holding cluster credentials. dagweave does not check who wrote the object.

Adoption needs a report with no dagweave command id on it and the Argo object’s UID, and nothing else. The UID is what keys every later report about the same Workflow onto the same row, so a run adopted while it is running is the same row that later goes succeeded.

There is a race worth knowing about. The cluster-wide watcher can report a Workflow before the submit that created it comes back, so a run dagweave dispatched can turn up adopted for a moment. When the dispatch claims the UID, the adopted twin is deleted and the dispatched row is the one that survives.

dagweave correlates a status report to a run by the command id it minted at dispatch, or failing that by the Argo UID. An adopted run has neither pointing at anything dagweave authored, so the row it creates carries no workflow id.

Nothing infers one. Tying a cluster Workflow back to a template dagweave already holds would mean reading the template label off the Argo object, and the connector’s WorkflowRef carries namespace, name, UID and Argo instance, with no labels field at all. There is no wire to send a label on. That correlation is not built.

Most of what follows is a consequence of the missing workflow id.

An adopted run belongs to the tenant of the connector that reported it. It has no author, because nobody clicked run, and no workflow whose viewers it could borrow instead. So it gets a rule of its own, and that rule is narrower than the one covering every other run:

  • Team admins and owners can read adopted runs, on the same permission that lets them delete the team’s connectors.
  • An explicit namespace:dispatch grant on the reporting connector also reads them. Dispatch is the one relation no broad role rolls up to, so holding it is always somebody’s deliberate act.
  • An ordinary team member cannot, and that includes a member who can already read every other run the team owns. An editor with no dispatch grant gets an empty list back, and a run they ask for by id answers 404, the same answer a run in another tenant gets.

The reason is what the alternative would have done. With no workflow to inherit from, the fallthrough is the team-wide read every other run rolls up to, which would hand a viewer with no cluster access the names, failure messages and logs of every namespace the connector watches.

This is stricter than teams and access control describes. Nothing on that page has changed; adopted runs are an exception written on top of it.

Not in the run history. The paged run list skips adopted rows, so the table in the executions view is the runs dagweave dispatched and nothing else. The same goes for GET /api/v1/runs on the public API, which is the same handler behind a token, and there is no v1 route that lists adopted runs at all.

They get their own list instead, scoped to the connectors the caller may read. In the executions view that list is a section of its own, below the table and outside the phase tabs, headed “Not started from dagweave”. It is there while the history is unfiltered and gone once you pick a phase. A reader the gate above turns away gets an empty list, and the section renders nothing at all.

An adopted run has no workflow name to be called after, so it goes by its Argo namespace and object name, which is what you would kubectl get it by. Its trigger source is empty for the same reason: manual, cron, webhook, GitHub, SNS and API are all things dagweave did, and dagweave did none of them. The row reads adopted in that column. There is no source filter for them, and none is needed, because the section is the whole population.

Adopted runs also stay outside every number that already existed. The health aggregates, the per-workflow success rates and the sweep that fails a run left pending too long all behave as though the adopted row were not there, so a busy cluster cannot make your own workflows look worse than they are.

Open one and you get what Argo recorded: the phase, the message, and the node list with each step’s start and finish. That is the Workflow object’s own data, so it is what happened rather than what some graph says should happen. The run carries an ADOPTED badge, so nothing on the screen implies dagweave sent it.

A failing adopted run fires the same failure alert as any other run, once, on the first transition into a terminal failure, over whichever of email and Slack the team configured. There is no workflow name for the message to use, so it names the run. That recipient is whatever the team set for failure notifications, which is a different decision from the read gate above.

Per-step logs are the one thing that does not follow. Where dagweave reads lines back from a hosted Loki, the query is keyed on the workflow id, and an adopted run has none, so that panel comes back empty.

Re-running an adopted run does not work. The rerun path re-dispatches the original run’s own workflow with its original parameters, and looks that workflow up by the id on the run. An adopted run’s is empty, the lookup misses, and the request comes back 404. There is nothing for dagweave to submit: it never held the spec that produced the run, only the status Argo reported about it.

Be honest about the comparison, because Argo’s own UI already lists every run on the cluster and will happily show you a CronWorkflow child. What it will not do is show that run to anyone without cluster credentials, or tell you it failed. Argo’s UI is a place you go and look.

So the practical version is narrow and worth having. Install the connector, write an ArgoConnection for each Argo instance, deploy nothing and change nothing, and the traffic already running on your cluster is readable in a browser by the people who administer that connection, with a failure alert attached. Whether you then move the authoring into dagweave is a separate decision, and this does not commit you to it.