Skip to content

Regression in 2.21: ansible_connection flips from short name to FQCN mid-loop #87062

@hunhejj

Description

@hunhejj

Summary

In ansible-core 2.21.0, when a play declares its connection using the short name (e.g. connection: local, not connection: ansible.builtin.local), the magic variable ansible_connection reports the declared short name (local) on the first iteration of a looped task and the connection
plugin's FQCN (ansible.builtin.local) on every subsequent iteration of the same task. The variable mutates inside a single task without anything in the playbook changing the connection.

The same playbook is unaffected on ansible-core 2.20.6 — there, ansible_connection reports the declared short name on every iteration.

Any Jinja expression in the codebase that compares ansible_connection against a short name (e.g. {{ ... if ansible_connection == 'local' else ... }}) silently flips its result on iterations 2+ after upgrading to 2.21.0. No deprecation in 2.19 or 2.20 warned about this; the only related
entry in the 2.21.0 changelog is "callbacks - The value of TaskResult.task.connection properly reflects the loaded connection name used. Previously, incorrect values were reported in some cases.", which is scoped to callbacks and does not announce a change to the user-templatable
ansible_connection variable.

Issue Type

Bug Report

Component Name

core

Ansible Version

$ ansible --version
  ansible [core 2.21.0]                                                                                                                                                                                                                             
    python version = 3.12.3
    jinja version = 3.1.6

Configuration

# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
  CONFIG_FILE() = None

  GALAXY_SERVERS:

OS / Environment

Ubuntu 24.04 (x86_64)

Steps to Reproduce

  ---
  - hosts: localhost                                                                                                                                                                                                                                
    connection: local
    gather_facts: false
    tasks:
      - debug:
          msg: "iter {{ item }}: ansible_connection={{ ansible_connection }}"
        loop: [1, 2, 3, 4]

Expected Results

All four iterations print ansible_connection=local, matching the play's declared connection: local. This is what ansible-core 2.20.6 does:

ok: [localhost] => (item=1) => { "msg": "iter 1: ansible_connection=local" }
ok: [localhost] => (item=2) => { "msg": "iter 2: ansible_connection=local" }
ok: [localhost] => (item=3) => { "msg": "iter 3: ansible_connection=local" }
ok: [localhost] => (item=4) => { "msg": "iter 4: ansible_connection=local" }

Actual Results

ok: [localhost] => (item=1) => { "msg": "iter 1: ansible_connection=local" }
  ok: [localhost] => (item=2) => { "msg": "iter 2: ansible_connection=ansible.builtin.local" }
  ok: [localhost] => (item=3) => { "msg": "iter 3: ansible_connection=ansible.builtin.local" }
  ok: [localhost] => (item=4) => { "msg": "iter 4: ansible_connection=ansible.builtin.local" }

# The variable's value changes inside one task — short name on iteration 1, FQCN on iterations 2+ — even though nothing in the playbook touches the connection between iterations.

Code of Conduct

  • I agree to follow the Ansible Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    affects_2.21This issue/PR affects Ansible v2.21bugThis issue/PR relates to a bug.has_prThis issue has an associated PR.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions