Playbook Modules

Ansible consist of many pre-built modules that helps us to create playbooks. For example,

  • set_fact

  • pause

  • prompt

  • wait_for

  • assemble

  • add_host

  • group_by

  • fetch

set_fact

This module allows us to add or change facts during the execution.

For example if we consider the below playbook,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Set a fact
      set_fact:
        our_fact: Ansible Rocks!

    - name: Show custom fact
      debug:
        msg: "{{ our_fact }}"

# Three dots indicate the end of a YAML document
...

In the first task we are setting a fact with the name out_fact and in the second task we print it's value using the debug module.

In addition to that, we can set multiple facts in the same iteration of the set_fact module. For example, let's modify our playbook in such a way,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Set a fact
      set_fact:
        our_fact: Ansible Rocks!
        ansible_distribution: "{{ ansible_distribution | upper }}"

    - name: Show our_fact
      debug:
        msg: "{{ our_fact }}"

    - name: Show ansible_distribution
      debug:
        msg: "{{ ansible_distribution }}"

# Three dots indicate the end of a YAML document
...

Then, let's assume that we have to set facts conditionally, for example, based on the environment. In such cases, we can do this by using the when key word along with the set_fact module,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Set our installation variables for CentOS
      set_fact:
        webserver_application_port: 80
        webserver_application_path: /usr/share/nginx/html
        webserver_application_user: root
      when: ansible_distribution == 'CentOS'

    - name: Set our installation variables for Ubuntu
      set_fact:
        webserver_application_port: 8080
        webserver_application_path: /var/www/html
        webserver_application_user: nginx
      when: ansible_distribution == 'Ubuntu'

    - name: Show pre-set distribution based facts
      debug:
        msg: "webserver_application_port:{{ webserver_application_port }} webserver_application_path:{{ webserver_application_path }} webserver_application_user:{{ webserver_application_user }}"

# Three dots indicate the end of a YAML document
...

pause module allows us to temporarily stop the playbook execution for a specified time period. It is also possible to interrput the pause by clieck control+C keys. For example,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Pause our playbook for 10 seconds
      pause:
        seconds: 10

# Three dots indicate the end of a YAML document
...

Running this playbook will output the following:

$ ansible-playbook pause_playbook.yaml 

PLAY [ubuntu3,centos3] ****************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [ubuntu3]
ok: [centos3]

TASK [Pause our playbook for 10 seconds] **********************************************
Pausing for 10 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [ubuntu3]

PLAY RECAP ****************************************************************************
centos3                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu3                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

In a situation where we have to take a manual action, we can use the pause module with prompt option. This will allow us to show a message to the user and ask to perform an action. For example,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Prompt user to verify before continue
      pause:
        prompt: Please check that the webserver is running, press enter to continue

# Three dots indicate the end of a YAML document
...

Running this playbook will result in the following output,

 ansible-playbook pause_playbook.yaml 

PLAY [ubuntu3,centos3] **********************************************************

TASK [Gathering Facts] **********************************************************
ok: [centos3]
ok: [ubuntu3]

TASK [Prompt user to verify before continue] ************************************
[Prompt user to verify before continue]
Please check that the webserver is running, press enter to continue:
ok: [ubuntu3]

PLAY RECAP **********************************************************************
centos3                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu3                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

In some cases when we want to wait for certian operations to be completed, we could use the wait_for module rather than using pause. For example, in a situation where we have to wait until a port becomes available.

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu3,centos3

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Wait for the webserver to be running on port 80
      wait_for:
        port: 80

# Three dots indicate the end of a YAML document
...

assemble module allows us to concatenate multiple files into one. For example, imagin a situation where we keep a comman ssh config file along with additional host specific configurations in separate files. Now that when we want to connect with those, we can use the assemble module to create a single ssh config file.

For example, let's start by creating a couple of ssh config files in conf.d directory like below,

conf.d/defaults:

## Defaults

Port 22
Protocol 2
ForwardX11 yes
GSSAPIAuthentication no

conf.d/centos1:

## Custom for centos1
Host centos1
  User root
  Port 2222

assemble_playbook.yaml :

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu-c

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Assemble conf.d to sshd_config
      assemble:
        src: conf.d
        dest: sshd_config

# Three dots indicate the end of a YAML document
...

In above playbook, it takes all content inside config.d directory and create a single config file with the name sshd_config. Which would contain a merged set of entries like below,

## Custom for centos1
Host centos1
  User root
  Port 2222

## Defaults

Port 22
Protocol 2
ForwardX11 yes
GSSAPIAuthentication no

add_host is another module where we can add hosts to our inventory dynamically. This useful when we create hosts in our playbook. Playbook example for this looks like below,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: ubuntu-c

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Add centos1 to adhoc_group
      add_host:
        name: centos1
        groups: adhoc_group1, adhoc_group2

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: adhoc_group1

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Ping all in adhoc_group1
      ping:

# Three dots indicate the end of a YAML document
...

Above playbook will add centos1 to adhoc_group1 and adhoc_group2 and then ping all instances in adhoc_group1.

Similarly group_by module associates / group items based on what's been advised. For example, below playbook group each host by OS distribution and then ping all centos instances in the custom group.

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: all

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Create group based on ansible_distribution
      group_by:
        key: "custom_{{ ansible_distribution | lower }}"

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: custom_centos

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Ping all in custom_centos
      ping:

# Three dots indicate the end of a YAML document
...

Finally, fetch module allows us to get files from the remote machine. For example,

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: centos

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Fetch /etc/redhat-release
      fetch:
        src: /etc/redhat-release
        dest: /tmp/redhat-release

# Three dots indicate the end of a YAML document
...

Last updated