From f7a9229d815d90a69a3695d814c9af991e24b37a Mon Sep 17 00:00:00 2001 From: Keith Jackson Date: Mon, 7 Sep 2026 02:44:03 -0500 Subject: [PATCH] fix(ansible): the NVMe node would have died on an undefined variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review of the role I had just written. On k3s-prod-2 the scheduler path is deliberately skipped, so the `stat` on /sys/fs/cgroup/system.slice/k3s.service is skipped too — and a SKIPPED registration has no `.stat` key at all. Ansible templates `loop:` BEFORE it evaluates `when:`, so loop: "{{ ['system.slice'] + (['system.slice/k3s.service'] if _eio_k3s_cgroup.stat.exists else []) }}" raises on that host even though the task would never have run. The role would have failed on the one node it is designed to leave alone — and it would have failed at the very end, after doing nothing, which reads like a broken mitigation rather than an intentional skip. `| default(false)` on both uses. Exercised offline against a simulated skipped registration; `--syntax-check` re-run. Co-Authored-By: Claude Opus 5 (cherry picked from commit 5ccf5111a54857abb934a64c41332b7aa5046323) --- infra/ansible/roles/etcd_io_priority/tasks/main.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/infra/ansible/roles/etcd_io_priority/tasks/main.yml b/infra/ansible/roles/etcd_io_priority/tasks/main.yml index c684a6f..1faea78 100644 --- a/infra/ansible/roles/etcd_io_priority/tasks/main.yml +++ b/infra/ansible/roles/etcd_io_priority/tasks/main.yml @@ -197,7 +197,7 @@ playbooks/etcd-io-priority.yml once k3s is up. when: - _eio_scheduler | length > 0 - - not _eio_k3s_cgroup.stat.exists + - not (_eio_k3s_cgroup.stat.exists | default(false)) - name: Read back the live cgroup I/O weights ansible.builtin.command: @@ -206,9 +206,13 @@ changed_when: false check_mode: false failed_when: false + # `| default(false)`: Ansible templates `loop:` BEFORE evaluating `when:`, so on an NVMe + # node — where the stat task above is skipped and _eio_k3s_cgroup has no `.stat` at all — + # a bare `_eio_k3s_cgroup.stat.exists` raises even though this task will not run. loop: >- {{ ['system.slice'] - + (['system.slice/k3s.service'] if _eio_k3s_cgroup.stat.exists else []) }} + + (['system.slice/k3s.service'] + if (_eio_k3s_cgroup.stat.exists | default(false)) else []) }} when: _eio_scheduler | length > 0 - name: VERIFY every live cgroup weight actually carries the boost