Read this in other languages: English, 日本語.
Demonstration use of Ansible Network Resource Modules
This exercise builds upon exercise 4 - Ansible Network Resource Modules. Please complete that exercise before starting this one.
There are two parts to this exercise:
state
parameters:replaced
overridden
and contrast them to what we saw with merged
.
state
parametersrendered
parsed
and contrast them to the gathered
parameter.
Login to an Arista switch. We are assuming the configuration from exercise 4 is already applied
vlan 20
name desktops
!
vlan 30
name servers
!
vlan 40
name printers
!
vlan 50
name DMZ
From the control node terminal, you can ssh rtr2
and type enable
$ ssh rtr2
Last login: Wed Sep 1 13:44:55 2021 from 44.192.105.112
rtr2>enable
Use the command configure terminal
to manually edit the Arista configuration:
rtr2#configure terminal
rtr2(config)#
Now configure vlan 50 to state suspend
rtr2(config)#vlan 50
rtr2(config-vlan-50)#state ?
active VLAN Active State
suspend VLAN Suspended State
rtr2(config-vlan-50)#state suspend
Save the configuration
rtr2(config-vlan-50)#exit
rtr2(config)#end
rtr2#copy running-config startup-config
Copy completed successfully.
Examine the configuration
rtr2#sh run | s vlan
vlan 20
name desktops
!
vlan 30
name servers
!
vlan 40
name printers
!
vlan 50
name DMZ
state suspend
Execute the playbook using the ansible-navigator run
.
$ ansible-navigator run resource.yml --mode stdout
The output will look similar to the following:
[student@ansible-1 network-workshop]$ ansible-navigator run resource.yml --mode stdout
PLAY [configure VLANs] *********************************************************
TASK [use vlans resource module] ***********************************************
ok: [rtr4]
ok: [rtr2]
PLAY RECAP *********************************************************************
rtr2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rtr4 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
The playbook did NOT modify the configuration. The state: merged
only enforces that the config provided exists on the network device. Lets contrast this to replaced
. If you login to the Arista network device the state suspend
will still be there.
Modify the resource.yml
playbook so that state: merged
is now state: replaced
The playbook should look like the following:
---
- name: configure VLANs
hosts: arista
gather_facts: false
tasks:
- name: use vlans resource module
arista.eos.vlans:
state: replaced
config:
- name: desktops
vlan_id: 20
- name: servers
vlan_id: 30
- name: printers
vlan_id: 40
- name: DMZ
vlan_id: 50
Execute the playbook using the ansible-navigator run
. Since there is just one task we can use the --mode stdout
$ ansible-navigator run resource.yml --mode stdout
The output will look similar to the following:
$ ansible-navigator run resource.yml --mode stdout
PLAY [configure VLANs] *********************************************************
TASK [use vlans resource module] ***********************************************
changed: [rtr4]
changed: [rtr2]
PLAY RECAP *********************************************************************
rtr2 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rtr4 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Now examine the config on rtr2, the state suspend
is now gone. Replaced will enforce (for the specified VLANs) the supplied configurations. This means that since state: suspend
was not supplied, and NOT the default for a VLAN, it will remove it from the network device.
Create vlan 100 on rtr2
rtr2(config)#vlan 100
rtr2(config-vlan-100)#name ?
WORD The ASCII name for the VLAN
rtr2(config-vlan-100)#name artisanal
We can assume that someone has created this VLAN outside of automation (e.g. they hand-crafted a VLAN i.e. artisanal VLAN) This is referred to as “out of band” network changes. This is very common in the network industry because a network engineer solved a problem, but then never documented or circled back to remove this configuration. This manual configuration change does not match best practices or their documented policy. This could cause issues where someone tries to use this VLAN in the future, and not aware of this configuration.
rtr2#show vlan
VLAN Name Status Ports
----- -------------------------------- --------- -------------------------------
1 default active
20 desktops active
30 servers active
40 printers active
50 DMZ active
100 artisanal active
Modify the playbook again, this time using the state: overridden
---
- name: configure VLANs
hosts: arista
gather_facts: false
tasks:
- name: use vlans resource module
arista.eos.vlans:
state: overridden
config:
- name: desktops
vlan_id: 20
- name: servers
vlan_id: 30
- name: printers
vlan_id: 40
- name: DMZ
vlan_id: 50
Execute the playbook using the ansible-navigator run
.
$ ansible-navigator run resource.yml --mode stdout
rtr2
device and examine the VLANs
rtr2#show vlan
VLAN Name Status Ports
----- -------------------------------- --------- -------------------------------
1 default active
20 desktops active
30 servers active
40 printers active
50 DMZ active
merged
to replaced
to overridden
will often match the automation journey for a network team as they gain more and more confidence with automation.Now lets return to using read-only parameters. These parameters do not modify the configuration on a network device. In exercise 4, we used the state: gathered
to retrieve the VLAN configuration from the Arista network device. This time we will use rendered
to get the Arista commands that generate the configuration:
Modify the resource.yml
playbook to state: rendered
Register the output from the task to a variable named rendered_config
Add a debug
task to print the output to the terminal window
The playbook will look like the following:
- name: use vlans resource module
arista.eos.vlans:
state: rendered
config:
- name: desktops
vlan_id: 20
- name: servers
vlan_id: 30
- name: printers
vlan_id: 40
- name: DMZ
vlan_id: 50
register: rendered_config
- name: use vlans resource module
debug:
msg: "{{ rendered_config }}"
Execute the playbook using the ansible-navigator run
.
```bash $ ansible-navigator run resource.yml –mode stdout
The output will look like the following:
[student@ansible-1 network-workshop]$ ansible-navigator run resource.yml --mode stdout
PLAY [configure VLANs] *********************************************************
TASK [use vlans resource module] ***********************************************
ok: [rtr2]
ok: [rtr4]
TASK [use vlans resource module] ***********************************************
ok: [rtr4] => {
"msg": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"failed": false,
"rendered": [
"vlan 20",
"name desktops",
"vlan 30",
"name servers",
"vlan 40",
"name printers",
"vlan 50",
"name DMZ"
]
}
}
ok: [rtr2] => {
"msg": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"failed": false,
"rendered": [
"vlan 20",
"name desktops",
"vlan 30",
"name servers",
"vlan 40",
"name printers",
"vlan 50",
"name DMZ"
]
}
}
PLAY RECAP *********************************************************************
rtr2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rtr4 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Specifically the rendered
key will display the Arista commands that are used to generate the configuration! This allows network automators to know exactly what commands would be run and executed before they actually run automation to apply the commands.
Finally lets cover the parsed parameter. This parameter is used when a existing file contains the network device configuration. Imagine there was already a backup performed.
First lets backup a configuration. Here is a simple playbook for doing a configuration backup. The playbook is backup.yml.
---
- name: backup config
hosts: arista
gather_facts: false
tasks:
- name: retrieve backup
arista.eos.config:
backup: true
backup_options:
filename: "{{ inventory_hostname }}.txt"
Execute the playbook:
$ ansible-navigator run backup.yml --mode stdout
Verify the backups were created:
$ ls backup
rtr2.txt rtr4.txt
Now modify the resource.yml
playbook to use the parsed
playbook:
---
- name: use parsed
hosts: arista
gather_facts: false
tasks:
- name: use vlans resource module
arista.eos.vlans:
state: parsed
running_config: "{{ lookup('file', 'backup/{{ inventory_hostname }}.txt') }}"
register: parsed_config
- name: print to terminal screen
debug:
msg: "{{ parsed_config }}"
There is a couple additional changes:
config
we are using running-config
and pointing to the backup file.parsed_config
varaibleparsed_config
variableExecute the playbook:
$ ansible-navigator run resource.yml --mode stdout
The output will look like the following:
[student@ansible-1 network-workshop]$ ansible-navigator run resource.yml --mode stdout
PLAY [use parsed] **************************************************************
TASK [use vlans resource module] ***********************************************
ok: [rtr4]
ok: [rtr2]
TASK [print to terminal screen] ************************************************
ok: [rtr2] => {
"msg": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"failed": false,
"parsed": [
{
"name": "desktops",
"state": "active",
"vlan_id": 20
},
{
"name": "servers",
"state": "active",
"vlan_id": 30
},
{
"name": "printers",
"state": "active",
"vlan_id": 40
},
{
"name": "DMZ",
"state": "active",
"vlan_id": 50
}
]
}
}
ok: [rtr4] => {
"msg": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"failed": false,
"parsed": [
{
"name": "desktops",
"state": "active",
"vlan_id": 20
},
{
"name": "servers",
"state": "active",
"vlan_id": 30
},
{
"name": "printers",
"state": "active",
"vlan_id": 40
},
{
"name": "DMZ",
"state": "active",
"vlan_id": 50
}
]
}
}
PLAY RECAP *********************************************************************
rtr2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rtr4 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
In the output above you will see that the flat-file backup was parsed into structured data:
"parsed": [
{
"name": "desktops",
"state": "active",
"vlan_id": 20
}
The default output is JSON but can be easily transformed into YAML.
We covered two additional configuration state
parameters:
replaced
- enforced config for specified VLANsoverridden
- enforced config for ALL vlansGoing from merged
to replaced
to overridden
follows the automation adoption journey as network teams gain more confidence with automation.
We covered additional read-only state
parameters
rendered
- shows commands that would generate the desired configurationparsed
- turned a flat-file configuration (such as a backup) into structured data (versus modifying the actual device)These allow network automators to use resource modules in additional scenarios, such as disconnected environments. Network resource modules provide a consistent experience across different network devices.
The documentation guide provided additional info of using network resource modules.
The finished Ansible Playbook is provided here for an answer key:
You have completed the supplemental lab!
Click here to return to supplemental exercises
Click here to return to the Ansible Network Automation Workshop