randomparity / randomparity/kdive

live_vm_host requires github_runner_user but never declares it, coupling the role to the CI runner

Open
#2,562 0 comments 0 reactions 0 assignees View on GitHub
area:provisioning effort:S priority:P3 risk:night-safe type:bug
Dominant language
Python
Stars
0
Forks
0
Avg merge
1h 26m
Merged PRs (30d)
311

Description

## Problem

The `live_vm_host` role reads `github_runner_user` in roughly twenty places but never declares
it. The variable is defined only in `github_runner/defaults/main.yml:2`, and Ansible loads a
role's defaults only for roles in the play — so `live_vm_host` silently requires the
`github_runner` role to be in the same play as itself.

The practical effect: a host cannot be provisioned as a live-VM worker host without also being
turned into a GitHub Actions runner.

## Observed

Running `libvirt_stack` + `libvirt_pool_net` + `live_vm_host` against a host — the same three
roles `deploy/ansible/playbooks/runner.yml` runs, minus `github_runner`:

```
TASK [live_vm_host : Ensure the runner service account exists in kvm and libvirt] ***
fatal: FAILED! => {"changed": false, "msg": "Task failed: Finalization of task args for
'ansible.builtin.user' failed: Error while resolving value for 'name':
'github_runner_user' is undefined"}
```

It fails at the first use and every later one would fail the same way.

## Evidence

Defined in exactly one place, and not in the role that consumes it:

```
deploy/ansible/roles/github_runner/defaults/main.yml:2:github_runner_user: github-runner
```

Consumed throughout `live_vm_host`, including as the owner of files and the account for
`become_user`:

```
deploy/ansible/roles/live_vm_host/tasks/main.yml:40: name: "{{ github_runner_user }}"
deploy/ansible/roles/live_vm_host/tasks/main.yml:63: name: "{{ github_runner_user }}"
deploy/ansible/roles/live_vm_host/tasks/main.yml:88: ansible.builtin.command: "loginctl enable-linger {{ github_runner_user }}"
deploy/ansible/roles/live_vm_host/tasks/main.yml:107: owner: "{{ github_runner_user }}"
deploy/ansible/roles/live_vm_host/tasks/main.yml:117: become_user: "{{ github_runner_user }}"
deploy/ansible/roles/live_vm_host/tasks/main.yml:373: local_worker_host_operator_user: "{{ github_runner_user }}"
(…~20 references in total)
```

`live_vm_host/meta/` declares no dependency on `github_runner`, and
`live_vm_host/defaults/main.yml` does not define the variable or a fallback.

There is a second instance of the same pattern in the other direction:
`local_worker_host/tasks/packages_debian.yml:4` installs `{{ live_vm_host_packages }}`, a
`live_vm_host`-prefixed name that is actually defined in
`local_worker_host/defaults/main.yml:9` and carries an explicit
`# noqa: var-naming[no-role-prefix]` to silence the lint that would flag it. So the prefix
convention is already known to be violated here and is suppressed rather than resolved.

## Why it matters

The role names a real boundary — "the account that owns the live-VM worker files" — but spells it
as the CI runner's account. That conflates two things that are only incidentally equal on the one
host that exists today, and it makes the role untestable and unusable anywhere else: a second
worker host, a developer box reproducing a live failure, or a proof run that must not also
register a CI runner.

It also weakens `runner.yml` itself. Because the coupling is implicit, reordering the roles or
splitting the playbook would break it with an `undefined` error at apply time rather than at lint
or check time.

## Expected

Either:

1. **Give the role its own variable**, e.g. `live_vm_host_operator_user`, defaulting to
`github_runner_user` where that is defined so `runner.yml` keeps working unchanged, and have
`runner.yml` pass it explicitly; or
2. **Declare the dependency** in `live_vm_host/meta/main.yml` if the coupling is genuinely
intended, so it is at least stated and the role fails with a dependency error rather than an
undefined-variable error.

(1) matches what the role actually means and is the smaller behavioural change. `local_worker_host`
already takes a `local_worker_host_operator_user` for exactly this purpose, and
`live_vm_host/tasks/main.yml:373` sets it *from* `github_runner_user` — so the shape to copy is
already in the tree.

## Out of scope

- Renaming `live_vm_host_packages` to match its owning role. Same class of problem, opposite
direction, and it is pinned by `deploy/ansible/tests/run-local-worker-host.py`; worth its own
decision.
- The missing `python3-dev` entry in that package list, filed separately.

## Provenance

Found while provisioning a host as a live-VM worker host without making it a CI runner, in order
to run a live proof for an unrelated pull request. Confirmed by reading where the variable is
defined and where it is consumed, not inferred from the failure message alone.

Contributor guide

Open the contributing guide

Research direction

Start with deploy/ansible/roles/live_vm_host/tasks/main.yml and compare its variable uses with github_runner/defaults/main.yml and live_vm_host/defaults/main.yml. Read deploy/ansible/playbooks/runner.yml and live_vm_host/meta/main.yml to understand the current role boundary, using local_worker_host as the existing variable pattern. Done means the live_vm_host role can run without github_runner while runner.yml continues to work unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
ansible
Domain
devops
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.