| Flag | Usage |
|---|---|
| name | specify which package(s) to install. This can be :
|
- name: "Do something with somePackage" yum: name: "somePackage" state: present
- name: "Do something with somePackage" yum: list: "somePackage" state: installed
present and installed look synonymous and both trigger the installation of somePackage, if missing--- # ANSIBLE_LOCALHOST_WARNING=false ansible-playbook assert_successFailMsg.yml - hosts: 127.0.0.1 connection: local gather_facts: no tasks: - assert: that: true success_msg: "'true' is true" fail_msg: "Only Chuck Norris can do this : {{ 1/0 }}" ...
PLAY [127.0.0.1] ******************************************************************************************* TASK [assert] ********************************************************************************************** An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ZeroDivisionError: division by zero fatal: [127.0.0.1]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""} PLAY RECAP ************************************************************************************************* 127.0.0.1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
success_msg and fail_msg directives are evaluated : fail_msg causes the error whereas success_msg is the one that would be displayedfail_msg directive— is misleading as it suggests assert had a very unexpected result leading to the fail_msg line execution.---
# ANSIBLE_LOCALHOST_WARNING=false ansible-playbook test.yml
- hosts: 127.0.0.1
connection: local
gather_facts: no
tasks:
- name: create temporary file "/tmp/ansible.xxxxxxxx.tmp"
tempfile:
state: file
suffix: '.tmp'
register: myTempFile
- debug:
var: myTempFile.path
- name: delete temporary file
file:
path: "{{ myTempFile.path }}"
state: absent
- name: check temp file is gone
stat:
path: "{{ myTempFile.path }}"
register: checkTempFileIsGone
- debug:
var: checkTempFileIsGone.stat.exists
...
PLAY [127.0.0.1] *********************************************************************************** TASK [create temporary file "/tmp/ansible.xxxxxxxx.tmp"] ******************************************* changed: [127.0.0.1] TASK [debug] *************************************************************************************** ok: [127.0.0.1] => { "myTempFile.path": "/tmp/ansible.ggx0tsvy.tmp" } TASK [delete temporary file] *********************************************************************** changed: [127.0.0.1] TASK [check temp file is gone] ********************************************************************* ok: [127.0.0.1] TASK [debug] *************************************************************************************** ok: [127.0.0.1] => { "checkTempFileIsGone.stat.exists": false } PLAY RECAP ***************************************************************************************** 127.0.0.1 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
---
# ANSIBLE_LOCALHOST_WARNING=false ansible-playbook test.yml -D
- hosts: 127.0.0.1
connection: local
gather_facts: no
tasks:
- name: Make HTTP GET expecting HTTP status 200
uri:
url: http://www.example.com
register: result
until: result.status == 200 in check mode, 'result' does not exist and this task will fail
- name: Make HTTP GET expecting HTTP status 404
uri:
url: http://www.example.com/nosuchpage.html
register: result
ignore_errors: yes
- debug:
var: result.status
...
Python 2.7.13
(nothing)Nope, not installed yet.
TASK [Create a virtual machine] ***********************************
fatal: [localhost]: FAILED! => changed=false
ansible_facts:
discovered_interpreter_python: /usr/bin/python
msg: 'Unknown error while connecting to vCenter or ESXi API at vSphere_host:443 : SmartConnect() got an unexpected keyword argument ''sslContext'''
sslContextPython 2.7.5
python2-pyvmomi.noarch : vSphere Python SDK python34-pyvmomi.noarch : vSphere SDK for Python3.4
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 undefinedrequiredVariable 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) vars:
myVariable: 'hello'
- assert:
that:
- myVariable is defined
- "{{ myVariable }} is undefined"
- undefinedVariable is undefined
- "{{ undefinedVariable }} is undefined"
And the 3 first assertions pass.
myVariable is definedmyVariable 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 undefinedhello is undefined is an assertion where we state the variable named hello is undefined. This is true, so it passes.undefinedVariable is undefinedundefinedVariable 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 !
--- # ANSIBLE_LOCALHOST_WARNING=false ansible-playbook test.yml - hosts: 127.0.0.1 connection: local gather_facts: no tasks: - shell: echo $RANDOM register: shellResult - debug: var: shellResult.stdout empty string since $RANDOM is a Bash variable - shell: bash -c 'echo $RANDOM' register: shellResult - debug: var: shellResult.stdout has a value ...
$HOME) and commands (>, |, &, ...) are NOT supported.Since both behave mostly the same way and accept the same hacks, I won't be repeating shell or command
hereafter .
args keywordcreates or removes :
creates and removes, otherwise, the corresponding tasks are skipped.fr_FR : Quelle page de manuel voulez-vous ? en_US : What manual page do you want? es_MX : ¿Qué página de manual desea? de_DE : Welche Handbuchseiten möchten Sie haben? ja_JP : マニュアルページを指定してください zh_CN : 您需要什么手册页?Workaround : force the output language to english by choosing the "default" C locale :
- name: "A task that makes great things" shell: "some shell command" environment: LANG: C
- 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=no
Does 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