https://github.com/ciscodevnet/ansible-pyats
https://github.com/ciscodevnet/ansible-pyats
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/ciscodevnet/ansible-pyats
- Owner: CiscoDevNet
- License: other
- Created: 2019-05-26T07:00:01.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2019-11-18T23:20:47.000Z (over 5 years ago)
- Last Synced: 2025-04-14T22:07:29.938Z (2 months ago)
- Language: Python
- Size: 28.3 KB
- Stars: 46
- Watchers: 12
- Forks: 14
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
ansible-pyats
=========ansible-genie is a implementation of the [pyATS](https://developer.cisco.com/pyats/) network testing framework in an
Ansible role. It contains modules, filters, and tasks:
* Run a command and get structured output
* "snapshot" the output of a command and save it to a file
* Compare the current output of a command to a previous "snapshot"## Installation
First, install the Python dependencies:
```bash
$ pip install pyats genieInstalling collected packages: pyats, genie
Successfully installed genie-19.9 pyats-19.9.2
```> pyATS and Genie require Python >=3.4.
### Manual
For manual installation, you can just clone the repository into your
[`ANSIBLE_ROLES_PATH`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-roles-path):```bash
$ git clone https://github.com/CiscoDevNet/ansible-pyats "${ANSIBLE_ROLES_PATH:-roles}/ansible-pyats"
Cloning into 'roles/ansible-pyats'...
remote: Enumerating objects: 83, done.
remote: Counting objects: 100% (83/83), done.
remote: Compressing objects: 100% (56/56), done.
remote: Total 83 (delta 28), reused 56 (delta 12), pack-reused 0
Unpacking objects: 100% (83/83), done.
```### Ansible Galaxy
If you are using [Ansible Galaxy](https://docs.ansible.com/ansible/latest/reference_appendices/galaxy.html),
you can use this role by adding the following to your `requirements.yml`:```yaml
- src: https://github.com/CiscoDevNet/ansible-pyats
scm: git
name: ansible-pyats
```Next, install your Galaxy dependencies:
```bash
$ ansible-galaxy install -r requirements.yml -p "${ANSIBLE_ROLES_PATH:-roles}"
```## Modules
* `pyats_parse_command`: Run a command on a remote device and return the structured output## Filters
* `pyats_parser`: provides structured data from unstructured command output
* `pyats_diff`: provides the difference between two data structures## Example Playbooks
### Run a command and retrieve the structured output
```yaml
- hosts: router
connection: network_cli
gather_facts: no
roles:
- ansible-pyats
tasks:
- pyats_parse_command:
command: show ip route bgp
register: output- debug:
var: output.structured
```### Snapshot the output of a command to a file
```yaml
- hosts: router
connection: network_cli
gather_facts: no
roles:
- ansible-pyats
tasks:
- include_role:
name: ansible-pyats
tasks_from: snapshot_command
vars:
command: show ip route
file: "{{ inventory_hostname }}_routes.json"
```#### Role Variables
* `command`: the command to run on the device
* `file`: the name of the file in which to store the command "shapshot"### Compare the output of a command with a previous snapshot
```yaml
- hosts: router
connection: network_cli
gather_facts: no
roles:
- ansible-pyats
tasks:
- include_role:
name: ansible-pyats
tasks_from: compare_command
vars:
command: show ip route
file: "{{ inventory_hostname }}_routes.json"
```#### Role Variables
* `command`: the command to run on the device
* `file`: the name of the file in which to store the command "shapshot"### Using the `pyats_parser` filter directly
```yaml
- hosts: router
connection: network_cli
gather_facts: no
roles:
- ansible-pyats
tasks:
- name: Run command
cli_command:
command: show ip route
register: cli_output
- name: Parsing output
set_fact:
parsed_output: "{{ cli_output.stdout | pyats_parser('show ip route', 'iosxe') }}"
```### Using the `pyats_diff` filter directly
```yaml
- name: Diff current and snapshot
set_fact:
diff_output: "{{ current_output | pyats_diff(previous_output) }}"
```### Change ACL configuration and compare before and after configs using `genie_config_diff`
```yaml
---- hosts: cisco
gather_facts: no
connection: network_clitasks:
- name: collect config (before)
ios_command:
commands:
- show run
register: result_before- name: load new acl into device
ios_config:
lines:
- permit ip host 192.168.114.1 any
- permit ip host 192.168.114.2 any
- permit ip host 192.168.114.3 any
parents: ip access-list extended test
save_when: modified- name: collect config (after)
ios_command:
commands:
- show run
register: result_after- name: debug
debug:
msg: "{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], mode='add', exclude=exclude_list) }}"vars:
exclude_list:
- (^Using.*)
- (Building.*)
- (Current.*)
- (crypto pki certificate chain.*)
```
The argument `mode` can be `add` (displays added commands in result_after), `remove` (displays removed commands in result_after), or `modified` (displays modified commands). If `mode` argument is not specified, added, removed, and modified commands are displayed.
The argument `exclude` means command lists which is excluded when comparing before and after configs.
In the playbook example above, variable `excluded_list`, which is defined as the play variable, is used.#### Other examples
```yaml
msg: "{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0]) }}"
msg: "{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], mode='remove') }}"
msg: "{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], exclude=exclude_list) }}"
```#### The result of example playbook
```yaml
PLAY [cisco] **********************************************************************************TASK [collect config (before)] ****************************************************************
ok: [test3]TASK [load new acl into device] ***************************************************************
ok: [test3]TASK [collect config (after)] *****************************************************************
ok: [test3]TASK [debug] **********************************************************************************
ok: [test3] => {
"msg": [
"ip access-list extended test:",
"+ permit ip host 192.168.114.1 any: ",
"+ permit ip host 192.168.114.2 any: ",
"+ permit ip host 192.168.114.3 any: "
]
}PLAY RECAP ************************************************************************************
test3 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```### Compare show commands using `genie_parser_diff`
This filter can compare the output of show commands parsed by Genie parser. The arguments `mode` and `exclude` also can be used.```yaml
- name: debug
debug:
msg: "{{ sh_int_parsed_before | genie_parser_diff(sh_int_parsed_after, mode='modified', exclude=exclude_list) }}"
vars:
exclude_list:
- (.*in_octets.*)
- (.*in_pkts.*)
- (.*out_octets.*)
- (.*out_pkts.*)
```License
-------Cisco Sample License