Introduction to modules
• Modules (also referred to as “task plugins” or “library plugins”) are discrete units of
code that can be used from the command line or in a playbook task.
• Ansible executes each module, usually on the remote managed node, and collects
return values.
• In Ansible 2.10 and later, most modules are hosted in collections.
• You can execute modules from the command line.
• ansible webservers -m service -a "name=httpd state=started"
• ansible webservers -m ping
• ansible webservers -m command -a "/sbin/reboot -t now"
• Each module supports arguments. Nearly all modules take key=value arguments, space
delimited. Some modules take no arguments, and the command/shell modules simply
take the string of the command you want to run.
• From playbooks, Ansible modules are executed in a very similar way.
- name: reboot the servers
command: /sbin/reboot -t now
• Another way to pass arguments to a module is using YAML syntax, also called ‘complex args’.
- name: restart webserver
service:
name: httpd
state: restarted
• All modules return JSON format data.
• This means modules can be written in any programming language. Modules should be idempotent,
and should avoid making any changes if they detect that the current state matches the desired final
state.
• When used in an Ansible playbook, modules can trigger ‘change events’ in the form of notifying
handlers to run additional tasks.
• You can access the documentation for each module from the command line with the ansible-doc tool.
• ansible-doc yum
• For a list of all available modules, see the Collection docs, or run the following at a command prompt.
• ansible-doc -l
Introduction to ad hoc
commands
• An Ansible ad hoc command uses the /usr/bin/ansible command-line
tool to automate a single task on one or more managed nodes.
• ad hoc commands are quick and easy, but they are not reusable.
• ad hoc commands demonstrate the simplicity and power of Ansible
Why use ad hoc commands?
• ad hoc commands are great for tasks you repeat rarely.
• For example, if you want to power off all the machines in your lab for
Christmas vacation, you could execute a quick one-liner in Ansible
without writing a playbook.
• An ad hoc command looks like this:
• $ ansible [pattern] -m [module] -a "[module options]"
• The -a option accepts options either through the key=value syntax or
a JSON string starting with { and ending with } for more complex
option structure.
Use cases for ad hoc tasks
• Rebooting servers
• The default module for the ansible command-line utility is the
[Link] module.
• You can use an ad hoc task to call the command module and reboot all
web servers in Atlanta, 10 at a time.
• Before Ansible can do this, you must have all servers in Atlanta listed in
a group called [atlanta] in your inventory, and you must have working
SSH credentials for each machine in that group.
• To reboot all the servers in the [atlanta] group:
• $ ansible atlanta -a "/sbin/reboot"
• /usr/bin/ansible will default to running from your user account. To
connect as a different user:
• $ ansible atlanta -a "/sbin/reboot" -f 10 -u username
• Rebooting probably requires privilege escalation. You can connect to
the server as username and run the command as the root user by
using the become keyword:
• $ ansible atlanta -a "/sbin/reboot" -f 10 -u username --become [--ask-
become-pass]
• If you add --ask-become-pass or -K, Ansible prompts you for the
password to use for privilege escalation (sudo/su/pfexec/doas/etc).
• To use a different module, pass -m for module name. For example, to
use the [Link] module:
• $ ansible raleigh -m [Link] -a 'echo $TERM'
Managing files
• An ad hoc task can harness the power of Ansible and SCP to transfer
many files to multiple machines in parallel. To transfer a file directly to
all servers in the [atlanta] group:
• $ ansible atlanta -m [Link] -a "src=/etc/hosts
dest=/tmp/hosts"
• If you plan to repeat a task like this, use the [Link]
module in a playbook.
• The [Link] module allows changing ownership and permissions on
files. These same options can be passed directly to the copy module as well:
• $ ansible webservers -m [Link] -a "dest=/srv/foo/[Link] mode=600"
• $ ansible webservers -m [Link] -a "dest=/srv/foo/[Link] mode=600
owner=mdehaan group=mdehaan"
• The file module can also create directories, similar to mkdir -p:
• $ ansible webservers -m [Link] -a "dest=/path/to/c mode=755
owner=mdehaan group=mdehaan state=directory"
• As well as delete directories (recursively) and delete files:
• $ ansible webservers -m [Link] -a "dest=/path/to/c state=absent"
Managing packages
• You might also use an ad hoc task to install, update, or remove packages on managed nodes
using a package management module such as yum.
• Package management modules support common functions to install, remove, and generally
manage packages.
• To ensure a package is installed without updating it:
$ ansible webservers -m [Link] -a "name=acme state=present"
• To ensure a specific version of a package is installed:
$ ansible webservers -m [Link] -a "name=acme-1.5 state=present"
• To ensure a package is at the latest version:
$ ansible webservers -m [Link] -a "name=acme state=latest"
• To ensure a package is not installed:
$ ansible webservers -m [Link] -a "name=acme state=absent"
Managing users and groups
• You can create, manage, and remove user accounts on your managed
nodes with ad hoc tasks:
• $ ansible all -m [Link] -a "name=foo password=<encrypted
password here>"
• $ ansible all -m [Link] -a "name=foo state=absent"
• See the [Link] module documentation for details on all of
the available options, including how to manipulate groups and group
membership
Managing services
• Ensure a service is started on all webservers:
$ ansible webservers -m [Link] -a "name=httpd
state=started"
• Alternatively, restart a service on all webservers:
$ ansible webservers -m [Link] -a "name=httpd
state=restarted"
• Ensure a service is stopped:
$ ansible webservers -m [Link] -a "name=httpd
state=stopped"
Gathering facts
• Facts represent discovered variables about a system.
• You can use facts to implement conditional execution of tasks but also just to get ad hoc
information about your systems.
• To see all facts:
$ ansible all -m [Link]
• You can also filter this output to display only certain facts, see the [Link] module
documentation for details.
Check mode
• In check mode, Ansible does not make any changes to remote systems. Ansible prints the
commands only. It does not run the commands.
$ ansible all -m copy -a "content=foo dest=/root/[Link]" -C
• Enabling check mode (-C or --check) in the above command means Ansible does not actually
create or update the /root/[Link] file on any remote systems.
Reference
• [Link]
intro_adhoc.html#intro-adhoc
Ansible Roles
• Ansible material can be arranged and reused using Ansible roles.
• They usually include a collection of variables, handlers, tasks, and
templates used to carry out a particular activity, like setting up an
application or installing and configuring a web server.
• Ansible playbooks can be made more modular and reusable by using
roles.
• To deploy many web apps, you could, for instance, build a role for
installing and configuring the Apache web server and then utilize that
role repeatedly in different playbooks.
• Sharing Ansible material with other people is another way to use roles.
To make your roles available for usage in other people's playbooks, you
can publish them to Ansible Galaxy, a public repository for Ansible roles.
• Ansible roles provide a well-defined framework and structure for
setting your tasks, variables, handlers, metadata, templates, and
other files. They enable us to reuse and share our Ansible code
efficiently. This way, we can reference and call them in our playbooks
with just a few lines of code while we can reuse the same roles over
many projects without the need to duplicate our code.
• Organizing our Ansible content into roles provides a more
manageable structure than using playbooks alone.
Roles
• With roles, you get a standardized structure for bundling related
tasks, variables, templates, handlers, and files, and this enhances
reusability.
• Roles follow a defined directory structure; a role is named by the top
level directory. Some of the subdirectories contain YAML files, named
[Link].
• The files and templates subdirectories can contain objects referenced
by the YAML files.
• An example project structure could look like this, the name of the role
would be "apache":
• To create a well-defined role directory
structure skeleton, we can leverage the
command
ansible-galaxy init <your_role_name>
Ex:
ansible-galaxy init apache
• By default, Ansible will look in most role directories for a [Link] file for
relevant content (also [Link] and main):
• tasks/[Link] - A list of tasks that the role provides to the play for execution.
• handlers/[Link] - handlers that are imported into the parent play for use by
the role or other roles and tasks in the play.
• defaults/[Link] - very low precedence values for variables provided by the role
(see Using variables for more information). A role’s own defaults will take priority
over other role’s defaults, but any/all other variable sources will override this.
• vars/[Link] - high precedence variables provided by the role to the play (see
Using variables for more information).
• files/[Link] - one or more files that are available for the role and it’s children.
• templates/something.j2 - templates to use in the role or child roles.
• meta/[Link] - metadata for the role, including role dependencies and optional
Galaxy metadata such as platforms supported. This is required for uploading into
galaxy as a standalone role, but not for using the role in your play.
• roles/webserver/tasks/[Link]
Using roles
• You can use roles in the following ways:
• at the play level with the roles option: This is the classic way of using roles in a play.
• at the tasks level with include_role: You can reuse roles dynamically anywhere in the tasks
section of a play using include_role.
• at the tasks level with import_role: You can reuse roles statically anywhere in the tasks section
of a play using import_role.
• as a dependency of another role (see the dependencies keyword in meta/[Link] in this same
page).
Using roles at the play level
• The classic (original) way to use roles is with the roles option for a given play:
---
- hosts: webservers
roles:
- common
- webservers
When you use the roles option at the play level, Ansible treats the roles as static imports and
Including roles: dynamic reuse
• You can reuse roles dynamically anywhere in the tasks section of a play using include_role.
• While roles added in a roles section run before any other tasks in a play, included roles run in the
order they are defined.
• If there are other tasks before an include_role task, the other tasks will run first.
• To include a role:
---
- hosts: webservers
tasks:
- name: Print a message
[Link]:
msg: "this task runs before the example role"
- name: Include the example role
include_role:
name: example
- name: Print a message
[Link]:
• You can pass other keywords, including variables and tags, when including roles:
---
- hosts: webservers
tasks:
- name: Include the foo_app_instance role
include_role:
name: foo_app_instance
vars:
dir: '/opt/a'
app_port: 5000
tags: typeA
# ...
Importing roles: static reuse
• You can reuse roles statically anywhere in the tasks section of a play using import_role.
• The behavior is the same as using the roles keyword. For example:
---
- hosts: webservers
tasks:
- name: Print a message
[Link]:
msg: "before we run our role"
- name: Import the example role
import_role:
name: example
- name: Print a message
[Link]:
• The various [Link] files contain content depending on their location in the
directory structure shown above.
• For instance, vars/[Link] references variables, handlers/[Link] describes
handlers, and so on.
• Note that in contrast to playbooks, the [Link] files only contain the specific content
and not additional playbook information like hosts, become or other keywords.
• Using roles in a Playbook is straight forward:
---
- name: launch roles
hosts: web
roles:
- role1
- role2
• For each role, the tasks, handlers and variables of that role will be included in the
Playbook, in that order.
• Create a Basic Role Directory Structure
• Ansible looks for roles in a subdirectory called roles in the project
directory. This can be overridden in the Ansible configuration. Each role
has its own directory. To ease creation of a new role the tool ansible- roles/
galaxy can be used. └── apache_vhost
├── defaults
• Ansible Galaxy is a hub for finding, reusing and sharing the best Ansible │ └── [Link]
content. ansible-galaxy helps to interact with Ansible Galaxy. ├── files
• Build a role that installs and configures Apache to serve a virtual host. ├── handlers
│ └── [Link]
Run these commands in your ~/ansible-files directory: ├── meta
│ └── [Link]
• [user@control ansible-files]$ mkdir roles ├── [Link]
├── tasks
• [user@control ansible-files]$ ansible-galaxy init --offline │ └── [Link]
roles/apache_vhost ├── templates
├── tests
• Have a look at the role directories and their content:
│ ├── inventory
│ └── [Link]
• [user@control ansible-files]$ tree roles └── vars
└── [Link]
Create the Tasks File
• The [Link] file in the tasks subdirectory of file:
the role should do the following:
---
• Make sure httpd is installed - name: install httpd
• Make sure httpd is started and enabled yum:
• Put HTML content into the Apache document name: httpd
root
state: latest
• Install the template provided to configure the
vhost
• The [Link] (and other files possibly - name: start and enable httpd service
included by [Link]) can only contain tasks, service:
not complete playbooks! name: httpd
state: started
• Edit the roles/apache_vhost/tasks/[Link] enabled: true
apache/
├── defaults
│ └── [Link]
├── files
├── handlers
│ └── [Link]
├── meta
│ └── [Link]
├── [Link]
├── tasks
│ └── [Link]
├── templates
├── tests
│ ├── inventory
│ └── [Link]
└── vars
└── [Link]
Handlers
• Sometimes when a task does make a change to the system, an additional task
or tasks may need to be run.
• For example, a change to a service’s configuration file may then require that
the service be restarted so that the changed configuration takes effect.
• Handlers can be seen as inactive tasks that only get triggered when
explicitly invoked using the "notify" statement.
• As a an example, let’s write a playbook that:
• manages Apache’s configuration file /etc/httpd/conf/[Link] on all hosts in the
web group
• restarts Apache when the file has changed
• First we need the file Ansible will deploy, let’s just take the one from node1.
Remember to replace the IP address shown in the listing below with the IP
address from your individual node1.
• Next, create the Playbook - restart_apache
httpd_conf.yml. handlers:
--- - name: restart_apache
- name: manage [Link] service:
hosts: web name: httpd
become: true state: restarted
tasks: • The "notify" section calls the
- name: Copy Apache configuration handler only when the copy task
file actually changes the file.
copy: • That way the service is only
src: [Link] restarted if needed - and not each
time the playbook is run.
dest: /etc/httpd/conf/
• The "handlers" section defines a
notify: task that is only run on notification.
Reference
• [Link]