But I can’t figure out how to access the date string to convert it to a date object. I need it in the form of YYMMDD. If I try to set a fact as follows:
I get an error about the fact being a list and not a string. How do I pull out the date string so I can turn it into a date?
What I’m ultimately trying to do is grab a user’s expiration date, and compare it to the current date. If the date is greater than or equal to 180, I need to disable the account.
TASK [Do you have the time?] *****************************************************************************
task path: /home/utoddl/ansible/date-utc2.yml:40
ok: [localhost] =>
msg:
Thanks for that! I can now reference the datetime member, but now I’m trying to convert that to a datetime object in the format of YYmmdd, but I get an error. Here’s how I’m setting the fact now:
name: Set facts
set_fact:
user_expires: “{{ user_show.json.result.result.krbpasswordexpiration[0][‘datetime’] | to_datetime(‘%Y%m%d’) }}”
When I run the playbook, it gives me the following error in the set_fact play:
FAILED! => {“msg”: "the field ‘args’ has an invalid value ({u’user_expires’: u"{{ user_show.json.result.result.krbpasswordexpiration[0][‘datetime’] | to_datetime(‘%Y%m%d’) }}"}), and could not be converted to an dict.The error was: unconverted data remains: 191401Z\n\n
Just some practical tip, if you find yourself needing to isolate things like some jinja/ansible filters, it can be quickly done using ad hoc:
dick.visser@GA0267 ~$ ansible -m debug -i localhost, all -a “msg={{ ‘20220207191401Z’ | to_datetime(‘%Y%m%d’) }}”
localhost | FAILED! => {
“msg”: “the field ‘args’ has an invalid value ({‘msg’: "{{ ‘20220207191401Z’ | to_datetime(‘%Y%m%d’) }}"}), and could not be converted to an dict.The error was: unconverted data remains: 191401Z”
}
Adjust the pattern:
dick.visser@GA0267 ~$ ansible -m debug -i localhost, all -a “msg={{‘20220207191401Z’|to_datetime(‘%Y%m%d%H%M%SZ’) }}”
localhost | SUCCESS => {
“msg”: “2022-02-07 19:14:01”
}
You don’t need a datetime object. You just need to know if the string you have sorts before or after this string:
‘{{ lookup(’‘pipe’‘, ‘‘date -u --date=“now - 180 days” +%Y%m%d000000Z’’) }}’
I would argue “now - 180 days” is going to be a lot easier to understand next year than whatever “pure Ansible” contortions you come up with to do the same thing.
Let me further clarify what I’m looking to do and show where I’m at. We have some bash scripts that check our IPA server user’s and determines their password age. Any user who has not changed their password in 180 days gets automatically disabled. So that expiration date will be in past. In bash we found an “abs” function to make a negative date calculation a positive value. For example, if a person’s account has been expired since May 19, 2021, that is 182 days ago and should be expired. I’m trying to do something similar with Ansible. But I’m working on the date calculations now before expanding.
So I’m able to get the user’s password expiration date using the IPA APIs, and can set the fact for it as assisted above in this thread. I can also get today’s date using the Ansible facts. What I am having an issue with now is trying to use the facts previously calculated to determine the age, and its not working:
Both utc and today are strings (a.k.a. “AnsibleUnsafeText”), so you can’t subtract one from the other. If they were both Python datetime objects, then you could get a difference like that (or something similar).
I’m evidently not communicating clearly, but please know that I have a lot of sympathy for the frustration you’re encountering with data manipulation in Ansible. Been there; got some scorched t-shirts out of it. I see what you’re trying to do, and, while you’re not wrong, and you can make Ansible do it that way, it involves a lot more “code” than is necessary to solve your problem.
I say that because you don’t need “today” or “age”. Nor do you need to manipulate any of the kerberos password “datetime” values, or convert anything to datetime objects or take their differences. The only new piece of data you need is a string representing the date that was 180 days ago.
Here’s another shot at demonstrating what I’m suggesting.
Thanks for that info! It works pretty much how I need it. Now I need to figure out how to loop through all users in our IPA server, get the password expiration, do the calculations, and then disable where needed. The IPA user_find API method doesn’t return the krbpasswordexpiration. So I may need to do the user find and pull out the user names into a fact, then traverse that using the user_show IPA API method to get the krbpasswordexpiration value, then go from there. Still planning that part out, but this calculation method is a huge step, and I appreciate everyone’s time and effort to help.