Bookmark this page

Implementing Multiple Plays

Objectives

  • Write a playbook that uses multiple plays and per-play privilege escalation, and effectively use automation content navigator to find new modules in available Ansible Content Collections and use them to implement tasks for a play.

Writing Multiple Plays

A playbook is a YAML file containing a list of one or more plays. Each play in the playbook is written as a top-level list item in the playbook.

A single play is an ordered list of tasks to execute against hosts selected from the inventory. If a playbook contains multiple plays, each play can apply its tasks to a separate set of hosts.

You can create a playbook with multiple plays to orchestrate a complex deployment involving different tasks on different hosts.

The following example shows a playbook with two plays. The first play runs against the ios inventory group, and the second play runs against the junos inventory group.

Although both plays create configuration backups, the plays use different inventory groups and modules from collections that are specific to each network platform.

The configbackups directory must exist.

---
# This is a playbook with two plays

- name: First play - Back up Cisco IOS configurations
  hosts: ios
  gather_facts: false
  tasks:
    # This task uses the ios_config module from the cisco.ios collection.
    - name: Back up IOS configurations
      cisco.ios.ios_config:
        backup: true
        backup_options:
          filename: {{ inventory_hostname }}.cfg
          dir_path: /configbackups

- name: Second play - Back up Juniper Junos configurations
  hosts: junos
  gather_facts: false
  tasks:
    # This task uses the junos_config module from the junipernetworks.junos collection.
    - name: Back up Junos configurations
      junipernetworks.junos.junos_config:
        backup: true
        backup_options:
          filename: {{ inventory_hostname }}.cfg
          dir_path: /configbackups

Privilege Escalation

Many network devices require credentials to enter a privileged mode where you can make configuration changes. You can configure privilege escalation in a play to automatically send privileged credentials to managed nodes.

Use the become Boolean keyword to enable or disable privilege escalation for an individual play or task.

Set become to true to enable privilege escalation, or set it to false to disable it.

become: true

If become is set to true, use the become_method keyword in the play to specify the privilege escalation method to use for that play. For network devices, set the become_method to enable.

become_method: enable

Important

For privilege escalation to work successfully on managed network nodes, you must set the connection type to either connection: ansible.netcommon.network_cli or connection: ansible.netcommon.httpapi.

The connection: ansible.common.netconf connection type does not support privilege escalation. To use this connection type, you must create a user on the managed nodes with the correct privilege level.

You can also enable privilege escalation by configuring the ansible_become and ansible_become_method connection variables. One way to configure these variables is in the inventory file, as shown in the following example:

ansible_network_os: cisco.ios.ios
ansible_connection: ansible.netcommon.network_cli
ansible_become: yes
ansible_become_method: enable
ansible_user: student

Selecting Modules

The large number of modules packaged with Ansible provides you with many tools for common tasks.

The ansible.builtin collection provides modules to copy files, read files from a remote inventory system, use templates to dynamically generate configuration files, and debug playbooks.

The following table lists some useful ansible.builtin modules:

Table 2.2. Ansible Built-in Modules

ModuleDescription
ansible.builtin.copy Copy files from the local machine to remote hosts.
ansible.builtin.fetch Copy files from remote hosts to the local machine.
ansible.builtin.file Create and manage files and directories.
ansible.builtin.lineinfile Ensure a particular line is or is not in a file.
ansible.builtin.slurp Read a file from a remote host.
ansible.builtin.template Dynamically generate text files and transfer them to managed nodes.
ansible.builtin.service Manage Linux services.
ansible.builtin.debug Print statements during playbook execution.
ansible.builtin.get_url Download files over HTTP, HTTPS, or FTP.
ansible.builtin.uri Interact with web services.
ansible.builtin.git Manage git repositories.

The automation execution environment that is used in this course, ee-supported-rhel8, includes several collections for managing network devices. This course uses modules from the following collections:

  • cisco.ios

  • cisco.nxos

  • junipernetworks.junos

  • arista.eos

  • paloalto.panos

Module Documentation

To display a list of the collections and modules available in your current automation execution environment, run the ansible-navigator doc -l command.

[user@host ~]$ ansible-navigator doc -l
...output omitted...
ansible.builtin.copy                      Copy files to remote locations
...output omitted...
cisco.ios.ios_config                      Module to manage configuration sectio...
...output omitted...
cisco.nxos.nxos_command                   Run arbitrary command on Cisco NXOS d...
...output omitted...
junipernetworks.junos.junos_interfaces    Junos Interfaces resource module
...output omitted...

Search the output of this command by typing a slash (/) at the colon prompt followed by the keyword, and then pressing Enter.

Note

For more details on network collections and connection types, visit the Ansible network platform options at https://docs.ansible.com/ansible/latest/network/user_guide/platform_index.html.

As an alternative to running the ansible-navigator collections command in interactive mode, you can use the ansible-navigator doc module_name command to display detailed documentation for a module.

If you specify the -m stdout option, formatted documentation is displayed to your terminal. If you do not specify that option, leaving ansible-navigator in interactive mode, then you can scroll through the documentation in YAML format.

Module documentation includes a description of what the module is for, a list of the attributes that you can use to control the module in a task, examples of how to use the module, and other metadata.

You can also view a summary of all the options you can use with a module by running the ansible-navigator -s doc module_name command:

[user@host ~]$ ansible-navigator -s doc cisco.ios.ios_config
- name: Module to manage configuration sections.
  ios_config:
      after:                 # The ordered set of commands to append to the ...
      backup:                # This argument will cause the module to create...
      backup_options:        # This is a dict object containing configurable...
      before:                # The ordered set of commands to push on to the...
      defaults:              # This argument specifies whether or not to col...
...output omitted...

YAML Syntax

This section investigates some YAML syntax elements that you might see in playbooks.

YAML Comments

You can also use comments to aid readability. In YAML, everything to the right of the number sign (#) is a comment. If there is content to the left of the comment, precede the number sign with a space.

# This is a YAML comment
some data # This is also a YAML comment

YAML Strings

Strings in YAML do not normally need to be put in quotation marks even if the string contains spaces.

this is a string

You must enclose strings in either double or single quotation marks if the string includes a colon character followed by a space.

Escape characters are not parsed in strings enclosed in single quotation marks. You must enclose strings in double quotation marks to parse escape characters such as the newline character (\n).

'Play 1: Configure SNMP settings'
"This is a private system\nUnauthorized use of this system is prohibited"

You can write multiline strings in either of two ways; using the vertical bar (|) character or the greater-than (>) character.

Use the vertical bar (|) character to denote that newline characters within the string are to be preserved.

banner_variable: |
  This system is restricted to authorized users.
  Unauthorized access is prohibited.
  If you are unauthorized, terminate access now.

A newline character is also added to the end of the string. Use (|-) if you do not want a newline character added to the end of the string.

Use the greater-than (>) character to indicate that newline characters are to be converted to spaces and that leading white spaces in the lines are to be removed. This method is often used to break long strings at space characters so that they can span multiple lines for better readability.

config_line: >
  description "This interface connects
  to interface1 on switch2 in the top
  of rack 10 in datacenter 4"

A newline character is still added to the end of the string. Use a greater-than symbol followed by a dash (>-) if you do not want a newline character added to the end of the string.

YAML Dictionaries

Dictionary key-value pairs are typically written as an indented block, as follows:

  name: svcrole
  svcservice: httpd
  svcport: 80

Dictionary key-value pairs can also be written in an inline block format inside braces, as follows:

  {name: svcrole, svcservice: httpd, svcport: 80}

Avoid the inline block format because it is harder to read. However, this format is sometimes used with Ansible roles. When a playbook includes a list of roles, it is more common to use this syntax to make it easier to distinguish roles included in a play from the variables being passed to a role.

YAML Lists

Lists are typically written with the normal single-dash syntax:

  hosts:
    - router1
    - router2
    - router3

Lists can also be written in an inline format in square braces, as follows:

hosts: [router1, router2, router3]

You should avoid this syntax because it is usually harder to read.

Obsolete Playbook Shorthand

Some playbooks might use an earlier shorthand method to define tasks by putting the key-value pairs for the module on the same line as the module name. For example, you might see this syntax:

  tasks:
    - name: Shorthand form
      ansible.builtin.service: name=httpd enabled=true state=started

Normally you would write the same task as follows:

  tasks:
    - name: Normal form
      ansible.builtin.service:
        name: httpd
        enabled: true
        state: started

You should generally avoid the shorthand form and use the normal form. Syntax highlighting tools in text editors such as VS Code can help you more effectively if you use the normal format than if you use the shorthand format.

Revision: do457-2.3-7cfa22a