liamfit
liamfit

Reputation: 35

Ansible remove blank lines from list

So I've got a playbook that retrieves the members of an AD group and gives me a list of their user IDs like this:

  tasks:
- name: Get group members
  set_fact:
    member: "{{ item }}"
  register: members
  with_ldap:
    - context: group_members
    - Jira_Administrators_GG

- name: Get userids
  set_fact:
    userid: "{{ lookup('ldap', '{{ item.item }}', context='users') }}"
  register: userids
  with_items: "{{ members.results }}"

- name: Create list of userids
  set_fact:
    userid_list: "{{ userids.results | map(attribute='ansible_facts.userid') | list }}"

Trouble is I end up with a few blank lines in the resultant list:

- name: Show userids
  debug:
    msg: "{{ hostvars['localhost']['userid_list'] }}"

Output:

TASK [Show userids] **************************************

ok: [xxxxxxxxx01] => {
    "msg": [
        "xxxxxxxxx55",
        "xxxxxxxxx58",
        "xxxxxxxxx71",
        [],
        "xxxxxxxxx46",
        [],
        "xxxxxxxxx27",
        [],
        "xxxxxxxxx63",
        "xxxxxxxxx27",
        [],
        "xxxxxxxxx04",
        "xxxxxxxxx87"
    ]
}

Does anyone know how to remove the blank lines from the list? I've had a look through http://jinja.pocoo.org/docs/2.9/templates/#builtin-filters and tried a couple like replace() and rejectattr() in between the map and list but for whatever reason I'm not getting it right.

EDIT - Some attempts that didn't work...

I'm clearly not getting the syntax right with this one:

- name: Create list of userids
  set_fact:
    userid_list: "{{ userids.results | rejectattr('ansible_facts.userid', 'equalto', '') | map(attribute='ansible_facts.userid') | list }}"

..because the output was:

    An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TemplateRuntimeError: no test named ''
fatal: [localhost]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}

I then tried moving rejectattr() before map. This was better, it actually runs but doesn't seem to make any difference to the resultant list:

- name: Create list of userids
  set_fact:
    userid_list: "{{ userids.results | rejectattr('ansible_facts.userid', 'equalto', '') | map(attribute='ansible_facts.userid') | list }}"

I tried with reject() instead of rejectattr() like this:

- name: Create list of userids
  set_fact:
     userid_list: "{{ userids.results | reject('equalto', '') | map(attribute='ansible_facts.userid') | list }}"

...and like this:

- name: Create list of userids
  set_fact:
     userid_list: "{{ userids.results | map(attribute='ansible_facts.userid') | reject('equalto', '') | list }}"

I've tried a few permutations, I also tried comparing to '[]' instead of '' because my empty lines show like that in the resultant list. I guess I just don't understand how to apply the filters correctly.

EDIT - Variable contents

Now if I do

- debug:
    var: userids

I get this (truncated to show 2 results that have userid populated and 1 with userid blank):

ok: [localhost] => {
    "userids": {
        "changed": false,
        "msg": "All items completed",
        "results": [
            {
                "_ansible_item_result": true,
                "_ansible_no_log": false,
                "ansible_facts": {
                    "userid": "xxxxxxxxx55"
                },
                "changed": false,
                "item": {
                    "_ansible_item_result": true,
                    "_ansible_no_log": false,
                    "ansible_facts": {
                        "member": "CN=Liam Fitzpatrick,OU=My User OU,DC=my,DC=domain,DC=com"
                    },
                    "changed": false,
                    "item": "CN=Liam Fitzpatrick,OU=My User OU,DC=my,DC=domain,DC=com"
                }
            },
            {
                "_ansible_item_result": true,
                "_ansible_no_log": false,
                "ansible_facts": {
                    "userid": "xxxxxxxxx58"
                },
                "changed": false,
                "item": {
                    "_ansible_item_result": true,
                    "_ansible_no_log": false,
                    "ansible_facts": {
                        "member": "CN=Mr Jones,OU=My User OU,DC=my,DC=domain,DC=com"
                    },
                    "changed": false,
                    "item": "CN=Mr Jones,OU=My User OU,DC=my,DC=domain,DC=com"
                }
            },
            {
                "_ansible_item_result": true,
                "_ansible_no_log": false,
                "ansible_facts": {
                    "userid": []
                },
                "changed": false,
                "item": {
                    "_ansible_item_result": true,
                    "_ansible_no_log": false,
                    "ansible_facts": {
                        "member": "CN=Mr Smith,OU=My User OU,DC=my,DC=domain,DC=com"
                    },
                    "changed": false,
                    "item": "CN=Mr Smith,OU=My User OU,DC=my,DC=domain,DC=com"
                }
            }

Upvotes: 1

Views: 11251

Answers (1)

Konstantin Suvorov
Konstantin Suvorov

Reputation: 68229

You have a list of strings (e.g. "xxxxxxxxx63") and empty lists ([]) – not empty strings.

You can use Jinja2 select/reject filters, for example:

- name: Create list of userids
  set_fact:
    userid_list: "{{ userids.results | map(attribute='ansible_facts.userid') | select('string') | list }}"

P.S. and avoid nested curly brackets, use:

"{{ lookup('ldap', item.item, context='users') }}"

Upvotes: 3

Related Questions