← All articles
AutomationFeb 11, 202316 min read

Ansible Automation — 3

Ansible provides a variety of modules that can be used to perform a wide range of tasks. Some of the most commonly used module types in Ansible include:

  1. Core modules: These are the built-in modules that are included with Ansible. Core modules are highly stable and provide basic functionality such as file management, package management, and user management. 2. Extra modules: These are additional modules that are provided by the Ansible community and are not included with Ansible by default. Extra modules can be installed using the Ansible Galaxy tool. 3. Custom modules: These are modules that are written by users to perform specific tasks. Custom modules can be written in any language that is compatible with the Ansible module API. 4. Cloud modules: These are modules that are used to manage resources in cloud environments, such as AWS, GCP, and Azure. Cloud modules provide a unified interface for managing resources in these environments. 5. Network modules: These are modules that are used to manage network devices, such as switches and routers. Network modules provide a unified interface for managing these devices and allow you to automate network configuration tasks. 6. Database modules: These are modules that are used to manage databases, such as MySQL and PostgreSQL. Database modules provide a unified interface for managing databases and allow you to automate database administration tasks. 7. Monitoring and log modules: These are modules that are used to monitor systems and gather log data. Monitoring and log modules allow you to automate the collection and analysis of system data.

Each module in Ansible provides specific functionality and is designed to be used in different scenarios. By using the right combination of modules, you can automate a wide range of tasks and simplify the management of your infrastructure.

Some important modules

Register

The register module in Ansible is used to capture the output of a task and store it as a variable. The stored variable can then be used in later tasks as part of your playbook. This allows you to use the results of one task in subsequent tasks, making it easier to automate complex workflows.

The basic syntax for using the register module is as follows:

  • name: Task name
  • <module>: <module options>
  • register: <variable name> # any string can be given as variable name

For example, you can use the register module to capture the output of a shell command and store it in a variable:

  • name: Get the current date and time
  • shell: date
  • register: date_output

The register module can be used with any Ansible module that returns output. The output of the task is stored in the specified variable, which can then be used in subsequent tasks. For example, you can use the following task to print the value stored in the date_output variable:

  • name: Print the date and time
  • debug:
  • var: date_output.stdout_lines

By using the register module, you can create complex workflows in Ansible that are easy to understand and maintain. The ability to store and use the output of tasks in subsequent tasks greatly expands the range of tasks that can be automated with Ansible.

Async

The async module in Ansible is used to run long-running tasks asynchronously. This means that the task is executed in the background while Ansible continues to run other tasks. This is useful in situations where you need to run a task that takes a long time to complete, but you don't want to wait for it to finish before running other tasks.

The basic syntax for using the async module is as follows:

  • name: Task name
  • async: <seconds> # timeout in sec
  • poll: <seconds> # poll time in sec
  • command: <task command>

The async module takes two parameters

  1. async: The number of seconds that Ansible should wait before checking the status of the task. 2. poll: The number of seconds that Ansible should wait between status checks.

For example, you can use the async module to run a shell command in the background:

  • name: Run command in the background
  • async: 300
  • poll: 30
  • command: <task command>

In this example, the task will run in the background and Ansible will check the status of the task every 30 seconds, waiting 300 seconds between each check. The async module can be used with any task that takes a long time to complete and is especially useful in situations where multiple long-running tasks are required. By using the async module, you can run tasks in parallel and significantly reduce the amount of time it takes to complete a playbook.

Run_once

The run_once module in Ansible is used to ensure that a task is executed only once, even if the playbook is run multiple times. This can be useful in situations where you want to ensure that a task is executed only once, regardless of the number of times the playbook is run.

The basic syntax for using the run_once module is as follows:

  • name: Task name
  • run_once: yes
  • <module>: <module options>

For example, you can use the run_once module to ensure that a shell command is executed only once:

  • name: Run command only once
  • run_once: yes
  • shell: <command>

In this example, the shell command will only be executed the first time the playbook is run. If the playbook is run multiple times, the run_once module will ensure that the task is not executed again.

The run_once module is particularly useful in situations where you want to run a task that has a significant impact on your system, such as installing software or modifying configuration files. By using the run_once module, you can ensure that the task is executed only once, avoiding any potential issues that might arise from running the task multiple times.

delegate_to

The delegate_to module in Ansible is used to run a task on a specific host, rather than on the host that the playbook is being run from. This is useful in situations where you want to run a task on a specific host, even though the playbook is being executed from a different host.

The basic syntax for using the delegate_to module is as follows:

  • name: Task name
  • delegate_to: <hostname>
  • <module>: <module options>

For example, you can use the delegate_to module to run a shell command on a specific host:

  • name: Run command on host
  • delegate_to: host1
  • shell: <command>

In this example, the shell command will be executed on the host named host1, rather than on the host that the playbook is being run from. The delegate_to module is useful in situations where you need to run a task on a specific host, such as when you need to configure a specific host in a group of hosts. By using the delegate_to module, you can ensure that the task is executed on the correct host, even if the playbook is being run from a different host.

We can use the run_once module with delegate_to module as per the business requirement.
  • hosts: all
  • tasks:
  • name: Print
  • command: echo "Hi Sreeni"
  • run_once: true
  • delegate_to: node2

Loops in anisble

Loops in Ansible allow you to execute a task multiple times, with each iteration using a different set of variables. Loops are useful when you need to perform the same task on multiple items, such as when you need to install software on a group of servers or configure settings for multiple users.

There are several different ways to perform loops in Ansible, including:

  1. with_items loop: The with_items loop is used to perform a task for each item in a list.

For example, you can use the with_items loop to install software on multiple servers:

  • name: Install software
  • yum:
  • name: <software>
  • with_items:
  • server1
  • server2
  • server3

In this example, the yum module will be used to install the specified software on each of the servers in the list.

  1. with_dict loop: The with_dict loop is used to perform a task for each key-value pair in a dictionary.

For example, you can use the with_dict loop to configure settings for multiple users:

  • name: Configure settings
  • user:
  • name: "{{ item.key }}"
  • shell: "/bin/bash"
  • with_dict:
  • user1: "/home/Sachin"
  • user2: "/home/Rajesh"
  • user3: "/home/Swami"

In this example, the user module will be used to configure the shell for each user in the dictionary.

  1. with_fileglob loop: The with_fileglob loop is used to perform a task for each file that matches a specified pattern.

For example, you can use the with_fileglob loop to copy files that match a specific pattern:

  • name: Copy files
  • copy:
  • src: "{{ item }}"
  • dest: "/tmp"
  • with_fileglob:
  • "/path/to/files/*.txt"

In this example, the copy module will be used to copy all of the .txt files in the specified directory to the /tmp directory.

These are just a few of the ways that you can use loops in Ansible. By using loops, you can automate repetitive tasks and perform complex operations on multiple items, making your playbooks more efficient and scalable.

Loop

The loop module in Ansible is used to repeat a task multiple times. This module is similar to the other loop modules (with_items, with_dict, with_fileglob, with_sequence, and with_subelements), but provides more flexibility in terms of the data structure you can use as the loop source. The loop module can use any valid Python expression as the source of the loop, including lists, dictionaries, and even nested data structures.

Here is an example of how you can use the loop module in a playbook:

  • name: Repeat a task using the loop module
  • loop: "{{ [1, 2, 3, 4, 5] }}"
  • command: echo {{ item }}
  • register: result
  • name: Show the result of the loop
  • debug:
  • var: result.results

In this example, the loop module is used to repeat the command task five times, with each iteration using a different item from the list [1, 2, 3, 4, 5]. The result of each iteration is stored in a variable result, which can then be displayed using the debug module.

The loop module can be very useful in situations where you need to repeat a task with a complex data structure, or when the data source for the loop is not easily handled by the other loop modules. By using the loop module, you can leverage the full power of Python to control the flow of your playbooks and perform complex operations with ease.

Parallelism in Ansible

The serial and fork parameters are used to control the order in which Ansible tasks are executed in a playbook.

Serial is used to specify the number of hosts that should be executed on in a play, in a sequential order. For example, if you specify serial: 2, Ansible will execute the play on 2 hosts at a time. This can be useful when you want to limit the number of hosts that are executing a play simultaneously, for example, when you have limited resources on your control machine. The syntax for using serial is as follows:

  • name: Play example with serial
  • hosts: all
  • tasks:
  • name: Task 1
  • shell: echo "Task 1"
  • name: Task 2
  • shell: echo "Task 2"
  • serial: 2

On the other hand, fork is used to specify the number of worker processes that Ansible should use to execute tasks. For example, if you specify fork: 4, Ansible will spawn 4 worker processes to execute the tasks in parallel. The syntax for using fork is as follows:

  • name: Play example with fork
  • hosts: all
  • tasks:
  • name: Task 1
  • shell: echo "Task 1"
  • name: Task 2
  • shell: echo "Task 2"
  • forks: 4

The use cases for serial and fork vary depending on the requirements of your playbook and the resources available on your control machine. In general, if you have limited resources, you may want to use serial to limit the number of hosts that are executing a play simultaneously. On the other hand, if you have plenty of resources and want to execute tasks as quickly as possible, you may want to use fork to increase the number of worker processes.

In conclusion, the choice between serial and fork depends on the specific requirements of your playbook and the resources available on your control machine. You may need to experiment with different values for these parameters to find the optimal configuration for your use case.

Conditions in Ansible

Conditions in Ansible allow you to control the flow of execution of your playbooks and tasks based on specific conditions. They are an essential part of any configuration management tool, and Ansible provides several ways to implement conditions in your playbooks.

  1. when statement: The when statement is the most commonly used method for controlling the execution of tasks in Ansible. It allows you to specify a condition that must be met for a task to be executed. For example, you could use a when statement to only execute a task if a certain file exists on a remote host. The syntax for using a when statement is as follows:
  • name: Task example with when
  • shell: echo "Task is executed"
  • when: file_exists == True

The when keyword in Ansible uses YAML syntax to specify conditions. To achieve the "and" condition, you can list multiple conditions separated by - symbols in the when statement, like this:

  • name: Only run this task if two conditions are met
  • shell: echo "Both conditions are met"
  • when:
  • variable_name is defined
  • variable_name == "desired_value"

To achieve the "or" condition, you can use the or operator:

  • name: Run this task if either of two conditions are met
  • shell: echo "One of the conditions is met"
  • when: variable_name is defined or file_exists

Note that the conditions specified in the when statement are expressions that evaluate to either true or false.

  1. failed_when statement: The failed_when statement allows you to specify a condition that must not be met for a task to succeed. If the condition is met, the task will fail. For example, you could use a failed_when statement to ensure that a certain file does not exist on a remote host. The syntax for using a failed_when statement is as follows:
  • name: Task example with failed_when
  • shell: echo "Task is executed"
  • failed_when: file_exists == True
  1. assert statement: The assert statement is used to enforce a particular condition. If the condition is not met, the task will fail, and the playbook will stop executing. For example, you could use an assert statement to ensure that a variable has a specific value before proceeding with a task. The syntax for using an assert statement is as follows:
  • name: Task example with assert
  • assert:
  • that:
  • variable_value == "expected_value"
  • shell: echo "Task is executed"

Business logic to use when, failed_when and assert:

when, failed_when, and assert are all used in Ansible to control the execution of tasks based on conditions.

when is used to conditionally execute a task. If the specified condition is true, the task is executed, otherwise it is skipped.

failed_when is used to specify a condition that will cause a task to fail. If the specified condition is true, the task will fail and the playbook execution will be halted.

assert is used to check for conditions within a playbook and fail the playbook execution if the condition is not met. assert is used to enforce preconditions in a playbook, similar to failed_when.

Here is an example to demonstrate the use of when, failed_when, and assert:

  • name: Check if variable is defined
  • shell: echo "Variable is defined"
  • when: variable is defined
  • name: Fail if variable is not defined
  • fail:
  • msg: "Variable 'variable_name' is not defined"
  • failed_when: variable is not defined
  • name: Assert variable is defined
  • assert:
  • that: variable is defined
  • fail_msg: "Variable 'variable_name' is not defined"

In this example, the first task will only be executed if the variable variable is defined. The second task will fail and halt the playbook execution if the variable is not defined. The third task uses the assert module to enforce that the variable variable is defined and will fail the playbook execution with the message "Variable 'variable_name' is not defined" if the condition is not met.

Until Module

The until loop in Ansible allows you to repeat a task until a certain condition is met. It is similar to a while loop in traditional programming languages. The loop will continue to run until the specified condition returns a result of true.

Here is an example of how to use the until loop in an Ansible playbook:

  • name: Wait for a shell task to complete
  • shell: echo {{ item }}
  • with_items:
  • Syed
  • Mohan
  • Vittal
  • Param
  • Rajesh
  • register: result
  • until: result.rc == 0
  • retries: 10
  • delay: 3

In this example, the task shell: echo {{item}} is executed using the until loop, and will continue to run until the return code (rc) of the command is 0, which indicates that the task is successfully done. The retries directive specifies the number of times the task should be executed before giving up, and the delay directive specifies the time in seconds to wait between retries. The result of the command is registered in a variable result, which can then be used to check the return code.

It's important to use the until loop judiciously, as it can run an unlimited number of times if the specified condition is never met. To avoid this, it is a good practice to set a maximum number of retries and a delay between retries to avoid overloading the system.

Logical Operators in Ansible: In Ansible, logical operators are used to evaluate conditions and make decisions. The following logical operators are available in Ansible:

  1. and: Returns true if both the conditions are true. 2. or: Returns true if either of the conditions is true. 3. not: Returns true if the condition is false, and false if the condition is true.

Here is an example to demonstrate the use of logical operators in Ansible:

  • name: Task 1
  • shell: echo "Task 1"
  • when: (variable1 is defined) and (variable2 is defined)
  • name: Task 2
  • shell: echo "Task 2"
  • when: (variable1 is defined) or (variable2 is defined)
  • name: Task 3
  • shell: echo "Task 3"
  • when: not (variable1 is defined)

In this example, Task 1 will only be executed if both variable1 and variable2 are defined. Task 2 will be executed if either variable1 or variable2 is defined. Task 3 will only be executed if variable1 is not defined.

Comparison operators in ansible: In Ansible, comparison operators are used to compare values and make decisions. The following comparison operators are available in Ansible:

  1. ==: Equal to 2. !=: Not equal to 3. <: Less than 4. >: Greater than 5. <=: Less than or equal to 6. >=: Greater than or equal to 7. in: Membership test 8. not in: Negation of membership test

Here is an example to demonstrate the use of comparison operators in Ansible:

  • name: Task 1
  • shell: echo "Task 1"
  • when: variable1 == "value1"
  • name: Task 2
  • shell: echo "Task 2"
  • when: variable2 != "value2"
  • name: Task 3
  • shell: echo "Task 3"
  • when: variable3 < 5
  • name: Task 4
  • shell: echo "Task 4"
  • when: variable4 in [ 1 , 2 , 3 , 4 , 5 ]
  • name: Task 5
  • shell: echo "Task 5"
  • when: variable5 not in [ 1 , 2 , 3 , 4 , 5 ]

In this example, Task 1 will only be executed if variable1 is equal to value1. Task 2 will be executed if variable2 is not equal to value2. Task 3 will only be executed if variable3 is less than 5. Task 4 will be executed if variable4 is a member of the list [1, 2, 3, 4, 5]. Task 5 will be executed if variable5 is not a member of the list [1, 2, 3, 4, 5].

MK
Mohankrishna PodileDevOps Engineer & Cloud Architect · Irving, Texas

Comments

Questions, corrections, war stories — all welcome. Sign in with GitHub to join the discussion.