Learning Ansible 2.7(Third Edition)
上QQ阅读APP看书,第一时间看更新

Studying the anatomy of a playbook

Playbooks can have a list of remote hosts, user variables, tasks, handlers, and so on. You can also override most of the configuration settings through a playbook. Let's start looking at the anatomy of a playbook.

The purpose of the playbook that we are going to consider now is to ensure that the httpd package is installed and the service is enabled and started. This is the content of the setup_apache.yaml file:


- hosts: all
remote_user: vagrant
tasks:
- name: Ensure the HTTPd package is installed
yum:
name: httpd
state: present
become: True
- name: Ensure the HTTPd service is enabled and running
service:
name: httpd
state: started
enabled: True
become: True

The setup_apache.yaml file is an example of a playbook. The file is comprised of three main parts, as follows:

  • hosts: This lists the host or host group that we want to run the task against. The hosts field is required. It is used by Ansible to determine which hosts will be targeted by the listed tasks. If a host group is provided instead of a host, Ansible will try to look up the hosts belonging to it based on the inventory file. If there is no match, Ansible will skip all the tasks for that host group. The --list-hosts option, along with the playbook (ansible-playbook <playbook> --list-hosts), will tell you exactly which hosts the playbook will run against.
  • remote_user: This is one of the configuration parameters of Ansible (consider, for example, tom' - remote_user) that tells Ansible to use a particular user (in this case, tom) while logging into the system.
  • tasks: Finally, we come to tasks. All playbooks should contain tasks. Tasks are a list of actions that you want to perform. A tasks field contains the name of the task (that is, the help text for the user about the task), a module that should be executed, and arguments that are required for the module. Let's look at the single task that is listed in the playbook, as shown in the preceding snippet of code.
All examples in the book would be executed on CentOS, but the same set of examples with a few changes would work on other distributions as well.

In the preceding case, there are two tasks. The name parameter represents what the task is doing and is present mainly to improve readability, as we'll see during the playbook run. The name parameter is optional. The yum and service modules have their own set of parameters. Almost all modules have the name parameter (there are exceptions, such as the debug module), which indicates what component the actions are performed on. Let's look at the other parameters:

  •  The state parameter holds the latest value in the yum module, and it indicates that the httpd package should have been installed. The command to execute roughly translates to yum install httpd.
  • In the service module's scenario, the state parameter with the started value indicates that the httpd service should be started, and it roughly translates to a /etc/init.d/httpd start. In this module, we also have the enabled parameter, which defines whether the service should start at boot or not.
  • The become: True parameter represents the fact that the tasks should be executed with sudo access. If the sudo user's file does not allow the user to run the particular command, then the playbook will fail when it is run.
You might have questions about why there is no package module that figures out the architecture internally and runs the yum, apt, or any other package options depending on the architecture of the system. Ansible populates the package manager value into a variable named ansible_pkg_manager.

In general, we need to remember that the number of packages that have a common name across different operating systems are a small subset of the number of packages that are actually present. For example, the httpd package is called httpd in Red Hat systems, but is called  apache2 in Debian-based systems. We also need to remember that every package manager has its own set of options that make it powerful; as a result, it makes more sense to use explicit package manager names so that the full set of options are available to the end user writing the playbook.