1) Debug module
This module prints statements during execution and can
be useful for debugging variables or expressions without necessarily halting
the playbook. Useful for debugging together with the ‘when:’ directive.
Options : msg, var
Examples:
2) Ansible dry run
# ansible-playbook foo.yml --check
Enabling/Disabling check mode in task
tasks:
- name: this
task will make changes to the system even in check mode
command: /something/to/run
--even-in-check-mode
check_mode: no
- name: this
task will always run under checkmode and not change the system
lineinfile:
line="important config" dest=/path/to/myconfig.conf state=present
check_mode:
yes
--even-in-check-mode : which is only allowed in the
following modules: command, win_command, shell, win_shell ,
script, include, include_vars, add_host, group_by,
set_fact, raw, meta
3) Showing Differences
--diff -
Will do the changes and shows us what is changed now after running the yaml
file
Example : # ansible-playbook
template_and_modify.yml --diff
PLAY [ss]
**********************************************************************
TASK [setup]
*******************************************************************
ok: [l0210]
TASK [compare file and restore if modified.]
***********************************
--- before
+++ after: dynamically generated
@@ -1,0 +1,1 @@
+/tmp *(rw,sync)
changed: [l0210]
PLAY RECAP
*********************************************************************
l0210 : ok=2 changed=1
unreachable=0 failed=0
4) Prompts
When running a playbook, you may wish to prompt the
user for certain input, and can do so with the ‘vars_prompt’ section.
A common use for this might be for asking for
sensitive data that you do not want to record.
This has uses beyond security, for instance, you may
use the same playbook for all software releases
and would prompt for a particular release version in a
push-script.
Here is a most basic example:
---
- hosts: all
remote_user:
root
vars:
from:
"camelot"
vars_prompt:
- name:
"name"
prompt:
"what is your name?"
- name:
"quest"
prompt:
"what is your quest?"
- name:
"favcolor"
prompt:
"what is your favorite color?"
Note :
Prompts for individual vars_prompt variables will be
skipped for any variable that is already defined through the command line
--extra-vars option, or when running from a non-interactive session (such as
cron or Ansible Tower)
Start and Step
This shows a few alternative ways to run playbooks. These modes are very useful for testing new plays or debugging.
Start-at-task If you want to start executing your playbook at a particular task, you can do so with the
--start-at-task option:
# ansible-playbook playbook.yml
--start-at-task="install packages"
The above will start executing your playbook at a task named “install packages”.
Step
Playbooks can also be executed interactively with --step:
# ansible-playbook playbook.yml --step
This will cause ansible to stop on each task, and ask if it should execute that task. Say you
had a task called “configure ssh”, the playbook run
will stop and ask:
Perform task:
configure ssh (y/n/c):
Answering “y” will execute the task, answering “n”
will skip the task, and answering “c” will
continue executing all the remaining tasks without
asking.
Tags
If you have a large playbook it may become useful to
be able to run a specific part of the configuration without running the whole
playbook.
Both plays and tasks support a “tags:” attribute for
this reason. You can ONLY filter tasks based on tags from the command line with
--tags or --skip-tags. Adding “tags:” in any part of a play (including roles)
adds those tags to the contained tasks.
Example:
tasks:
- yum:
name={{ item }} state=installed
with_items:
- httpd
-
memcached
tags:
-
packages
-
template: src=templates/src.j2 dest=/etc/foo.conf
tags:
-
configuration
If you wanted to just run the “configuration” and
“packages” part of a very long playbook, you could
do this:
ansible-playbook example.yml --tags
"configuration,packages"
On the other hand, if you want to run a playbook
without certain tasks, you could do this:
ansible-playbook example.yml --skip-tags
"notification"
Tag Reuse
You can apply the
same tag name to more than one task, in the same file
or included files. This
will run all tasks with that tag.
Example:
---
# file:
roles/common/tasks/main.yml
- name: be sure ntp
is installed
yum: name=ntp
state=installed
tags: ntp
- name: be sure ntp
is configured
template:
src=ntp.conf.j2 dest=/etc/ntp.conf
notify:
- restart
ntpd
tags: ntp
- name: be sure ntpd
is running and enabled
service: name=ntpd state=started enabled=yes
tags: ntp
Tag Inheritance
You can apply tags to
more than tasks, but they ONLY affect the tasks
themselves. Applying tags
anywhere else is just a convenience so you don’t have
to write it on every
task:
- hosts: all
tags:
- bar
tasks:
...
- hosts: all
tags: ['foo']
tasks:
...
You may also apply
tags to roles:
roles:
- { role:
webserver, port: 5000, tags: ['web', 'foo' ] }
And include
statements:
- include: foo.yml
tags:
[web,foo]
All of these apply
the specified tags to EACH task inside the play,
included file, or role, so
that these tasks can be selectively run when the
playbook is invoked with the
corresponding tags.
Special Tags
There is a special
always tag that will always run a task, unless
specifically skipped
(--skip-tags always)
Example:
tasks:
- debug:
msg="Always runs"
tags:
- always
- debug:
msg="runs when you use
tag1"
tags:
- tag1
Rolling Update Batch
Size
By default, Ansible
will try to manage all of the machines referenced in a
play in parallel. For a
rolling updates use case, you can define how many
hosts Ansible should manage
at a single time by using the ”serial” keyword:
- name: test play
hosts:
webservers
serial: 3
In the above example,
if we had 100 hosts, 3 hosts in the group ‘webservers’
would complete the play
completely before moving on to the next 3 hosts.
The ”serial” keyword
can also be specified as a percentage in Ansible 1.8 and later, which will be applied to the total number of hosts in a play, in order to determine the number of hosts per pass:
- name: test play
hosts: webservers
serial:
"30%"
If the number of hosts does not divide equally into the number of passes, the final pass will contain the remainder. As of Ansible 2.2, the batch sizes can be specified as a list, as follows:
- name: test play
hosts:
webservers
In the above example,
the first batch would contain a single host, the next
would contain 5 hosts, and (if there are any hosts left), every following batch
would contain 10 hosts until all available hosts are
used. It is also possible to list multiple batch sizes as percentages:
used. It is also possible to list multiple batch sizes as percentages:
- name: test play
hosts:
webservers
serial:
-
"10%"
-
"20%"
-
"100%"
You can also mix and match the values:
- name: test play
hosts:
webservers
serial:
- 1
- 5
-
"20%"
Note : No matter how small the percentage, the number of hosts per pass will always be 1 or greater. Maximum Failure Percentage New in version 1.3. By default, Ansible will continue executing actions as long as there are hosts in the group that have not yet failed. In some situations, such as with the rolling updates described above, it may be desirable to abort the play when a certain threshold of failures have been reached. To achieve this, as of version 1.3 you can set a maximum failure percentage on a play as follows:
- hosts: webservers
max_fail_percentage: 30
serial: 10
fetch - Fetches a
file from remote nodes
This module works
like copy, but in reverse. It is used for fetching
files from remote machines
and storing them locally in a file tree, organized by
hostname.
A directory to save
the file into. For example, if the dest directory is
/backup a src file named
/etc/profile on host host.example.com, would be saved
into
/backup/host.example.com/etc/profile
fail_on_missing
When set to 'yes',
the task will fail if the remote file cannot be read
for any reason. Prior to
Ansible-2.4, setting this would only fail if the
source file was missing.
The default was
changed to "yes" in Ansible-2.4.
5) when statement
The When Statement
Sometimes you will want to skip a particular step on a
particular host. This could be something as simple as not installing a certain
package if the operating system is a
particular version, or it could be something like
performing some cleanup steps if a filesystem is getting full.
This is easy to do in
Ansible with the when clause, which contains a raw
Jinja2 expression without
double curly braces (see Variables). It’s actually
pretty simple:
tasks:
- name:
"shut down Debian flavored
systems"
command:
/sbin/shutdown -t now
when:
ansible_os_family == "Debian"
# note that
Ansible facts and vars like ansible_os_family can be used
# directly
in conditionals without double curly braces
You can also use parentheses to group conditions:
tasks:
- name:
"shut down CentOS 6 and Debian 7 systems"
command:
/sbin/shutdown -t now
when:
(ansible_distribution == "CentOS" and
ansible_distribution_major_version == "6") or (ansible_distribution
== "Debian" and ansible_distribution_major_version == "7")
Multiple conditions
that all need to be true (a logical ‘and’) can also be
specified as a list:
tasks:
- name:
"shut down CentOS 6 systems"
command:
/sbin/shutdown -t now
when:
- ansible_distribution ==
"CentOS"
- ansible_distribution_major_version ==
"6"
6) register statement
Registered Variables
Another major use of variables is running a command
and using the result of that command to save the
result into a variable. Results will vary from module
to module. Use of -v when executing playbooks will show possible values for the
results.
The value of a task being executed in ansible can be
saved in a variable and used later. See some
examples of this in the Conditionals chapter.
While it’s mentioned elsewhere in that document too,
here’s a quick syntax example:
- hosts: web_servers
tasks:
- shell:
/usr/bin/foo
register:
foo_result
ignore_errors: True
- shell:
/usr/bin/bar
when:
foo_result.rc == 5
Registered variables
are valid on the host the remainder of the playbook
run, which is the same as
the lifetime of “facts” in Ansible. Effectively
registered variables are just
like facts.
When using register
with a loop the data structure placed in the variable
during a loop, will
contain a results attribute, that is a list of all
responses from the module.
For a more in-depth example of how this works, see the
Loops section on using
register with a loop.
The register
statement is used to store the output of a single task
into a variable. The
exact contents of the registered variable can vary widely
depending on the type
of task (for example a shell task will include stdout
& stderr output from
the command you run in the registered variable, while
the stat task will
provide details of the file that is passed to the
task)
7) stderr and stdout
Want to run a shell command do something with the output?
Registered variables
have useful attributes like :
changed – set to
boolean true if something happened (useful to tell
when a task has done
something on a remote machine).
stderr – contains
tringy output from stderr
stdout – contains
stringy output from stdout
stdout_lines –
contains a list of lines (i.e. stdout split on \n).
8) debug statement
I think you can register the result to a variable, then print with debug.
- name: print to stdout
command: echo
"hello"
register:
hello
- debug: msg="{{ hello.stdout }}"
- debug: msg="{{ hello.stderr }}"