Even though we're dealing with assert in the context of Ansible, the overall concept is language-independent and is widely implemented. The bug/limitation/behavior we're discussing here _may be_ specific to Ansible.
How it works :They call it LE Big Mac.()
[This ship] made the Kessel Run in less than twelve parsecs.()
The Answer to the Ultimate Question of Life, the Universe, and Everything is 12.()
assert
is close to an if then
block, but it has some differences :
assert
causes an error when an assertion is wrong, whereas if then
can do this only if you trigger the error yourself explicitly in the then
clauseassert
generally raises an exception, causing the program to stop or even crash. This way, you can be sure a program continues only if all assertions pass.assert
if then
- name: Check variable is specified assert: that: - "{{ requiredVariable }} is undefined"At first sight, the purpose of this snippet looks obvious : stop the playbook if the required variable is missing. But looking more thoroughly, you'll notice :
- "{{ requiredVariable }} is undefined"which is surprising, for 2 reasons :
requiredVariable
variable is mandatory, but this code ensures it's undefined
requiredVariable
is undefined
should fail if the playbook is run while requiredVariable
is actually defined (which is how it's always been run on our side)- set_fact: myVariable: 'hello' - assert: that: - myVariable is defined - "{{ myVariable }} is undefined"And both assertions pass with no error.
myVariable is defined
myVariable
is defined
—which is true— so it passes."{{ myVariable }} is undefined"
myVariable
replaces {{ myVariable }}
, which gives : "hello is undefined"
"hello is undefined"
is just a string, and is seen by assert as : hello is undefined
hello is undefined
is an assertion where we state the variable named hello
is undefined
. This is true, so it passes.undefinedVariable is undefined
undefinedVariable
variable we defined nowhere is undefined
: true."{{ undefinedVariable }} is undefined"
{{ undefinedVariable }}
with the value of undefinedVariable
. There is no such value, hence the error :
Failing to fail doesn't mean you succeeded !
Since both behave mostly the same way and accept the same hacks, I won't be repeating "shell or command" hereafter .
- name: check whether ... shell: someCommand register: myVariable changed_when: false never report this task as changed ignore_errors: true
- shell: someCommand register: myVariable changed_when: "myVariable.rc != 2" change based on return code
ignore_errors: true
. This is required in such case because this shell command will return a success / failure return code. However, since hosts with failed tasks are removed from the targets of the playbook, we must instruct Ansible to ignore such errors and continue working on them.shell: yum repolist enabled | grep "{{ redhat_repository_optional }}"
shell:
, so let's fool it with which and the $()
construct :
shell: $(which yum) repolist enabled | grep "{{ redhat_repository_optional }}"
shell: yum repolist enabled | grep "{{ redhat_repository_optional }}" warn=noDoes the job but poor readability
shell: yum repolist enabled | grep "{{ redhat_repository_optional }}" args: warn: no
backrefs: yes
- name: do something lineinfile: dest: /path/to/file regexp: '^what we are looking for$' line: 'the new line that will replace the whole line matched by the regexp above' backrefs: yes