Skip to content
Advertisement

Using register with a loop in Ansible

i want to code a playbook which IF a user exists changes the pw of it. The playbook should be able to take n User’s and change the pw of those Users.

At the moment im having the issue that the when is empty due to the loop, i tried using with_items: {{ user_exists.results }} but this is somehow not working. (http://docs.ansible.com/ansible/playbooks_loops.html#using-register-with-a-loop)

Am i doing something wrong ?

Br, Numblesix

---
-
  become: true
  become_method: sudo
  hosts: xetest
  name: "Updates the password of given User if exists"
  tasks:
    -
      ignore_errors: true
      name: "Check if User exists"
      register: user_exists
      shell: "grep -q {{ item.key }} /etc/passwd &>/dev/null"
      with_dict: "{{ users }}"
    -
      debug:
       var: user_exists
    -
      debug:
        msg: "User name is {{ item.key }} and hash is {{ item.value.passwd}} and return code is: "
      with_dict: "{{ users }}"
    -
      debug:
        var: user_exists
      with_items: "{{user_exists.results }}"
    -
      name: "updating password for given User"
      user: "name={{ item.key }} update_password=always password={{ item.value.passwd}} createhome=no"
      when: user_exists.rc == 0
      with_dict: "{{ users }}"
      with_items: "{{ user_exists.results }}"
  vars:
    users:
      foo:
        passwd: $6$random_salt$12A.ar9eNDsgmds3leKoCDZPmq7OHLvhBtQg/Q3K2G/3yeEa/r8Ou4DxJpN6vzccewugvZt7IkfCbHFF2i.QU.

RESULTS IN ERROR!

 duplicate loop in task: items

WITHOUT with_items: “{{ user_exists.results }}” im getting this error

"failed": true, "msg": "The conditional check 'user_exists.rc == 0' failed. 
 The error was: error while evaluating conditional (user_exists.rc == 0): 
 'dict object' has no attribute 'rc'

Advertisement

Answer

For my testing, I’m using ansible 2.1.4.0.

When running the script, you can see in the debug for user_exists.results that it contains the input value passed in along with the return code:

    "results": [
        {
            "_ansible_item_result": true,
            "_ansible_no_log": false,
            "_ansible_parsed": true,
            "changed": true,
            "cmd": "grep -q foo /etc/passwd",
            "delta": "0:00:00.009034",
            "end": "2017-05-02 17:42:57.835871",
            "failed": true,
            "invocation": {
                "module_args": {
                    "_raw_params": "grep -q foo /etc/passwd",
                    "_uses_shell": true,
                    "chdir": null,
                    "creates": null,
                    "executable": null,
                    "removes": null,
                    "warn": true
                },
                "module_name": "command"
            },
            "item": {
                "key": "foo",
                "value": {
                    "passwd": "foobar"
                }
            },
            "rc": 1,
            "start": "2017-05-02 17:42:57.826837",
            "stderr": "",
            "stdout": "",
            "stdout_lines": [],
            "warnings": []
        },

So instead doing two loops (which would have been done with with_nested and two lists), you can do everything with a single loop:

- name: "updating password for given User"
  debug:
    msg: "name={{ item.item.key }} update_password=always password={{ item.item.value.passwd}} createhome=no"
  when: item.rc == 0
  with_items: "{{ user_exists.results }}"

Note: In my testing shell: “grep -q {{ item.key }} /etc/passwd &>/dev/null” was always returning a 0 return code. I had to remove the “&>/dev/null” part to get the proper return code.

Advertisement