Search code examples
python-3.xansibleansible-tower

Ansible - Access output of a shell command with with_items


I wrote a python script which gets executed via my ansible playbook and returns the following output via stdout:

- { username: ansible, admin: yes}
- { username: test, admin: no }

The output then should get saved in the variable "users" and with the "with_items" (or the newer "loop" conditional) I want to iterate through the variable in order to assign the right permissions for each user separately:

- name: execute python script
  command: "python3 /tmp/parse_string.py --user_permissions={{ user_permissions }}"
  register: output

- name: register
  set_fact:
    users: "{{ output.stdout }}"

- name: output
  debug: msg="{{ users }}"

- name: Add user to group -admin
  user:
    name={{ item.username }}
    groups=admin
    append=yes
    state=present
  when: "item.admin == yes"
  with_items: '{{users}}

However when launching the playbook it says that the variable "users" has no attribute "username".

TASK [create_users : output] ***************************************************
ok: [ansible] => {
    "msg": "- { username: ansible, admin: yes }\n- { username: test, admin: no }\n- { username: test2, admin: no }"
}
TASK [create_users : Add user to group -admin ***************
fatal: [ansible]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'username'\n\nThe error appears to be in '***': line 29, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: \n  ^ here\n"}

Can anyone help me with this case?

BR


Solution

  • You are setting your users var to a string. It happens that this string is a yaml representation of a datastructure but ansible has no clue about that at this point.

    To achieve your requirement, you need to parse that string as yaml and register the result. Luckily, there is a from_yaml filter for that purpose

    You just have to modify your set_fact task as the following and everything should work as expected:

    - name: register
      set_fact:
        users: "{{ output.stdout | from_yaml }}"