Simplify tasks by using vendor-independent network resource modules and the ansible.netcommon Ansible Content Collection.
Network platforms typically separate their configuration data into subsections, or resources.
You can use network resource modules to read and configure these resources, such as VLANs, interfaces, ACLs, and others. The goal of network resource modules is to provide a consistent experience across network devices running different network platforms.
For example, you can use the following network resource modules to configure Layer 3 interfaces on various network platforms.
Notice that the l3_interfaces part in the name of the resource module is the same in each case.
cisco.ios.ios_l3_interfaces
arista.eos.eos_l3_interfaces
junipernetworks.junos.junos_l3_interfaces
In the same way, you can use the following network resource modules to configure ACLs on different network platforms.
cisco.ios.ios_acls
arista.eos.eos_acls
junipernetworks.junos.junos_acls
Network resource modules enable you to standardize your automation files and create configurations that you can apply consistently across network operating systems.
Use network resource modules by setting the module state. Resource modules support the following states:
Ansible merges the current device configuration with the configuration provided in the task.
Ansible replaces the current device configuration subsection with the configuration provided in the task.
Ansible overrides the current device configuration with the configuration provided in the task. This means that the entire resource is deleted (for example, all L3 interfaces), and then the new configuration is added.
Use caution with the overridden state as you could remove your access to the device.
Ansible deletes the current device configuration subsection and restores any default settings.
Ansible displays the resource details gathered from the network device.
Ansible displays these details in the gathered key in the task output.
Ansible renders the provided configuration in the task in the native format for the network platform.
Ansible displays this rendered configuration in the rendered key in the task output.
The rendered state does not communicate with or change the network device and can be used offline.
Ansible parses the configuration subsection data from the running_config parameter into Ansible structured data.
View the collection documentation for the particular network platform to determine how to generate the correct configuration data to pass to the running_config parameter.
Ansible displays this data in the parsed key in the task output.
The parsed state does not communicate with or change the network device and can be used offline.
For more details on resource modules and states, visit https://docs.ansible.com/ansible/latest/network/user_guide/network_resource_modules.html.
Network resource modules return a data structure that can be registered into a variable, or displayed in the task output.
Resource modules all support the same return values, regardless of the network OS. This makes it easy to automate consistently across network platforms.
Resource modules support the following return values:
The configuration, displayed as structured data, before the module runs.
The configuration, displayed as structured data, after the module runs.
The set of commands pushed to the network device.
You can use the return values to verify if and how the device configuration was changed.
The ansible.netcommon collection provides modules that can be used to automate network devices without having to specify a particular network platform.
This enables you to manage or configure devices from different vendors without having to use a separate module for each different type of device.
The following table lists the modules available in the ansible.netcommon collection:
| Module | Description |
|---|---|
cli_command
| Run a CLI command. |
cli_config
| Push text-based configuration to network devices. |
grpc_config
| Append configs option to an existing configuration in a gRPC-enabled devices. |
grpc_get
| Fetch configuration/state data from gRPC-enabled target hosts. |
net_get
| Copy a file from a network device to automation controller. |
net_ping
| Use ping from a network device to ensure communication to a remote destination. |
net_put
| Copy a file from automation controller to a network device. |
netconf_config
| Enable the user to send a configuration XML file to a NETCONF device, and detects if there was a configuration change. |
netconf_get
| Fetch configuration/state data from NETCONF-enabled network devices. |
netconf_rpc
| Execute operations on NETCONF-enabled network devices. |
network_resource
| Manage resource modules. |
restconf_config
| Create, update, read, or delete configuration data on RESTCONF-enabled devices. |
restconf_get
| Fetch configuration/state data from RESTCONF-enabled devices. |
telnet
| Execute a Telnet command. |
You can use platform-specific *_command modules to send commands to managed network nodes that have a command-line interface, and then process the results of those commands.
If you use a separate module for each different network platform, then you would need three separate tasks to run the same type of command, as in the following example:
---
- name: Run Cisco IOS command
cisco.ios.ios_command:
commands: "show ip interface"
when: ansible_network_os == 'cisco.ios.ios'
- name: Run Junos command
junipernetworks.junos.junos_command:
commands: "show interface terse"
when: ansible_network_os == 'junipernetworks.junos.junos'
- name: Run Arista EOS command
arista.eos.eos_command:
commands: "show ip interface"
when: ansible_network_os == 'arista.eos.eos'You can simplify such playbooks by using the platform-independent ansible.netcommon.cli_command module, as in the following example:
---
- name: Run a command across multiple network platforms
hosts: ios,junos,eos
gather_facts: false
vars:
ansible_connection: ansible.netcommon.network_cli
tasks:
- name: Run command and display results
block:
- name: Run a command
ansible.netcommon.cli_command:
command: "{{ some_command }}"
register: result
- name: Display result
ansible.builtin.debug:
var: result['stdout_lines']Store the some_command variable in files under the group_vars directory, with the actual commands to run on each network platform.
For example, the following variable file holds the some_command variable for the Arista EOS platform:
--- some_command: "show ip interface brief"
In the following example, the variable file holds the some_command variable for the Juniper Junos platform:
--- some_command: "show interface terse"
You can use the ansible.netcommon.cli_config module to configure managed network nodes, back up existing configurations, or look for configuration differences.
The following example configures NTP on Cisco IOS, Cisco Junos, and Arista EOS platforms:
---
- name: Configure IOS, Junos, and EOS platforms
hosts: ios,junos,eos
gather_facts: false
vars:
ansible_connection: ansible.netcommon.network_cli
tasks:
- name: Configure NTP settings
ansible.netcommon.cli_config:
config: "{{ config_ntp }}"
notify:
- Save configuration
handlers:
- name: Save configuration
ansible.netcommon.cli_command:
command: "{{ save_config }}"You store the config_ntp and save_config variables in files under the group_vars directory, with the actual commands to run on each network platform.
For example, the following variable file holds the config_ntp and save_config variable for the Arista EOS platform:
--- config_ntp: | ntp server 10.10.10.10 prefer ntp server 10.10.10.11 save_config: "copy running-config startup-config"
In the following example, the variable file holds the config_ntp and save_config variables for the Juniper Junos platform:
--- config_ntp: | set system ntp server 10.10.10.10 prefer set system ntp server 10.10.10.11 save_config: "commit"
The ansible.netcommon.cli_config module can also back up configurations across network platforms.
The following example backs up the configurations on Cisco IOS, Juniper Junos, and Arista EOS platforms:
---
- name: Backup configurations on IOS, Junos, and EOS
hosts: ios,junos,eos
gather_facts: false
tasks:
- name: Backup configurations
vars:
ansible_connection: ansible.netcommon.network_cli
ansible.netcommon.cli_config:
backup: true
backup_options:
filename: "{{ inventory_hostname }}.cfg"
dir_path: ./backupParsing is the process of converting unstructured or semistructured text into structured data. You can use parsed data for many purposes, including creating dynamic documentation or to automate troubleshooting steps.
Network resource modules and fact modules parse the data returned from managed network nodes when running Ansible tasks.
You can also use the ansible.utils.cli_parse module to parse data.
Network configurations are stored in different formats on different network platforms. You might want to store configurations from multiple network platforms in a vendor-neutral format for configuration management, migration, or troubleshooting purposes.
You can use the resource module parsed state to parse and reformat sections of configuration data.
You can then store the configuration data in a version control system or import it into a configuration management system.
For example, the following playbook parses an IOS Layer 3 interface configuration stored in the l3int.cfg file, and then saves the transformed configuration data to the parsed_l3int.cfg file.
The l3int.cfg file is generated by running the show running-config | section ^interface command on the IOS device and then saving the output to the file:
---
- name: Parse L3 interface configuration and save the data to a file
hosts: ios1.example.com
gather_facts: false
tasks:
- name: Parse L3 interface configuration
cisco.ios.ios_l3_interfaces:
running_config: "{{ lookup('file', 'l3int.cfg') }}"
state: parsed
register: ios_l3int
- name: Save configuration data
ansible.builtin.copy:
content: >-
"{{ ios_l3int | ansible.builtin.to_nice_yaml }}"
dest: parsed_l3int.cfg
delegate_to: localhostThe l3int.cfg file consists of the following content:
interface GigabitEthernet1 ip address 172.25.250.20 255.255.255.0 negotiation auto interface GigabitEthernet2 ip address 172.25.251.20 255.255.255.0 ipv6 address 2001:db8:251:20::/64 negotiation auto
After this playbook is run, the parsed_l3int.cfg file consists of the following content:
"changed: false
failed: false
parsed:
- ipv4:
- address: 172.25.250.20/24
name: GigabitEthernet1
- ipv4:
- address: 172.25.251.20/24
ipv6:
- address: 2001:db8:251:20::/64
name: GigabitEthernet2"Consult the module documentation to determine how to generate the correct configuration file to use with the parsed state and the running_config option.
You might want to use the ansible.utils.cli_parse module to parse data for the following reasons:
Because a network resource module does not exist for the particular network platform and resource
Because fact modules do not return the data that you want
To convert configuration files into structured data and then send it to an external system, such as an IP address management (IPAM) or network management system
To parse operational state data, such as the output of show commands, and there is no module available to get the data you require
The ansible.utils.cli_parse module uses an architecture based on plug-ins and supports several different plug-ins.
The ansible.netcommon.native plug-in is covered in this section.
For more information on parsing plug-ins that you can use with the ansible.utils.cli_parse module, visit https://docs.ansible.com/ansible/latest/network/user_guide/cli_parsing.html
To use the ansible.netcommon.native plug-in, you must create a template.
The plug-in takes the output of a network device command and applies a YAML template to transform the command output into structured data.
The YAML template file uses regular expressions to parse the received data into structured data.
The YAML template is structured as a list of parsers, each containing the following key-value pairs:
| Key | Description |
|---|---|
example
| An example line of the text line to be parsed. |
getval
| A regular expression using named capture groups to store the extracted data. |
result
| A data tree, populated as a template, from the parsed data. |
shared
| (optional) The shared key makes the parsed values available to the rest of the parser entries until matched again. |
For example, the following play runs the show ip interface command on IOS managed nodes, and then parses and displays the output:
---
- name: Run a command and parse the output
hosts: ios
gather_facts: false
tasks:
- name: Parse interface data
ansible.utils.cli_parse:
command: "show ip interface"
parser:
name: ansible.netcommon.native
template_path: "./templates/interfaces.yml"
set_fact: ios_interfaces
- name: Display structured data
ansible.builtin.debug:
var: ansible_facts['ios_interfaces']Set the path to the template file with the template_path parameter.
If you do not set the template path, then the default path for a parser template is templates/{{ short_os }}_{{ command }}.{{ extension }}.
short_os is derived from the ansible_network_os variable and set to lowercase.
command is the command passed to the module with spaces replaced with underscore (_) characters.
extension is specific to the parser used (native=yaml, textfsm=textfsm, ttp=ttp).
The associated YAML template consists of the following content:
---
- example: "GigabitEthernet1 is up, line protocol is up"
getval: '(?P<name>\S+)\sis\s(?P<admin_state>\S+)\,\sline\sprotocol\sis\s(?P<oper_state>\S+)'
result:
"{{ name }}":
name: "{{ name }}"
state:
admin: "{{ admin_state }}"
operating: "{{ oper_state }}"When the play is run, the parsed output is displayed as follows:
...output omitted... ok: [ios1.example.com] => { "ansible_facts": { "ios_interfaces": { "GigabitEthernet1": {vendor-independent } ok: [ios2.example.com] => { "ansible_facts": { "ios_interfaces": { "GigabitEthernet1": { "name": "GigabitEthernet1", "state": { "admin": "up", "operating": "up" } } } } } ...output omitted...
You can then copy this data to a file and perform further actions with it, such as sending the data to an external system.
Ansible validated content is a set of Ansible Content Collections that are focused on specific use cases.
Validated content stems from and complements the Red Hat Validated Patterns initiative. A selection of Ansible content is curated by experts, such as the Red Hat Automation Community of Practice, to ensure that:
The use cases are based on successfully deployed customer examples.
The content creators are trusted and verified subject matter experts.
The content itself adheres to the latest best practices and guidelines issued by the Red Hat engineering team.
Ansible validated content is tested against supported versions of Ansible Automation Platform and is ready for use in production environments.
The network.base Ansible Content Collection is Ansible validated content focusing on platform-independent network automation, and provides core functionality for other network-oriented Ansible Content Collections that are Ansible validated content, such as the network.ospf, network.interfaces, and network.bgp collections.
The persist action gets the facts for a given resource and stores the facts as inventory host variables.
The list action displays the list of all resource modules supported for a given network OS.
The gather action gathers and displays the facts for specified network resources.
The deploy action deploys changes, based on host variables, to the device.
The configure action provides another way of pushing configuration changes to the device.
For more information on Ansible validated content, visit https://learn.spidernet.pl/en/blog/automate-expert-ansible-validated-content.