Skip to content

Bare non-empty-string conditionals break under ansible-core 2.17.4 (~28 sites, 3 already fixed) #387

Open

Description

@ddemlow

Summary

ansible-core 2.17.4 (what the self-hosted2 CI container actually runs) rejects a bare
non-empty string used directly as a when:/assert.that boolean condition, with:

[ERROR]: Task failed: Conditional result (True) was derived from value of type 'str' at
'.../integration_config.yml:334:31'. Conditionals must have a boolean result.

Older ansible-core implicitly truthy-tested a bare string ("non-empty string = true"),
which is the idiom used throughout this collection's integration tests
(- some_field as shorthand for "this field is present/non-empty"). This newer version
requires an explicit boolean.

This is a pre-existing compatibility gap, not something introduced by the Indy-lab
failover work (#383/#384/#385/#386)
— it's been dormant because, until that work, no host
actually in rotation had a genuinely non-empty value flowing through one of these specific
checks during a real CI run. Restoring CI to the first real nested-vSNS hosts in a long time
is what surfaced it, three separate times:

What's left

A YAML-aware scan (walks every task's when: and every assert/ansible.builtin.assert
task's that: list, flags any bare dotted-path expression with no comparison operator,
filter, or is/in/and/or/not) found 27 more candidates across 14 files below.

Caveat, read before fixing any of these: this scan can only see the textual shape of
the expression, not its runtime type. The confirmed failures so far have all been on
STRING-valued fields. A few of these candidates (features.*.is_supported,
features.*.is_writable, features.version_update.old_update_status_present) are backed by
literal YAML True/False values in integration_config.yml.j2, so they may already be
real native booleans and not actually broken — but worth confirming empirically (run the
target; if it fails with the same "Conditionals must have a boolean result" message, it's
real) rather than assuming either way. The fix, where needed, is the same shape used in
#385/#386: replace the bare expression with an explicit boolean test, e.g.
sc_config[sc_host].sc_replication_dest_host → sc_config[sc_host].sc_replication_dest_host | length > 0
(prefer | length > 0/| length == 0 over | bool — Ansible's bool filter only
recognizes a fixed set of yes/no/true/false-style tokens and isn't guaranteed to treat an
arbitrary string, like a URL, the way you'd want).

Likely a real, active failure right now (not just a candidate) — .64's nested cluster
has sc_replication_dest_host genuinely configured, so remote_cluster_info's "If remote
cluster is configured" branch runs for real on it, same as vm_replication_info did before
#386:

  • remote_cluster_info/tasks/main.yml (task with the assert.that block covering name,
    connection_status, replication_ok, remote_node_ips, remote_node_uuids) — 5 items

Full candidate list

File Context Expression
cluster_name/tasks/main.yml when sc_config[sc_host].features.cluster_name.is_writable
dns_config/tasks/01_dns_config_info.yml assert.that (×2) result.record.latest_task_tag
node_info/tasks/main.yml assert.that (×3) initial.records[0].node_uuid / .backplane_ip / .lan_ip
registration/tasks/main.yml assert.that (×2) result.record
remote_cluster_info/tasks/main.yml assert.that (×5) initial.records[0].name / .connection_status / .replication_ok / .remote_node_ips / .remote_node_uuids
smtp/tasks/01_smtp_info.yml assert.that result.record.latest_task_tag
smtp/tasks/02_smtp.yml when (×3) test_on_emtpy_cluster
time_server/tasks/01_time_server_info.yml assert.that result.record.latest_task_tag
time_zone/tasks/01_time_zone_info.yml assert.that result.record.latest_task_tag
version_update_status_info/tasks/main.yml when sc_config[sc_host].features.version_update.old_update_status_present
virtual_disk/tasks/main.yml when sc_config[sc_host].features.virtual_disk.is_supported
virtual_disk_attach/tasks/main.yml when sc_config[sc_host].features.virtual_disk.is_supported
virtual_disk_info/tasks/main.yml when sc_config[sc_host].features.virtual_disk.is_supported
vm_clone/tasks/01_cleanup.yml when source_running_info.records
vm_disk__iso_eject/tasks/main.yml assert.that (×2) vm.records.0.disks.0
vm_disk__nvram_vtpm/tasks/main.yml when vtpm_supported

(paths relative to tests/integration/targets/)

Suggested approach

  1. Start with remote_cluster_info — near-certain active failure against the current fixture.
  2. For the rest, the fastest way to separate real bugs from false positives is just running
    each target and seeing whether it fails with the same message, rather than reasoning about
    types statically.
  3. Same fix shape as Fix bare-string when/assert conditionals rejected by ansible-core 2.17.4 #385/vm_replication_info: fix remaining bare-string assert conditional #386 once confirmed.

Found while restoring this collection's CI after the PUB5/XLab outage — see #383 for that
context.

Activity

  1. ddemlow commented on Nov 2, 2026

    @ddemlow
    MemberAuthor

    New related finding (2026-11-02), different shape, worth tracking here too:

    integ-physical's vm_replication/vm_replication_info targets (already pinned to
    ansible-core~=2.16.0, unrelated to this issue's 2.17.4 bare-truthy-string bug) now fail with:

    The conditional check 'replication_info.records[0].remote_cluster == "{{ remote_cluster_0_name }}"'
    failed. The error was: Conditional is marked as unsafe, and cannot be evaluated.
    

    tests/integration/targets/vm_replication/tasks/main.yml:106 — an unquoted Jinja2 expression
    ("{{ remote_cluster_0_name }}") inside an assert.that boolean comparison. These same targets
    passed clean in the 2026-10-29 validation run
    (https://github.com/ScaleComputing/HyperCoreAnsibleCollection/actions/runs/40864780591), so this
    looks like a newer ansible-core 2.16.x patch release tightening this specific check (unsafe/
    untrusted templating inside a condition), not something the Indy-lab rebuild introduced.

    Same fix shape as #385/#386 — quote the whole condition expression (or move the comparison value
    out of the Jinja2 braces) rather than leaving a bare templated string inline. Leaving unfixed for
    now per the same reasoning as this issue: hand XLab working CI to continue from, not everything
    pre-solved. Validation run showing this failure:
    https://github.com/ScaleComputing/HyperCoreAnsibleCollection/actions/runs/41462388092

  2. ddemlow commented on Nov 2, 2026

    @ddemlow
    MemberAuthor

    Correction to my 2026-11-02 comment above — I said the `vm_replication`/`vm_replication_info` "unsafe conditional" failure looked like a newer ansible-core 2.16.x patch tightening a check, unrelated to the Indy-lab rebuild. That was wrong.

    Checked the exact installed version in both runs:

    So #389's ansible-core 2.16.0 pin itself caused this — it didn't surface a pre-existing bug. The two issues point in opposite directions: this collection's bare-truthy-string idiom (this issue) needs ansible-core <2.17 to pass; this particular unquoted-Jinja2-in-a-condition shape (tests/integration/targets/vm_replication/tasks/main.yml:106) needs >=2.17 to pass. Pinning to 2.16.0 trades ~15 fixed targets for these 2 newly broken ones — net positive for nightly CI, but not a clean fix either way. The actual fix for this one (quote the whole condition) still removes the version-dependency entirely, same as the real fixes for #385/#386 did for the other kind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions