I’m currently having a var in my ./vars/default.yml, which is used at several points in my playbook for branching installation operations.
boolean_var: true
Depending on this I’m performing (or not) install steps
…
when: not boolean_var
So far so good. I’m also using this var in some j2 templates like so:
{% if boolean_var %}
…
{% endif %}
My problem is, that I mostly forget to set this variable to a proper state, which reflects the real status on the host system, so I have to abort an update.
I would rather like to derive it from a pre_task, checking the existence of a particular file on the host before starting all operations.
Is there a way to define a variable with the same scope (playbook and templates) at runtime?
Well it is easier as I thought. Should have tried by myself before having asked here. Sharing the result. Still need to derive the var from the file stat, but hoping it is possible:
test.yml:
ansible-playbook -l offline -i hosts.cfg test.yml
hosts: all
vars:
test: true
tasks:
name: Copy config file, when test is defined
tags: copy
template:
src: templates/test.j2
dest: test.cfg
when: test
name: Copy config file, when test is not defined
tags: copy
template:
src: templates/test.j2
dest: test.cfg
when: not test
templates/test.j2:
{% if test %}
Test is defined
{% else %}
Test is not defined
{% endif %}
A run with test=true skips the second copy task (as desired) and produces a file, which states “Test is defined” (as desired). The other way around with test=false
Test if there was a previous source installation of KMS
name: Test if there was a KMS source installation running before
stat:
path: ~/.kms_installed_from_source
register: kms_trace
vars:
kms_installed_from_source: ‘{{ true if (kms_trace.stat.exists) else false }}’
tasks:
name: Copy config file, when kms_installed_from_source is defined
tags: copy
template:
src: templates/test.j2
dest: test.cfg
when: kms_installed_from_source
name: Copy config file, when kms_installed_from_source is not defined
tags: copy
template:
src: templates/test.j2
dest: test.cfg
when: not kms_installed_from_source
name: Print
debug:
msg:
‘Status of “kms_installed_from_source”: {{ kms_installed_from_source}}’
./templates/test.j2:
{% if kms_installed_from_source %}
kms_installed_from_source is defined
{% else %}
kms_installed_from_source is not defined
{% endif %}
Which is if you look closely what I wrote. Similar to what I said . Register the results from stat. Feed that into template. Thank you for taking my suggestion.
pre_tasks:
# Test if there was a previous source installation of KMS
- name: Test if there was a KMS source installation running before
stat:
path: ~/.kms_installed_from_source
register: kms_trace
vars:
kms_installed_from_source: '{{ true if (kms_trace.stat.exists) else false }}'
You have the 'vars' section after 'pre_tasks', giving the impression
that this matters, while it doesn't.
It can be anywhere.
However, while it can be listed anywhere, it won't always work,
because kms_installed_from_source won't be available if used in tasks
that are earlier than the 'stat' task.
Things will be less ambiguous if you use a set_fact task, so it is
clear where the variable is actually set.
Regarding 'pre_tasks' (as well as post_tasks), I find those somewhat
confusing. I always have just 'tasks' and then the order of the tasks
is as they appear in that list. I'm saying because I've seen
post_tasks being put at the beginning, and the other way around.
The "true if (kms_trace.stat.exists) else false" is unnecessary as
stat.exists is already a boolean.
Concluding, if you must use a dedicated variale, then this task (as
part of just 'tasks') should be sufficient:
The reason for having vars after stat is that I feared the “not defined” issue. I never tried to have vars before, but since I will try your set_fact approach, this doesn’t matter either.
pre_task btw is just to have a means to print out some installation variables for quick check in order to be able to react and abort the installation, if something is not as desired.
It is also quite handy, if you for instance use foreign roles (like geerlinguys node js installer). That needs an apt-cache update on bionic, before the role jumps in. So I sometimes find it helpful to have an early quick spot on something.