{"id":20589592,"url":"https://github.com/ciscodevnet/ansible-pyats","last_synced_at":"2025-04-14T22:07:40.962Z","repository":{"id":128722397,"uuid":"188650494","full_name":"CiscoDevNet/ansible-pyats","owner":"CiscoDevNet","description":null,"archived":false,"fork":false,"pushed_at":"2019-11-18T23:20:47.000Z","size":29,"stargazers_count":46,"open_issues_count":6,"forks_count":14,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-14T22:07:29.938Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CiscoDevNet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-26T07:00:01.000Z","updated_at":"2024-07-30T11:58:27.000Z","dependencies_parsed_at":"2023-05-06T10:17:00.130Z","dependency_job_id":null,"html_url":"https://github.com/CiscoDevNet/ansible-pyats","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CiscoDevNet%2Fansible-pyats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CiscoDevNet%2Fansible-pyats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CiscoDevNet%2Fansible-pyats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CiscoDevNet%2Fansible-pyats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CiscoDevNet","download_url":"https://codeload.github.com/CiscoDevNet/ansible-pyats/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248968845,"owners_count":21191162,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T07:29:57.777Z","updated_at":"2025-04-14T22:07:40.955Z","avatar_url":"https://github.com/CiscoDevNet.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"ansible-pyats\n=========\n\nansible-genie is a implementation of the [pyATS](https://developer.cisco.com/pyats/) network testing framework in an\nAnsible role.  It contains modules, filters, and tasks:\n* Run a command and get structured output\n* \"snapshot\" the output of a command and save it to a file\n* Compare the current output of a command to a previous \"snapshot\"\n\n## Installation\n\nFirst, install the Python dependencies:\n\n```bash\n$ pip install pyats genie\n\u003csnip\u003e\nInstalling collected packages: pyats, genie\nSuccessfully installed genie-19.9 pyats-19.9.2\n```\n\n\u003e pyATS and Genie require Python \u003e=3.4.\n\n### Manual\n\nFor manual installation, you can just clone the repository into your\n[`ANSIBLE_ROLES_PATH`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-roles-path):\n\n```bash\n$ git clone https://github.com/CiscoDevNet/ansible-pyats \"${ANSIBLE_ROLES_PATH:-roles}/ansible-pyats\"\nCloning into 'roles/ansible-pyats'...\nremote: Enumerating objects: 83, done.\nremote: Counting objects: 100% (83/83), done.\nremote: Compressing objects: 100% (56/56), done.\nremote: Total 83 (delta 28), reused 56 (delta 12), pack-reused 0\nUnpacking objects: 100% (83/83), done.\n```\n\n\n### Ansible Galaxy\n\nIf you are using [Ansible Galaxy](https://docs.ansible.com/ansible/latest/reference_appendices/galaxy.html),\nyou can use this role by adding the following to your `requirements.yml`:\n\n```yaml\n- src: https://github.com/CiscoDevNet/ansible-pyats\n  scm: git\n  name: ansible-pyats\n```\n\nNext, install your Galaxy dependencies:\n\n```bash\n$ ansible-galaxy install -r requirements.yml -p \"${ANSIBLE_ROLES_PATH:-roles}\"\n```\n\n## Modules\n* `pyats_parse_command`: Run a command on a remote device and return the structured output\n\n## Filters\n* `pyats_parser`: provides structured data from unstructured command output\n* `pyats_diff`: provides the difference between two data structures\n\n## Example Playbooks\n\n### Run a command and retrieve the structured output\n```yaml\n- hosts: router\n  connection: network_cli\n  gather_facts: no\n  roles:\n    - ansible-pyats\n  tasks:\n    - pyats_parse_command:\n        command: show ip route bgp\n      register: output\n\n    - debug:\n        var: output.structured\n```\n\n### Snapshot the output of a command to a file\n```yaml\n- hosts: router\n  connection: network_cli\n  gather_facts: no\n  roles:\n    - ansible-pyats\n  tasks:\n    - include_role:\n        name: ansible-pyats\n        tasks_from: snapshot_command\n      vars:\n        command: show ip route\n        file: \"{{ inventory_hostname }}_routes.json\"\n```\n\n#### Role Variables\n\n* `command`: the command to run on the device\n* `file`: the name of the file in which to store the command \"shapshot\"\n\n### Compare the output of a command with a previous snapshot\n```yaml\n- hosts: router\n  connection: network_cli\n  gather_facts: no\n  roles:\n    - ansible-pyats\n  tasks:\n    - include_role:\n        name: ansible-pyats\n        tasks_from: compare_command\n      vars:\n        command: show ip route\n        file: \"{{ inventory_hostname }}_routes.json\"\n```\n\n#### Role Variables\n\n* `command`: the command to run on the device\n* `file`: the name of the file in which to store the command \"shapshot\"\n\n### Using the `pyats_parser` filter directly\n```yaml\n- hosts: router\n  connection: network_cli\n  gather_facts: no\n  roles:\n    - ansible-pyats\n  tasks:\n    - name: Run command\n      cli_command:\n        command: show ip route\n      register: cli_output\n    \n    - name: Parsing output\n      set_fact:\n        parsed_output: \"{{ cli_output.stdout | pyats_parser('show ip route', 'iosxe') }}\"\n```\n\n### Using the `pyats_diff` filter directly\n```yaml\n- name: Diff current and snapshot\n  set_fact:\n    diff_output: \"{{ current_output | pyats_diff(previous_output) }}\"\n```\n\n### Change ACL configuration and compare before and after configs using `genie_config_diff`\n```yaml\n---\n\n- hosts: cisco\n  gather_facts: no\n  connection: network_cli\n\n  tasks:\n    - name: collect config (before)\n      ios_command:\n        commands:\n          - show run\n      register: result_before\n\n    - name: load new acl into device\n      ios_config:\n        lines:\n          - permit ip host 192.168.114.1 any\n          - permit ip host 192.168.114.2 any\n          - permit ip host 192.168.114.3 any\n        parents: ip access-list extended test\n        save_when: modified\n\n    - name: collect config (after)\n      ios_command:\n        commands:\n          - show run\n      register: result_after\n\n    - name: debug\n      debug:\n        msg: \"{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], mode='add', exclude=exclude_list) }}\"\n\n  vars:\n    exclude_list:\n      - (^Using.*)\n      - (Building.*)\n      - (Current.*)\n      - (crypto pki certificate chain.*)\n```\nThe 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.  \nThe argument `exclude` means command lists which is excluded when comparing before and after configs.\nIn the playbook example above, variable `excluded_list`, which is defined as the play variable, is used.\n\n#### Other examples\n```yaml\n        msg: \"{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0]) }}\"\n        msg: \"{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], mode='remove') }}\"\n        msg: \"{{ result_before.stdout[0] | genie_config_diff(result_after.stdout[0], exclude=exclude_list) }}\"\n```\n\n#### The result of example playbook\n```yaml\nPLAY [cisco] **********************************************************************************\n\nTASK [collect config (before)] ****************************************************************\nok: [test3]\n\nTASK [load new acl into device] ***************************************************************\nok: [test3]\n\nTASK [collect config (after)] *****************************************************************\nok: [test3]\n\nTASK [debug] **********************************************************************************\nok: [test3] =\u003e {\n    \"msg\": [\n        \"ip access-list extended test:\",\n        \"+ permit ip host 192.168.114.1 any: \",\n        \"+ permit ip host 192.168.114.2 any: \",\n        \"+ permit ip host 192.168.114.3 any: \"\n    ]\n}\n\nPLAY RECAP ************************************************************************************\ntest3                      : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   \n```\n\n\n### Compare show commands using `genie_parser_diff`\nThis filter can compare the output of show commands parsed by Genie parser. The arguments `mode` and `exclude` also can be used.\n\n```yaml\n    - name: debug\n      debug:\n        msg: \"{{ sh_int_parsed_before | genie_parser_diff(sh_int_parsed_after, mode='modified', exclude=exclude_list) }}\"\n        \n  vars:\n    exclude_list:\n      - (.*in_octets.*)\n      - (.*in_pkts.*)\n      - (.*out_octets.*)\n      - (.*out_pkts.*)\n```\n\nLicense\n-------\n\nCisco Sample License\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciscodevnet%2Fansible-pyats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fciscodevnet%2Fansible-pyats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciscodevnet%2Fansible-pyats/lists"}