Module documentation, Registering output & tags

1. Théorie

Modules

Modules do the actual work in ansible, they are what gets executed in each playbook task.

  • Typically written in Python (but not limited to it)
  • Modules are idempotent
  • Modules take user input in the form of parameters

Network modules

Ansible modules for network automation typically references the vendor OS followed by the module name.

  • *_facts
  • *_command
  • *_config

more modules depending on platform

Arista EOS = eos_* Cisco IOS/IOS-XE = ios_* Cisco NX-OS = nxos_* Cisco IOS-XR = iosxr_* Juniper Junos = junos_* VyOS = vyos_*

Modules per network platform

- hosts: all
  connection: network_cli
  tasks:
    - name: configure eos system properties
      eos_system:
        domain_name: ansible.com
        vrf: management
      when: ansible_network_os == 'eos'

    - name: configure nxos system properties
      nxos_system:
        domain_name: ansible.com
        vrf: management
      when: ansible_network_os == 'nxos'

Modules Documentation

http://docs.ansible.com/

Modules Documentation

# List out all modules installed
$ ansible-doc -l
...
ios_banner                                Manage multiline banners on Cisco IOS devices
ios_command                               Run commands on remote devices running Cisco IOS
ios_config                                Manage Cisco IOS configuration sections
...

# Read documentation for installed module
$ ansible-doc ios_command
> IOS_COMMAND

     Sends arbitrary commands to an ios node and returns the results read from the
     device. This module includes an argument that will cause the module to wait for a
     specific condition before returning or timing out if the condition is not met. This
     module does not support running commands in configuration mode. Please use
     [ios_config] to configure IOS devices.

Options (= is mandatory):
...

Limiting tasks within a play

  • Tags allow the user to selectively execute tasks within a play.
  • Multiple tags can be associated with a given task.
  • Tags can also be applied to entire plays or roles.
    - name: DISPLAY THE COMMAND OUTPUT
      debug:
        var: show_output
      tags: show

Tags are invoked using the –tags flag while running the playbook

ansible-playbook gather_ios_data.yml --tags=show

This is useful while working with large playbooks, when you might want to “jump” to a specific task.

Registering the output

The register parameter is used to collect the output of a task execution. The output of the task is ‘registered’ in a variable which can then be used for subsequent tasks.

    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief
      tags: show
      register: show_output

2. Lab

In the previous section you learned to use the ios_facts and the debug modules. The debug module had an input parameter called msg whereas the ios_facts module had no input parameters. As someone just starting out how would you know what these parameters were for a module?

There are 2 options.

    1. Point your browser to https://docs.ansible.com > Network Modules and read the documentation
    1. From the command line, issue the ansible-doc <module-name> to read the documentation on the control host.

Step 1

On the control host read the documentation about the ios_facts module and the debug module.

ansible-doc debug

What happens when you use debug without specifying any parameter?

ansible-doc ios_facts

How can you limit the facts collected ?

Step 2

In the previous section, you learned how to use the ios_facts module to collect device details. What if you wanted to collect the output of a show command that was not provided as a part of ios_facts ?

The ios_command module allows you to do that. Go ahead and add another task to the playbook to collect the output of 2 show commands to collect the hostname and the output of the show ip interface brief commands:

---
- name: GATHER INFORMATION FROM ROUTERS
  hosts: cisco
  connection: network_cli
  gather_facts: no

  tasks:
    - name: GATHER ROUTER FACTS
      ios_facts:

    - name: DISPLAY VERSION
      debug:
        msg: "The IOS version is: {{ ansible_net_version }}"

    - name: DISPLAY SERIAL NUMBER
      debug:
        msg: "The serial number is:{{ ansible_net_serialnum }}"


    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief

Note: commands is a parameter required by the ios_command. The input to this parameter is a “list” of IOS commands.

Step 3

Before running the playbook, add a tag to the last task. Name it “show”

Tags can be added to tasks, plays or roles within a playbook. You can assign one or more tags to any given task/play/role. Tags allow you to selectively run parts of the playbook.

---
- name: GATHER INFORMATION FROM ROUTERS
  hosts: cisco
  connection: network_cli
  gather_facts: no

  tasks:
    - name: GATHER ROUTER FACTS
      ios_facts:

    - name: DISPLAY VERSION
      debug:
        msg: "The IOS version is: {{ ansible_net_version }}"

    - name: DISPLAY SERIAL NUMBER
      debug:
        msg: "The serial number is:{{ ansible_net_serialnum }}"


    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief
      tags: show

Step 4

Selectively run the last task within the playbook using the --tags option:

ansible-playbook gather_ios_data.yml --tags=show

PLAY [GATHER INFORMATION FROM ROUTERS] **************************************************************************

TASK [COLLECT OUTPUT OF SHOW COMMANDS] **************************************************************************
ok: [rtr2]
ok: [rtr3]
ok: [rtr1]
ok: [rtr4]

PLAY RECAP ******************************************************************************************************
rtr1                       : ok=1    changed=0    unreachable=0    failed=0   
rtr2                       : ok=1    changed=0    unreachable=0    failed=0   
rtr3                       : ok=1    changed=0    unreachable=0    failed=0   
rtr4                       : ok=1    changed=0    unreachable=0    failed=0   

[root@ansible networking-workshop]#

Note 2 important points here.

  1. Only a single task was executed during the playbook run (You no longer can see the serial number and IOS version being displayed)

  2. The output of the show commands is not being displayed.

Step 5

Re-run the playbook using the -v verbose flag to see the output coming back from the routers.

ansible-playbook  gather_ios_data.yml --tags=show -v

Step 6

With the ios_facts module, the output was automatically assigned to the ansible_* variables. For any of the ad-hoc commands we run against remote devices, the output has to be “registered” to a variable in order to use it within the playbook. Go ahead and add the register directive to collect the output of the show commands into a variable called show_output:

---
- name: GATHER INFORMATION FROM ROUTERS
  hosts: cisco
  connection: network_cli
  gather_facts: no

  tasks:
    - name: GATHER ROUTER FACTS
      ios_facts:

    - name: DISPLAY VERSION
      debug:
        msg: "The IOS version is: {{ ansible_net_version }}"

    - name: DISPLAY SERIAL NUMBER
      debug:
        msg: "The serial number is:{{ ansible_net_serialnum }}"

    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief
      tags: show
      register: show_output

Step 7

Add a task to use the debug module to display the content’s of the show_output variable. Tag this task as “show” as well.

---
- name: GATHER INFORMATION FROM ROUTERS
  hosts: cisco
  connection: network_cli
  gather_facts: no

  tasks:
    - name: GATHER ROUTER FACTS
      ios_facts:

    - name: DISPLAY VERSION
      debug:
        msg: "The IOS version is: {{ ansible_net_version }}"

    - name: DISPLAY SERIAL NUMBER
      debug:
        msg: "The serial number is:{{ ansible_net_serialnum }}"

    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief
      tags: show
      register: show_output

    - name: DISPLAY THE COMMAND OUTPUT
      debug:
        var: show_output
      tags: show

Note the use of var vs msg for the debug module.

Step 8

Re-run the playbook to execute only the tasks that have been tagged. This time run the playbook without the -v flag.

ansible-playbook  gather_ios_data.yml --tags=show

PLAY [GATHER INFORMATION FROM ROUTERS] **************************************************************************

TASK [COLLECT OUTPUT OF SHOW COMMANDS] **************************************************************************
ok: [rtr4]
ok: [rtr1]
ok: [rtr3]
ok: [rtr2]

TASK [DISPLAY THE COMMAND OUTPUT] *******************************************************************************
ok: [rtr4] => {
    "show_output": {
        "changed": false,
        "failed": false,
        "stdout": [
            "hostname rtr4",
            "Interface              IP-Address      OK? Method Status                Protocol\nGigabitEthernet1       172.17.231.181  YES DHCP   up                    up      \nLoopback0              192.168.4.104   YES manual up                    up      \nLoopback1              10.4.4.104      YES manual up                    up      \nTunnel0                10.101.101.4    YES manual up                    up      \nVirtualPortGroup0      192.168.35.101  YES TFTP   up                    up"
        ],
        "stdout_lines": [
            [
                "hostname rtr4"
            ],
            [
                "Interface              IP-Address      OK? Method Status                Protocol",
                "GigabitEthernet1       172.17.231.181  YES DHCP   up                    up      ",
                "Loopback0              192.168.4.104   YES manual up                    up      ",
                "Loopback1              10.4.4.104      YES manual up                    up      ",
                "Tunnel0                10.101.101.4    YES manual up                    up      ",
                "VirtualPortGroup0      192.168.35.101  YES TFTP   up                    up"
            ]
        ]
    }
}
ok: [rtr1] => {
    "show_output": {
        "changed": false,
.
.
.
.
.
<output omitted for brevity>

Step 9

The show_output variable can now be parsed just like a Python dictionary. It contains a “key” called stdout. stdout is a list object, and will contain exactly as many elements as were in the input to the commands parameter of the ios_command task. This means show_output.stdout[0] will contain the output of the show running | i hostname command and show_output.stdout[1] will contain the output of show ip interface brief.

Write a new task to display only the hostname using a debug command:

---
- name: GATHER INFORMATION FROM ROUTERS
  hosts: cisco
  connection: network_cli
  gather_facts: no

  tasks:
    - name: GATHER ROUTER FACTS
      ios_facts:

    - name: DISPLAY VERSION
      debug:
        msg: "The IOS version is: {{ ansible_net_version }}"

    - name: DISPLAY SERIAL NUMBER
      debug:
        msg: "The serial number is:{{ ansible_net_serialnum }}"

    - name: COLLECT OUTPUT OF SHOW COMMANDS
      ios_command:
        commands:
          - show run | i hostname
          - show ip interface brief
      tags: show
      register: show_output

    - name: DISPLAY THE COMMAND OUTPUT
      debug:
        var: show_output
      tags: show

    - name: DISPLAY THE HOSTNAME
      debug:
        msg: "The hostname is {{ show_output.stdout[0] }}"
      tags: show

Step 10

Re-run the playbook.

ansible-playbook  gather_ios_data.yml --tags=show

PLAY [GATHER INFORMATION FROM ROUTERS] **************************************************************************

TASK [COLLECT OUTPUT OF SHOW COMMANDS] **************************************************************************
ok: [rtr2]
ok: [rtr4]
ok: [rtr1]
ok: [rtr3]

TASK [DISPLAY THE COMMAND OUTPUT] *******************************************************************************
ok: [rtr2] => {
    "show_output": {
        "changed": false,
        "failed": false,
        "stdout": [
.
.
.
.
.
<output omitted for brevity>
.
.
.
TASK [DISPLAY THE HOSTNAME] *************************************************************************************
ok: [rtr2] => {
    "msg": "The hostname is hostname rtr2"
}
ok: [rtr1] => {
    "msg": "The hostname is hostname rtr1"
}
ok: [rtr3] => {
    "msg": "The hostname is hostname rtr3"
}
ok: [rtr4] => {
    "msg": "The hostname is hostname rtr4"
}

PLAY RECAP ******************************************************************************************************
rtr1                       : ok=3    changed=0    unreachable=0    failed=0   
rtr2                       : ok=3    changed=0    unreachable=0    failed=0   
rtr3                       : ok=3    changed=0    unreachable=0    failed=0   
rtr4                       : ok=3    changed=0    unreachable=0    failed=0   

[root@ansible networking-workshop]#