# Creating a fact array

**URL:** <https://forum.ansible.com/t/creating-a-fact-array/36082>\
**Category:** Ansible Project\
**Created:** [December 8, 2021, 3:50pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082 "2021-12-08T15:50:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 8, 2021, 3:50pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/1 "2021-12-08T15:50:00Z")

</div>

I had another topic about using a fact in a loop, but since this question is slightly different, I figured I’d start a new topic.

Background:  
I’m using the IPA API calls using the uri module to get a list of users in our IPA server. Once I get the uses via user\_find, I set a fact of just the uid’s. This works well. Then I am using that fact to use the user\_show API via uri. This also works, but since we have over 1600 users, it takes a bit of time. So I’m looping through the uid list to process the first 20.

Issue:

I am registering the user\_show data in a variable called user\_show. I’m trying to set a fact that has the uid, password expiration, and the age calculation. The problem I have is that the fact has the information from the last user processed, and is not an array of data as I expect. Here’s how I’m setting the facts:

- name: Run user\_show from IDM API using previously stored session cookie  
uri:  
url: “https://{{idmfqdn}}/ipa/session/json”  
method: POST  
headers:  
Cookie: “{{ login.set\_cookie }}”  
Referer: “https://{{idmfqdn}}/ipa”  
Content-Type: “application/json”  
Accept: “application/json”  
body\_format: json  
body: “{"method": "user\_show","params": [["{{ uid[item|int] }}"],{"all": true,"version": "{{ api\_vers }}"}]}”  
register: user\_show  
with\_sequence: start=0 end=19

- name: Set user\_show fact  
set\_fact:  
users:

- “{{ (user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’) }}”

- “{{ (ansible\_date\_time.epoch|int - ((user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’))|int) / (60_60_24) }}”

- “{{ user\_show.results[item|int].json.result.result.uid[0] }}”

- name: Print users fact \<------------------- This shows the last user and not the previous 19  
debug:  
msg: “{{ users }}”

So how can I accomplish this?

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![Oluwole\_Leigh](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@Oluwole\_Leigh](https://forum.ansible.com/u/Oluwole_Leigh)\
**Post date:** [December 8, 2021, 5:27pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/2 "2021-12-08T17:27:42Z")

</div>

Hi there,  
You can use the debug module directly to display the required output . This can be done using with\_together in a loop as shown below

debug:  
msg: “{{ item.0 }}{{ item.1 }}{{ item.2 }}”  
with\_together:

- “{{ (user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’) }}”
- “{{ (ansible\_date\_time.epoch|int - ((user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’))|int) / (60_60_24) }}”
- “{{ user\_show.results[item|int].json.result.result.uid[0] }}”

If you need to store in a fact you can use the set\_fact instead of debug module as seen below

set\_fact:  
users: “{{ item.0 }}{{ item.1 }}{{ item.2 }}”

with\_together:

- “{{ (user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’) }}”
- “{{ (ansible\_date\_time.epoch|int - ((user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’))|int) / (60_60_24) }}”
- “{{ user\_show.results[item|int].json.result.result.uid[0] }}”

register: res

set\_fact:  
userlist: “{{ item }}”  
loop: “{{ res.results |map(attribute=‘ansible\_facts.users’) |list }}”

Your desired content should now be stored in the userlist variable

Wole

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 8, 2021, 5:53pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/3 "2021-12-08T17:53:41Z")

</div>

The problem with implementing it that way is that the users’s fact is referencing "user\_show.results[item|int], but I can’t add another loop variable. I’m using with\_sequence earlier in the playbook for testing to limit the amount of users queried, and that number is needed for the user\_show.results array.

Harry

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [December 8, 2021, 6:57pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/4 "2021-12-08T18:57:17Z")

</div>

> The problem with implementing it that way is that the users’s fact is referencing "user\_show.results[item|int], but I can’t add another loop variable. I’m using with\_sequence earlier in the playbook for testing to limit the amount of users queried, and that number is needed for the user\_show.results array.

You can use `loop_control` to use names other than `item` for your loop variables. [https://docs.ansible.com/ansible/latest/user\_guide/playbooks\_loops.html#defining-inner-and-outer-variable-names-with-loop-var](https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#defining-inner-and-outer-variable-names-with-loop-var)

​

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 8, 2021, 7:08pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/5 "2021-12-08T19:08:50Z")

</div>

So if I have this:

- name: Set user\_show fact  
set\_fact:  
users: “{{ item.0 }}{{ item.1 }}{{ item.2 }}”  
with\_together:
- “{{ user\_show.results[item|int].json.result.result.uid[0] }}”
- “{{ (user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’) }}”
- “{{ (ansible\_date\_time.epoch|int - ((user\_show.results[item|int].json.result.result.krbpasswordexpiration[0][‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’))|int) / (60_60_24) }}”  
register: res

How do I add/use a loop\_control variable to that? Also, with\_together seems to have been replaced by loop and the zip filter.

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![Oluwole\_Leigh](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@Oluwole\_Leigh](https://forum.ansible.com/u/Oluwole_Leigh)\
**Post date:** [December 9, 2021, 5:00pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/6 "2021-12-09T17:00:49Z")

</div>

Hi,  
I wanted to know why you are using item to retrieve results - “{{ user\_show.results[item|int].json.result.result.uid[0] }}” . since item is useful when you have a loop running. Is it not possible to retrieve the result using json\_query or the map filter ?If that can be done , then we won’t need to bring in the loop\_control variable.From my experience, its better to get the basic stuff (with\_X)to work first before using the latest stuff- loop/zip (filter).

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 9, 2021, 7:04pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/7 "2021-12-09T19:04:08Z")

</div>

For my testing, I’m calling the user\_show IPA API via uri for the first 5 items. The registered variable called “user\_show” has the json value of “user\_show.results.json.result.result.Y” (where X is 0 for the first user, 1 for the second, etc; and Y is the user property (uid, firstname, etc.). I don’t know how to get/retrieve just the uid property of those 5 users, or just the krbpasswordexpiration of those 5 users. I don’t have to do a loop, but nothing I try seems to let me get past the fact that the results json is an array, and I need to reference the particular items of that array.

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![Oluwole\_Leigh](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@Oluwole\_Leigh](https://forum.ansible.com/u/Oluwole_Leigh)\
**Post date:** [December 9, 2021, 9:22pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/8 "2021-12-09T21:22:32Z")

</div>

Can you show a sample of user\_show.results

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 10, 2021, 1:08pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/9 "2021-12-10T13:08:19Z")

</div>

I’m including the playbook below, followed by the relevant output. I have redacted the real data values with dummy values, but it should give you an idea of what I’m trying and what I’m getting.

Thanks,  
Harry

Playbook:

---

<div class="post-metadata">

**Author:** ![Oluwole\_Leigh](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@Oluwole\_Leigh](https://forum.ansible.com/u/Oluwole_Leigh)\
**Post date:** [December 10, 2021, 4:39pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/10 "2021-12-10T16:39:11Z")

</div>

Hi there,  
I created this sample playbook and based on the data you sent.  
I used the mail field because that was not embedded in another key/value pair like krbpasswordexpiration but the principle is basically the same.  
The difference with your playbook is that I used a variable to register the set\_fact . Without that, it would just show the value of the last item in the loop which will overwrite the previous values. By registering the output , I can extract out all the values in the last task.  
There are probably other methods but this one works.

tasks:

- name: lookup  
set\_fact:  
fil: “{{ lookup(‘file’, ‘json.json’) }}”
- name: set  
set\_fact:  
users: “{{ fil |json\_query(‘[_].json.result.result.uid’)|flatten }}"  
pwdexp: "{{ fil |json\_query('[_].json.result.result.mail’)|flatten }}”
- name: sf1  
set\_fact:  
factone: “{{ item.0 }} {{ item.1 }}”  
with\_together:
- “{{ users }}”
- “{{ pwdexp }}”  
register: facttwo
- name: sf2  
set\_fact:  
factthree: “{{ facttwo.results | map(attribute=‘ansible\_facts.factone’)|list }}”
- name: debug  
debug:  
msg: “{{ factthree }}”

The Output is displayed below

ASK [sf1] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> (item=[‘test.user1’, ‘[test.user1@example.com](mailto:test.user1@example.com)’])  
ok: [localhost] =\> (item=[‘test.user2’, ‘[test.user2@example.com](mailto:test.user2@example.com)’])

TASK [sf2] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost]

TASK [debug] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> {  
“msg”: [  
“test.user1 [test.user1@example.com](mailto:test.user1@example.com)”,  
“test.user2 [test.user2@example.com](mailto:test.user2@example.com)”  
]  
}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [December 10, 2021, 7:52pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/11 "2021-12-10T19:52:03Z")

</div>

I finally installed FreeIPA in a VM on my laptop so I could see what you’re seeing. Except for having a self-signed certificate and way less than 1500 users, I think I’ve got something I can test on. A few things to note, though they may not be all that you’re looking for:

- Exclude your ‘admin’ user. It shouldn’t be an issue, but, just in case. 🙂

- I used loop: “{{ uid | json\_query(‘[:20]’) }}” to limit the ‘user\_show’ calls rather than with\_sequence:. Not better or worse, just showing another way to do it. Since we’re both using json\_query later, it has to be available anyway.

- Once you’ve got your show\_user output, you can go straight to a list of users to delete - with their pw expiration dates - in one json\_query. There’s no need to create so many intermediate set\_fact lists.  
I didn’t notice before, but you aren’t doing nested loops after all, so all that stuff I mentioned about loop\_control is irrelevant. Sorry about the rabbit hole.

Here’s my current playbook to produce a list like

- uid: user1  
pwdepx: 20201210012032Z

- uid: user2  
pwdepx: 20181080021425Z  
…  
of just the users who are eligible for deletion. Hope this helps.

- name: Set fact for users  
set\_fact:  
uid: “{{ user\_find.json.result.result|map(attribute=‘uid’)|flatten|difference([‘admin’]) }}”

- name: Run user\_show from IDM API using previously stored session cookie  
uri:  
url: “https://{{idmfqdn}}/ipa/session/json”  
validate\_certs: “{{ validate\_certs }}”  
method: POST  
headers:  
Cookie: “{{ login.set\_cookie }}”  
Referer: “https://{{idmfqdn}}/ipa”  
Content-Type: “application/json”  
Accept: “application/json”  
body\_format: json  
body:  
method: user\_show  
params:

- 
  - “{{ item }}”

- all: true  
version: “{{ api\_vers }}”  
register: user\_show  
loop: “{{ uid | json\_query(‘[:20]’) }}”

- name: Print user\_show variable  
debug:  
msg: “{{ user\_show }}”

- name: Save “{{ cutoff\_days }} days ago” in krbpasswordexpiration. **datetime** format  
set\_fact:  
cutoff\_date: ‘{{ lookup(’‘pipe’‘,  
‘‘date -u --date=“{{ cutoff\_days }} days ago” +%Y%m%d000000Z’’) }}’

- name: Set deletable\_users fact  
set\_fact:  
deletable\_users: “{{ user\_show.results |  
json\_query(‘[\*].json.result.result.{uid: uid[0], pwdexp: krbpasswordexpiration[0]. **datetime** }’) |  
selectattr(‘pwdexp’,‘\<’,cutoff\_date) | list }}”

- name: Print deletable\_users  
debug:  
msg: “{{ deletable\_users }}”

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 10, 2021, 7:56pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/12 "2021-12-10T19:56:26Z")

</div>

OK, I got that to work following your example. Thanks for that. So the next step I’m trying to get to is to determine if the user’s password has been expired for more than 180 days. A negative value means its not expired, and a positive value means that it is expired. I know you used email, but I’m using password expiration (krbpasswordexpiration), and I am actually calculating the password age in the fact at the same time. So now the playbook looks like this:

- name: Grab UID/Password Expiration/Disabled Status from user\_show  
set\_fact:  
users: “{{ user\_show.results|json\_query(‘[_].json.result.result.uid[0]‘)|flatten }}"  
pwdexp: "{{ user\_show.results|json\_query(’[_].json.result.result.krbpasswordexpiration[0]’)|flatten }}”

- name: Combine data into one fact  
set\_fact:  
tmpuserlist1: “{{ item.0 }} {{ (ansible\_date\_time.epoch|int - ((item.1[‘ **datetime** ’] | to\_datetime(‘%Y%m%d%H%M%SZ’)).strftime(‘%s’))|int) / (60_60_24) }}”  
with\_together:

- “{{ users }}”

- “{{ pwdexp }}”  
register: tmpuserlist2

- name: Set Temporary User List fact  
set\_fact:  
userlist: “{{ tmpuserlist2.results|map(attribute=‘ansible\_facts.tmpuserlist1’)|list }}”

- name: Print Final User List  
debug:  
msg: “{{ userlist }}”

Which gives the following:

TASK [Grab UID/Password Expiration/Disabled Status from user\_show] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)]

TASK [Combine data into one fact] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> (item=[u’test.user1’, {u’ **datetime** ’: u’20220103195934Z’}])  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> (item=[u’test.user2’, {u’ **datetime** ’: u’20200218151047Z’}])

TASK [Set Temporary User List fact] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)]

TASK [Print Final User List] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> {  
“msg”: [  
“test.user1 -24.2161574074”,  
“test.user2 660.984386574”  
]  
}

I think that the next step should be to create a list of users who’s age is greater than or equal to 180, then go loop through that list and disable them. But I can’t seem to figure out how to grab the age field now that it’s in the new “userlist” fact. If I try to show each item individually via a loop like this:

- name: Print Final User List  
debug:  
msg: “{{ item }}”  
loop: “{{ userlist }}”

I get:

TASK [Print Final User List] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> (item=test.user1 -24.2126273148) =\> {  
“msg”: “test.user1 -24.2126273148”  
}  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> (item=test.user2 660.987916667) =\> {  
“msg”: “test.user2 660.987916667”  
}

Should I be using the tmpuserlist2 fact that was generated using “with\_together” instead for this loop/process?

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 10, 2021, 8:38pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/13 "2021-12-10T20:38:34Z")

</div>

So a few things that I tried based on Uto’s suggestion: I changed the cutoff days to 30 for testing, and I only look over the first 10 users. I had to change the \< check to \>, but when the disabled\_users fact is printed, It shows the same user all 10 times, almost as if it added the user 10 times. Any ideas?

Harry

- name: Run user\_show from IDM API using previously stored session cookie  
uri:  
url: “https://{{idmfqdn}}/ipa/session/json”  
method: POST  
headers:  
Cookie: “{{ login.set\_cookie }}”  
Referer: “https://{{idmfqdn}}/ipa”  
Content-Type: “application/json”  
Accept: “application/json”  
body\_format: json  
body: “{"method": "user\_show","params": [["{{ uid[item|int] }}"],{"all": true,"version": "{{ api\_vers }}"}]}”  
register: user\_show  
loop: “{{ uid|json\_query(‘[:10]’) }}”

- name: Save “{{ cutoff\_days }}” in Password Expiration format  
set\_fact:  
cutoff\_date: ‘{{ lookup(’‘pipe’‘, ‘‘date -u --date=“{{ cutoff\_days }} days ago” +%Y%m%d000000Z’’) }}’

- name: Print cutoff\_date  
debug:  
msg: “{{ cutoff\_date }}”

- name: Set Disabled Users fact  
set\_fact:  
disabled\_users: “{{ user\_show.results | json\_query(‘[\*].json.result.result.{uid: uid[0], pwdexp: krbpasswordexpiration[0]. **datetime** }’) | selectattr(‘pwdexp’,‘\>’,cutoff\_date) | list }}”

- name: Print disabled users  
debug:  
msg: “{{ disabled\_users }}”

Output:

TASK [Print disabled users] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [[ipaserver.example.com](http://ipaserver.example.com)] =\> {  
“msg”: [  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
},  
{  
“pwdexp”: “20220103195934Z”,  
“uid”: “test.user1”  
}  
]  
}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [December 10, 2021, 8:49pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/14 "2021-12-10T20:49:46Z")

</div>

> So a few things that I tried based on Uto's suggestion: I changed the cutoff days to 30 for testing, and I only look over the first 10 users. I had to change the \< check to \>, but when the disabled\_users fact is printed, It shows the same user all 10 times, almost as if it added the user 10 times. Any ideas?

That is strange. I'll go create some more test users and back-date their pw expiration dates. Hmm.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [December 10, 2021, 9:40pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/15 "2021-12-10T21:40:15Z")

</div>

When you change from with\_sequence to loop: “{{ uid|json\_query(‘[:10]’) }}”, item is no longer an index into the uid list. It’s actual uids. So your body becomes  
body:  
method: user\_show  
params:

- 
  - “{{ item }}”

- all: true  
version: “{{ api\_vers }}”  
register: user\_show  
loop: “{{ uid | json\_query(‘[:20]’) }}”

(And you don’t have to generate the json string yourself. The module will do that for you. Much easier to read/maintain than  
body: “{"method": "user\_show","params": [["{{ item }}"],{"all": true,"version": "{{ api\_vers }}"}]}”  
but I fixed that line just in case you like that better.)

Also, change the ‘\>’ back to ‘\<’. Earlier date strings are ‘\<’ later date strings.

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 11, 2021, 1:45am UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/16 "2021-12-11T01:45:30Z")

</div>

Todd,

Thank you a MILLION! Got it to work, and its much simpler too. I can’t thank you enough for going above and beyond the call in helping me out. I’ll keep working on it next week, but for now its doing exactly what I need it to do at this point. And I picked up a few tricks along the way, like the json\_query(‘[:20]’) and how to use the difference filter to ignore user names I don’t need to check. Great stuff here!

Thanks!  
Harry

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 13, 2021, 2:33pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/17 "2021-12-13T14:33:13Z")

</div>

I have another quick question: I got this to work and it currently shows ALL disabled accounts. I can also grab the nsaccountlock value, which will show True if the account is already disabled and False if it is not. What’d I’d like to do is filter the results to users who’s password has been expired 180 days or longer (selectattr(‘pwdexp’, “\<”,cutoff\_date) AND nsaccountlock is false. How do I specify that in the example you gave using selectattr? My “disabled users” fact is currently:

- name: Set Disabled Users fact  
set\_fact:  
disabled\_users: “{{ user\_show.results | json\_query(‘[\*].json.result.result.{uid: uid[0], mail: mail[0], disabled: nsaccountlock, pwdexp: krbpasswordexpiration[0]. **datetime** }’) | selectattr(‘pwdexp’,‘\<’,cutoff\_date) | list }}”

- name: Print disabled users  
debug:  
msg: “{{ item.uid }} / {{ item.mail }} / {{ item.disabled |ternary(‘Disabled’, ‘Not Disabled’) }} / {{ item.pwdexp }}”  
loop: “{{ disabled\_users }}”

Thanks,  
Harry

---

<div class="post-metadata">

**Author:** ![Oluwole\_Leigh](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@Oluwole\_Leigh](https://forum.ansible.com/u/Oluwole_Leigh)\
**Post date:** [December 13, 2021, 5:14pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/18 "2021-12-13T17:14:29Z")

</div>

Hi there,  
Have you tried using selectattr(‘nsaccountlock’, ‘true’) if the value is logical (True / false) as an extra filter in the set\_fact task?  
Also a long route could be to compare deletable\_users with disabled\_users and use the intersection filter  
{{ **deletable\_users** | intersect(disabled\_users) }}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [December 13, 2021, 9:29pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/19 "2021-12-13T21:29:00Z")

</div>

- name: Set Disabled Users fact  
set\_fact:

disabled\_users: “{{ user\_show.results | json\_query(‘[\*].json.result.result.{uid: uid[0], mail: mail[0], disabled: nsaccountlock, pwdexp: krbpasswordexpiration[0]. **datetime** }’) |  
selectattr(‘pwdexp’, ‘\<’, cutoff\_date) |  
selectattr(‘disabled’, ‘==’, false) | list }}”

---

<div class="post-metadata">

**Author:** ![harry\_devine](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/harry_devine/32/5293_2.png) [@harry\_devine](https://forum.ansible.com/u/harry_devine)\
**Post date:** [December 14, 2021, 3:58pm UTC](https://forum.ansible.com/t/creating-a-fact-array/36082/20 "2021-12-14T15:58:12Z")

</div>

I used “selectattr(‘disabled’,‘equalto’,False)”, but it gave me the desired result. Thanks, I appreciate it!

Harry
