Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

list concatenation using "set_fact" and "with_items" not working (regression) #80404

Closed
1 task done
unicode-it opened this issue Apr 5, 2023 · 5 comments
Closed
1 task done
Labels
affects_2.14 bug This issue/PR relates to a bug.

Comments

@unicode-it
Copy link

unicode-it commented Apr 5, 2023

Summary

Loops with set_fact do not behave like they used to. Unless this change is intended or documented somewhere, it is a regression. Maybe it is related to breaking changes with jinja3.

Issue Type

Bug Report

Component Name

core, jinja

Ansible Version

$ ansible --version
ansible [core 2.14.2]
  config file = /home/xxx/xxx/ansible.cfg
  configured module search path = ['/home/user/xxx']
  ansible python module location = /home/xxx/xxx
  ansible collection location = /home/user/xxx/collections
  executable location = /home/xxx/bin/ansible
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110] (/home/xxx/bin/python)
  jinja version = 3.0.3
  libyaml = True

Configuration

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

OS / Environment

Debian bullseye

Steps to Reproduce

Vars:

shares:
  - name: something
    type: nfs4
    from:
      nfs_server:
        path: /export/recordings/unpublished
        options: "rw,sync,no_root_squash,no_subtree_check"
    to:
      nfs_client1:
        path: /some/folder/
        opts: rw,auto,nofail
      nfs_client2:
        path: /some/folder/
        opts: rw,auto,nofail

Task:

- name: create vars for nfs role
  set_fact:
    nfs_exports: "{{ nfs_exports | default([]) }} + [ '/share/{{item.from[ansible_host].path.split('/')[-1]}}      {% for client in item.to | default([]) %}{{ips_intern[client]}} {% endfor %}{% for host in item.from[ansible_host].hosts | default([]) %}{{host}}({{item.from[ansible_host].options}}) {% endfor %}']"
  with_items: "{{shares}}"
  when:
    - "'nfs_servers' in group_names"
    - "ansible_host in item.from"
    - "item.from[ansible_host].hosts is defined"

Expected Results

"nfs_exports": ['/share fd75:5a92:ipv6 fd75:5a92:ipv6 ', '/share fd75:5a92:ipv6 fd75:5a92:ipv6 ']

Actual Results

"nfs_exports": "[] + ['/share      fd75:5a92:ipv6 fd75:5a92:ipv6 '] + ['/share      fd75:5a92:ipv6 fd75:5a92:ipv6 ']"

Since update to this ansible Version a string is generated. Concat of lists does not work any more. With {{ nfs_exports | default([]) | list }} it works as expected, but the list filter breaks the wrong interpretated string into single characters: ["[", "]"]

Code of Conduct

  • I agree to follow the Ansible Code of Conduct
@ansibot
Copy link
Contributor

ansibot commented Apr 5, 2023

Files identified in the description:
None

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

@ansibot ansibot added affects_2.14 bug This issue/PR relates to a bug. needs_triage Needs a first human triage before being processed. labels Apr 5, 2023
@flowerysong
Copy link
Contributor

flowerysong commented Apr 5, 2023

This is not a bug. You are doing concatenation outside of a Jinja expression, which used to work due to a bug but was never intended behavior. As noted in the porting guide {{ [1] }} + [2] should instead be written as a single Jinja expression, {{ [1] + [2] }}.

@unicode-it
Copy link
Author

Thanks for the clarification.
But this doesn't solve the use case above. Because that way Jinja expression (for loop) cannot be used any more. It cannot be put within {{ }}.
Can you help how this logic can be ported?

@flowerysong
Copy link
Contributor

The lazy way is to just put it in a separate variable.

- name: create vars for nfs role
  set_fact:
    nfs_exports: "{{ nfs_exports | default([]) + [new_export] }}"
  loop: "{{ shares }}"
  vars:
    new_export: /share/{{item.from[ansible_host].path.split('/')[-1]}}      {% for client in item.to | default([]) %}{{ips_intern[client]}} {% endfor %}{% for host in item.from[ansible_host].hosts | default([]) %}{{host}}({{item.from[ansible_host].options}}) {% endfor %}
  when:
    - "'nfs_servers' in group_names"
    - "ansible_host in item.from"
    - "item.from[ansible_host].hosts is defined"

@unicode-it
Copy link
Author

True that is an easy solution. Thx alot.

I am closing this issue.

@sivel sivel removed the needs_triage Needs a first human triage before being processed. label Apr 5, 2023
@ansible ansible locked and limited conversation to collaborators Jun 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.14 bug This issue/PR relates to a bug.
Projects
None yet
Development

No branches or pull requests

4 participants