0

I'm trying to register the output of a shell command to an item property inside a list of items.

This takes place during a loop but does not appear to register the properties. After the task is ran, the property is still showing the value none. I'm wondering if I'm doing something wrong ? Or Is there a way to accomplish this ?

Variables:

users:
  - username: someguy
    description: "Some Guy"
    groups: ['sudo', 'guy']
    new_id: 6001
    old_uid:
    old_gid:
    user_exists:
    password: waffles
  - username: somedude
    description: "Some Dude"
    groups: ['dude']
    new_id: 6002
    old_uid:
    old_gid:
    user_exists:
    password: toast

Tasks

---

- name: Check if user exists
  shell: /usr/bin/getent passwd {{ item.username }} | /usr/bin/wc -l | tr -d ' '
  with_items: "{{ users }}"
  register: item.user_exists

- name: Check user current UID
  shell: /usr/bin/id -u {{ item.username }}
  with_items: "{{ users }}"
  register: item.old_uid
  when: item.user_exists == 1

- name: Check user current GID
  shell: /usr/bin/id -g {{ item.username }}
  with_items: "{{ users }}"
  register: item.old_gid
  when: item.user_exists == 1

Output

TASK: [users | Check if user exists] ****************************************** 
changed: [bserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
changed: [aserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
changed: [aserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
changed: [bserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})

TASK: [users | Check user current UID] **************************************** 
skipping: [aserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [aserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [bserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [bserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})

TASK: [users | Check user current GID] **************************************** 
skipping: [aserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [aserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [bserver] => (item={'username': 'someguy', 'password': 'waffles', 'description': 'Some Guy', 'new_id': 6001, 'groups': ['sudo', 'guy'], 'user_exists': None, 'old_uid': None, 'old_gid': None})
skipping: [bserver] => (item={'username': 'somedude', 'password': 'toast', 'description': 'Some Dude', 'new_id': 6002, 'groups': ['dude'], 'user_exists': None, 'old_uid': None, 'old_gid': None})

1 Answer 1

2

Unfortunately that is not how it works.

Your line register: "{{item.user_exists}}" would probably result into the result registered in a variable called false.

You can not inject the result of a task into any object. The register feature will only take a string.

Additionally register has a complete different behavior in a loop. Instead of registering every iteration separately, it will register one single object which holds the results of all items in the key results.

You can still loop over your users and check for existence. But I don't think you will get with this where you want to be.

First register the result in one single variable, here users_checked:

- name: Check if user exists
  shell: /usr/bin/getent passwd {{ item.username }} | /usr/bin/wc -l | tr -d ' '
  with_items: users
  register: users_checked

I recommend you to work with the debug module to always check with what structure of data you're working.

- debug: var=users_checked

This will show you something like this:

"var": {
    "users_checked": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "changed": true,
                "cmd": "/usr/bin/getent passwd someguy | /usr/bin/wc -l | tr -d ' '",
                "delta": "0:00:00.005415",
                "end": "2015-09-08 20:59:33.379516",
                "invocation": {
                    "module_args": "/usr/bin/getent passwd someguy | /usr/bin/wc -l | tr -d ' '",
                    "module_name": "shell"
                },
                "item": {
                    "description": "Some Guy",
                    "groups": [
                        "sudo",
                        "guy"
                    ],
                    "new_id": 6001,
                    "old_gid": null,
                    "old_uid": null,
                    "password": "waffles",
                    "user_exists": null,
                    "username": "someguy"
                },
                "rc": 0,
                "start": "2015-09-08 20:59:33.374101",
                "stderr": "",
                "stdout": "0",
                "stdout_lines": [
                    "0"
                ],
                "warnings": []
            },
            {
                "changed": true,
                "cmd": "/usr/bin/getent passwd somedude | /usr/bin/wc -l | tr -d ' '",
                "delta": "0:00:00.006362",
                "end": "2015-09-08 20:59:33.530546",
                "invocation": {
                    "module_args": "/usr/bin/getent passwd somedude | /usr/bin/wc -l | tr -d ' '",
                    "module_name": "shell"
                },
                "item": {
                    "description": "Some Dude",
                    "groups": [
                        "dude"
                    ],
                    "new_id": 6002,
                    "old_gid": null,
                    "old_uid": null,
                    "password": "toast",
                    "user_exists": null,
                    "username": "somedude"
                },
                "rc": 0,
                "start": "2015-09-08 20:59:33.524184",
                "stderr": "",
                "stdout": "0",
                "stdout_lines": [
                    "0"
                ],
                "warnings": []
            }
        ]
    }
}

So the result not only holds the actual results of all items, but as well the input objects. That enables you to loop over users_checked.results instead of your original users list.

- name: Check user current UID
  shell: /usr/bin/id -u {{ item.item.username }}
  with_items: users_checked.results
  when: item.stdout == 1

But now it would get nasty, since you want to check two more things. You probably could continue with this approach, register the above result, then use the registered data structure as input for the next loop, but you will end up with a deeply nested object and at the end having the original object somewhere in registered_var.results[x].item.results[y].item.results[z].item....

To avoid this mess you might want to look into creating a custom module for this task.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.