We have a particular cron job that we run once a day on each host during business hours. Any particular host uses the same time every day, but across all the hosts those jobs are scheduled fairly evenly throughout the day. We accomplish this by picking the hour and minute for each host with the random()
function, seeding each call to random()
with a value specific and unchanging for each host.
hour: "{{ 19 | random(seed=ansible_machine_id, start=7) }}" # hours between 7 and 18
minute: '{{ 59 | random(seed=ansible_hostname) }}' # minutes between 0 and 59
This has worked for years. (And the jobs are much more evenly spread than expected!)
Recently, ansible-lint
has raised objections to this practice, complaining specifically that both ansible_machine_id
and ansible_hostname
are of type AnsibleUnsafeText
, whereas the he only supported seed types are: None
, int
, float
, str
, bytes
, and bytearray
.
It’s trivially easy to work around. For example, this:
- name: Test some AnsibleUnsafeText re-typing methods
ansible.builtin.debug:
msg:
- "(ansible_machine_id) is a {{ ansible_machine_id | type_debug }} : {{ ansible_machine_id }}"
- "(ansible_machine_id | string) is a {{ ansible_machine_id | string | type_debug }} : {{ ansible_machine_id | string }}"
- "(ansible_machine_id ~ '') is a {{ (ansible_machine_id ~ '') | type_debug }} : {{ (ansible_machine_id ~ '') }}"
- "(ansible_machine_id | regex_replace('a', 'a')) is a {{ ansible_machine_id | regex_replace('a', 'a') | type_debug }} : {{ ansible_machine_id | regex_replace('a', 'a') }}"
produces
- '(ansible_machine_id) is a AnsibleUnsafeText : 245ebab998344152848322cf4c07ba6e'
- '(ansible_machine_id | string) is a NativeJinjaText : 245ebab998344152848322cf4c07ba6e'
- '(ansible_machine_id ~ '''') is a str : 245ebab998344152848322cf4c07ba6e'
- '(ansible_machine_id | regex_replace(''a'', ''a'')) is a str : 245ebab998344152848322cf4c07ba6e'
and ansible-lint
seems happy with these techniques.
My question is: Are any of these methods the Right Way™ to deal with AnsibleUnsafeText
? This feels highly reminiscent of Perl’s “tainted” values and the similar workarounds.
Is the point of AnsibleUnsafeText
simply to make the user aware of possible issues? If so, it seems like it should take an explicit “unsafe_ok
” filter to use such values. As it is, you can “unsafe_var_a ~ unsafe_var_b
” and get a str
. Lots of normal expressions can accidentally employ AnsibleUnsafeText
with the user being none the wiser. Which leaves one wondering: What’s really the point?