ansible.network icon indicating copy to clipboard operation
ansible.network copied to clipboard

[proposal] Plugin to validate network configuration against a predefined rule set

Open NilashishC opened this issue 3 years ago • 1 comments

Proposal:

Add support for a config validation plugin that evaluates network configurations against a predefined set of rules and renders warnings/failures based on the outcome of the validation task. This is aimed to precede *_config tasks in a playbook and would allow us to catch potential errors in the candidate config before the succeeding tasks make configuration changes on the target. The rule set(s) are expected to be implemented by the users based on their exact needs and target platforms.

  • Status: New
  • Proposal type: Action Plugin
  • Targeted Release:
  • Associated PR:

Motivation

Describe the reasons for this proposal. Have the ability to determine the "correctness" of the configuration to be pushed and ensure a more predictable outcome from the *_config modules.

Problems

As a user of the *_config modules:

  • I want to ensure that the candidate configuration is properly linted to minimize idempotence issues.
  • I want to ensure that every candidate configuration pushed to the target device is in terms with a rule set.

Solution proposal

Playbook:

- hosts: sw01
  gather_facts: no
  tasks:
  - name: Validate candidate config against a pre-defined set of rules
    ansible.utils.validate_config:
      config: "{{ lookup('file', 'candidate.cfg') }}"
      rules: "{{ role_path }}/rules/rules.yaml"

candidate.cfg:

interface Eth1/1
  description test-description-too-long
  no switchport

interface Ethernet1/2
  description intf-2

interface port-channel1
  description po-1

interface po2.1
  description po2

interface Loopback 10
  description lo10

rules.yaml:

---
- name: 1. Interface description should not be more than 8 chars
  example: "Matches description this-is-a-long-description"
  rule: 'description\s(.{9,})'
  action: warn

- name: Ethernet interface names should be in format Ethernet[Slot/chassis number].[sub-intf number (optional)]
  example: "Matches interface Eth1/1, interface Eth 1/1, interface Ethernet 1/1, interface Ethernet 1/1.100"
  rule: 'interface\sE(?!\w{7}\d/\d(.\d+)?)'
  action: fail

- name: Ethernet interface names should be in format Ethernet[Slot/chassis number].[sub-intf number (optional)]
  example: "Matches interface eth1/1, interface eth 1/1, interface ethernet 1/1, interface ethernet 1/1.100"
  rule: 'interface\se(?!\w{7}\d/\d(.\d+)?)'
  action: fail

- name: Loopback interface names should be in format loopback[Virtual Interface Number]
  example: "Matches interface Lo10, interface Loopback 10"
  rule: 'interface\sl(?!\w{7}\d)'
  action: fail

- name: Loopback interface names should be in format loopback[Virtual Interface Number]
  example: "Matches interface lo10, interface loopback 10"
  rule: 'interface\sL(?!\w{7}\d)'
  action: fail

- name: Port Channel names should be in format port-channel[Port Channel number].[sub-intf number (optional)]
  example: "Matches interface port-channel 10, interface po10, interface port-channel 10.1"
  rule: 'interface\sp(?!\w{3}-\w{7}\d(.\d+)?)'
  action: fail

- name: Port Channel names should be in format port-channel[Port Channel number].[sub-intf number (optional)]
  example: "Matches interface Port-channel 10, interface Po10, interface Port-channel 10.1"
  rule: 'interface\sP(?!\w{3}-\w{7}\d(.\d+)?)'
  action: fail

Result:

result: {
  failures: [
    {
        "name": Ethernet interface names should be in format Ethernet[Slot/chassis number].[sub-intf number (optional)],
        "rule": 'interface\sE(?!\w{7}\d/\d(.\d+)?)',
        "config_line": "interface Eth1/1",
    },
    {
        "name": Port Channel names should be in format port-channel[Port Channel number].[sub-intf number (optional)],
        "rule": 'interface\sp(?!\w{3}-\w{7}\d(.\d+)?)',
        "config_line": "interface po2.1",
    },
    {
        "name": Loopback interface names should be in format loopback[Virtual Interface Number],
        "rule": 'interface\sL(?!\w{7}\d)',
        "config_line": "interface Loopback 10",
    },
  ],
  warnings: [
    {
        "name": "Interface description should not be more than 8 chars",
        "rule": "description\s(.{9,})",
        "config_line": "description test-description-too-long", 
    },
  ]
}

NilashishC avatar Jun 05 '21 12:06 NilashishC