refactor: user extraction - #956
Conversation
don't log all users to the terminal 3 times Signed-off-by: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com>
63739c2 to
fa4ba5e
Compare
schurzi
left a comment
There was a problem hiding this comment.
I think i generally like this change. with some minor tweaks it should be equally readable and much nicer in implementation.
| | dict2items | ||
| | rejectattr('key', 'in', os_always_ignore_users) | ||
| | rejectattr('key', 'in', os_ignore_users) | ||
| | json_query( |
There was a problem hiding this comment.
I dislike a bit how we are abusing json_query here, do you think you can convert this to two calls for selectattr?
There was a problem hiding this comment.
The original data of the user is stored as a string array.
Inside a selectattr we can't cast to an int nor do greater/smaller then comparison, as it only works with strings (as far as I'm aware).
So I use the json_query only for the greater/smaller then comparison of the userid as we can do the | int cast in there.
There was a problem hiding this comment.
There is one more nuance to the usage of json_query the userid is stored at index 1 in the array.
With selectattr and rejectattr we can't index into an array.
All ways I've tries give an error:
selectattr('value.1', '>', 0)selectattr('value[1]', '>', 0)selectattr('value'[1], '>', 0)
My previous statement about greater/smaller then comparison is incorrect.
There was a problem hiding this comment.
Hey @Tinyblargon, sorry for taking so long to respond. I really want to find a sensible way to get around using json_query. :)
I have given this some thought and our main problem here is that getent does not return the value for uid as int. Maybe we could solve that by creating a temporary list with the correct datatype:
- name: Extract accounts from local user database
ansible.builtin.set_fact:
system_users: >-
{{ all_users
| rejectattr('0', 'in', os_always_ignore_users)
| rejectattr('0', 'in', os_ignore_users)
| selectattr('1', 'gt', 0)
| selectattr('1', 'le', os_auth_sys_uid_max | int)
| map(attribute='0') | list }}
regular_users: >-
{{ all_users
| rejectattr('0', 'in', os_always_ignore_users)
| rejectattr('0', 'in', os_ignore_users)
| selectattr('1', 'ge', os_auth_uid_min | int)
| selectattr('1', 'le', os_auth_uid_max | int)
| map(attribute='0') | list }}
root_users: >-
{{ all_users | selectattr('1', 'eq', 0) | map(attribute='0') | list }}
vars:
all_users: >-
{{ ansible_facts.getent_passwd.keys() | zip(ansible_facts.getent_passwd.values() | map(attribute=1) | map('int')) | list }}note: I did just some cursory tests on that and it seems to work
WDYT? Also @rndmh3ro you also have very nice oppinions about this kind of stuff. :D
There was a problem hiding this comment.
All (including the current) implementations are hard to read, so I'm impartial there. @schurzi, your solution looks the most readable, however it should get some comments what each of the matches do.
| | dict2items | ||
| | rejectattr('key', 'in', os_always_ignore_users) | ||
| | rejectattr('key', 'in', os_ignore_users) | ||
| | json_query( |
There was a problem hiding this comment.
I dislike a bit how we are abusing json_query here, do you think you can convert this to two calls for selectattr?
There was a problem hiding this comment.
this also seems checked in by accident, can you remove it?
Refactored the user extraction logic to only use jinja filters instead of loops.
Previously the whole list of all users would be printed to the terminal 3 times.
Now we don't print any, removing clutter from the task log.
Not sure if the logging was intentional or an unexpected side-effect.
Tested on a default
Debian 13installation and both implementation returned the same results.Did some benchmarking on a default
Debian 13and the jinja is ~15% faster than the loops.On a default
Debian 13with 1000 normal users the jinja is ~470% faster than the loops.