I did something similar for NTP on IOS, maybe this will help you:

1) Provide a list of NTP server addresses I want provisioned
    - { role: ntp, state: present,
              ntp_source_interface: Vlan10,
              ntp_servers:
                [ 0.us.pool.ntp.org,
                  1.1.1.1,
                  2.2.2.2,
                  3.3.3.3,
                 4.4.4.4 ] }

Later finding the NTP servers that may already be there on the IOS device. 
 In a past role, I obviously collected "show running-config" and set_fact 
"config" to hold that.  The regex_findall returns a list of all the ip 
address instances for 'ntp server' lines
- name: get current configured ntp servers
  set_fact: old_ntp_servers="{{ config | regex_findall('ntp server 
(.+)\\n') }}"

- name: get current configured ntp source
  set_fact: old_ntp_source="{{ config | regex_findall('ntp source (.+)\\n') 
}}"

- name: configure ios ntp parameters
  ios_template:
    src: "{{ state }}/ios.j2"
    config: "{{ config }}"
    provider: "{{ provider }}"

And then the template "ios.j2", basically I let Ansible's idempotency 
handle whether or not to issue "ntp server" commands.  And later I check 
for any ntp servers that were previously configured (remember I collected 
these in old_ntp_servers above) that are not in the list of ntp servers I 
want configured (ntp_servers) and then issue the "no ntp server" for those.
!
# Let Ansible idempotency decide for each line if the command needs to be 
issued
{% if ntp_source_interface is defined %}
  ntp source {{ ntp_source_interface }}
{% endif%}
!
# Let Ansible idempotency decide for each line if the command needs to be 
issued
{% if ntp_servers is defined %}
  {% for ntp_item in ntp_servers %}
    ntp server {{ ntp_item }}
  {% endfor %}
  !
  # If there are any ntp servers still listed that aren't in the list 
provided by
  # the user, remove them (compliance).
  {% for old_ntp_item in old_ntp_servers %}
    {% if old_ntp_item | lower not in ntp_servers | lower %}
      no ntp server {{ old_ntp_item }}
    {% endif %}
  {% endfor %}
{% endif%}
!

Hope this gives you some ideas


On Thursday, March 16, 2017 at 6:26:19 PM UTC-7, [email protected] wrote:
>
> 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.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/cff67867-eee9-4985-8a0b-ac119001bb58%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to