YAML and Network Configurations

Table of contents

When working with YAML files to store network device configurations, you might encounter a common issue: multi-line strings representing commands are loaded as a single string without newline characters. This can create problems when applying these configurations to devices using tools like Netmiko, which expect commands to be separated by newlines. In this quick blog article, we'll explore the problem and provide a simple solution using YAML's literal style.
The Problem
Consider the following YAML snippet, which defines a configuration for a network device:
R1:
netmiko:
host: clab-ospf_foundations__ospf_broadcast-r1
device_type: cisco_ios
username: admin
password: autonetops
port: 22
config:
interface Ethernet0/1
ip address 100.100.100.1 255.255.255.0
!
interface Tunnel1234
ip address 10.1.1.1 255.255.255.0
no ip redirects
ip nhrp map 10.1.1.2 100.100.100.2
ip nhrp map 10.1.1.3 100.100.100.3
ip nhrp map 10.1.1.4 100.100.100.4
ip nhrp network-id 111
ip ospf network broadcast
ip ospf priority 100
tunnel source Ethernet0/1
tunnel mode gre multipoint
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
ip ospf network point-to-point
!
router ospf 1
network 1.1.1.1 0.0.0.0 area 0
network 10.1.1.0 0.0.0.255 area 0
When this YAML is loaded in Python using yaml.safe_load, the config section is interpreted as a single string with newlines replaced by spaces:
'interface Ethernet0/1 ip address 100.100.100.1 255.255.255.0 ! interface Tunnel1234 ...'
This "folded" string is not suitable for network automation tools, as they can't distinguish between individual commands.
The Solution
To preserve newlines in the configuration string, you can use YAML's literal style by adding a pipe symbol (|) after the config: key. This tells the YAML parser to keep the text exactly as written, including newlines and indentation. Here's the corrected YAML:
R1:
netmiko:
host: clab-ospf_foundations__ospf_broadcast-r1
device_type: cisco_ios
username: admin
password: autonetops
port: 22
config: |
interface Ethernet0/1
ip address 100.100.100.1 255.255.255.0
!
interface Tunnel1234
ip address 10.1.1.1 255.255.255.0
no ip redirects
ip nhrp map 10.1.1.2 100.100.100.2
ip nhrp map 10.1.1.3 100.100.100.3
ip nhrp map 10.1.1.4 100.100.100.4
ip nhrp network-id 111
ip ospf network broadcast
ip ospf priority 100
tunnel source Ethernet0/1
tunnel mode gre multipoint
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
ip ospf network point-to-point
!
router ospf 1
network 1.1.1.1 0.0.0.0 area 0
network 10.1.1.0 0.0.0.255 area 0
Now, when loaded with yaml.safe_load, the config section retains its newlines:
"interface Ethernet0/1\n ip address 100.100.100.1 255.255.255.0\n !\ninterface Tunnel1234\n ip address 10.1.1.1 255.255.255.0\n no ip redirects\n..."
This multi-line string can be split into individual commands, making it compatible with tools like Netmiko.
Why It Works
Default Behavior: Without the |, YAML uses the "folded" style, replacing newlines with spaces.
Literal Style: The | ensures that newlines and indentation are preserved, maintaining the configuration's structure.
Alternative Approach
You could also structure the config as a list of commands:
R1:
netmiko:
# ... connection details ...
config:
- interface Ethernet0/1
- ip address 100.100.100.1 255.255.255.0
- !
- interface Tunnel1234
# ... and so on
This loads as a Python list, which works well with some automation tools. However, it loses the indentation hierarchy, which can affect readability or functionality in certain contexts.
Conclusion
For network configurations in YAML, adding the | symbol to use the literal style is a straightforward fix to preserve newlines and indentation. This ensures your commands are loaded correctly and ready for automation, making it the preferred approach for hierarchical configurations like the one above. Happy automating!
Subscribe to my newsletter
Read articles from pDamasceno directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
