Heya,
TLDR, the summary: I’m trying to use Ansible 2.2’s network modules to manage configs on EOS/IOS switches. I’m trying to find a module invocation that adds a number of, say, radius-server commands, removes any that aren’t expected, and also diff properly before applying config so I can accurately measure which switches were already correctly configured and which weren’t. What follows is my series of attempts at making this work before I was out of options short of doing the config diffs manually.
So for example, I want to write a task that manages the radius-server lines on an EOS device. The existing config might be…
`
radius-server host 1.1.1.1
radius-server host 2.2.2.2
radius-server host 3.3.3.3
`
…and I want to replace it with my good configuration:
radius-server host 2.2.2.2 radius-server host 3.3.3.3
BUT, I don’t know what the original two lines are for sure. Maybe they’re as above, or maybe one of them is actually 4.4.4.4 instead. So what I’m really trying to do is remove any lines that begin with “radius-server host …” and then add on the two good config lines. I can’t find a way to make this work that accurately diffs the running config and avoids pushing changes if the lines already match.
I found a couple ‘workarounds’ but they each suffer from this problem. One of them is to use ‘before’ and run ‘no radius-server host’, nuking the existing config and replacing it with my good config:
`
- name: Install new RADIUS server config.
eos_config:
provider: “{{ cli_connection_info }}”
lines: - radius-server host 1.1.1.1 vrf mgmt
- radius-server host 2.2.2.2 vrf mgmt
before: “no radius-server host”
match: none
replace: block
save: yes
`
“match” has to be “none” because if both of my good config lines are on the device, but there’s a third “radius-server host …” configured, I want to remove it. The above task accomplishes that but it always detects a diff, which means I can’t dry-run the play and I don’t get any feedback on how many devices in the fleet were actually different from the intended configuration.
But an even bigger problem is that not all OSs/versions support a generic “no …” command as used above. IOS, for example, will not accept “no radius-server host”; an IP must be specified, so I must somehow know what “bad” IPs are already configured before running the config module. And, I’m trying to eliminate config drift so I don’t know what those IPs are off hand. So here’s another workaround:
`
-
name: Get current RADIUS server config.
ios_command:
provider: “{{ cli_connection_info }}”
commands: “show running-config | include radius-server host”
register: current_config -
name: Build cleanup commands.
set_fact:
ios_radius_commands_to_remove: |
{% set output = %}
{% for existing_line in current_config.stdout_lines[0] %}
{% if existing_line %}
{% set _ = output.append('no ’ + existing_line) %}
{% endif %}
{% endfor %}
{{ output }} -
name: Cleanup old and install new config.
ios_config:
provider: “{{ cli_connection_info }}”
before: “{{ ios_radius_commands_to_remove }}”
lines: -
radius-server host 1.1.1.1 vrf mgmt
-
radius-server host 2.2.2.2 vrf mgmt
match: none
replace: block
`
This makes sure I catch all unknown, bad lines of config and works on pretty much every platform I care about but it too needs to be forced with ‘match: none’ to work; especially on platforms that don’t support config sessions or a similar diff mechanism.
So the last thing I tried was the ‘config’ parameter. From its documentation, I understand it to be a user-provided parameter to replace the auto-fetched running-config from a device. To illustrate this understanding, I would expect something like this to never report a diff and not even connect to the device:
`
- name: Install RADIUS server config.
ios_config:
provider: “{{ cli_connection_info }}”
config: - radius-server host 1.1.1.1 vrf mgmt
- radius-server host 2.2.2.2 vrf mgmt
lines: - radius-server host 1.1.1.1 vrf mgmt
- radius-server host 2.2.2.2 vrf mgmt
match: line
replace: line
`
But, it does. The module still reports a diff and pushes the content of ‘lines’ to the device. I can’t discern any difference in behavior when using the config parameter.
So, does anyone else have a good way of doing this? At this point I can only assume I went the wrong way on some really simple assumption or the module doesn’t support this behavior. But the ability to specify a class of config that could be unexpected and should be pruned is such a useful feature, a config management system is incomplete without it.