{ "info": { "author": "network.toCode()", "author_email": "info@networktocode.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "Programming Language :: Python :: 3" ], "description": "[![Build Status](https://travis-ci.org/networktocode/ntc-templates.svg?branch=master)](https://travis-ci.org/networktocode/ntc-templates)\n\nNTC TEMPLATES\n=============\n\nRepository of TextFSM Templates for Network Devices, and Python wrapper for TextFSM's CliTable.\n\n[TextFSM](https://github.com/google/textfsm/wiki) is a project built by Google that takes CLI string output and passes each line through a series of regular expressions until it finds a match. The regular expressions use named capture groups to build a text table out of the significant text. The names of the capture groups are used as column headers, and the captured values are stored as rows in the table.\n\nThis project provides a large collection of TextFSM Templates (text parsers) for a variety of Networking Vendors. In addition to the templates, there is a function that will convert the CLI output into a CliTable object; the resulting text table is converted into a list of dictionaries mapping the column headers with each row in the table.\n\n\nInstallation and Usage\n----------------------\nThe project can be installed using either Git or PyPI; if you would like to use the templates outside of this project, then Git is the recommended approach.\n\n#### Git\n\n```shell\n$ git clone git@github.com:networktocode/ntc-templates.git\n$ \n# Optional steps to install ntc-templates as a python package\n$ pip install -e ntc-templates/\n$ \n```\n\n#### PyPI\n\n```shell\n$ pip install ntc_templates\n$ \n```\n\n#### Usage\n\n```python\n>>> from ntc_templates.parse import parse_output\n>>> vlan_output = (\n \"VLAN Name Status Ports\\n\"\n \"---- -------------------------------- --------- -------------------------------\\n\"\n \"1 default active Gi0/1\\n\"\n \"10 Management active \\n\"\n \"50 VLan50 active Fa0/1, Fa0/2, Fa0/3, Fa0/4, Fa0/5,\\n\"\n \" Fa0/6, Fa0/7, Fa0/8\\n\"\n )\n>>> vlan_parsed = parse_output(platform=\"cisco_ios\", command=\"show vlan\", data=vlan_output)\n>>> vlan_parsed\n[\n {\n 'vlan_id': '1',\n 'name': 'default',\n 'status': 'active',\n 'interfaces': ['Gi0/1']\n },\n {\n 'vlan_id': '10',\n 'name': 'Management',\n 'status': 'active',\n 'interfaces': []\n },\n {\n 'vlan_id': '50',\n 'name': 'VLan50', 'status': 'active',\n 'interfaces': ['Fa0/1', 'Fa0/2', 'Fa0/3', 'Fa0/4', 'Fa0/5', 'Fa0/6', 'Fa0/7', 'Fa0/8']\n }\n]\n>>> \n```\n\nContributing\n------------\n\nPull requests are welcomed and automatically built and tested through TravisCI.\n\n### New Templates\nTo contribute new templates, each new pull request must include the following:\n\n- TextFSM template\n- Modified version of the **index** file\n- Tests\n * Raw version of text to be parsed\n * YAML file containing the expected parsed dictionary\n\n#### TextFSM Template\n\nTextFSM templates should be placed in the `./templates` directory and should adhere to the following NTC-Templates style.\nThe TextFSM template name should be in the following format:\n\n##### Naming\n\nThe template should be named using: `{{ vendor_os }}_{{ command_with_underscores }}.template`\n> Ex: cisco_ios_show_cdp_neighbors.template\n\nNote: The vendor name must be valid from the [os_choices](https://github.com/networktocode/ntc-templates/blob/master/tests/test_index_order.py#L59) tests, which is primarily based on [Netmiko](https://github.com/ktbyers/netmiko/tree/master/netmiko) list of supported vendors. New vendors added should adhere to **vendor_os**.\n> Ex: vmware_nsx\n\n##### Values\n\nThe capture group names should be in UPPERCASE.\n\nAn example of the proper format is shown below.\n\n```\nValue TIME (\\d+:\\d+:\\d+)\nValue TIMEZONE (\\S+)\nValue DAYWEEK (\\w+)\nValue MONTH (\\d+)\nValue DAY (\\d+)\nValue YEAR (\\d+)\n\nStart\n ^${TIME}\\s+${TIMEZONE}\\s+${DAYWEEK}\\s+${DAY}/${MONTH}/${YEAR} -> Record\n ^. -> Error\n```\n##### States\n\nIf the raw output has a heading, the `Start` state should match on the column headings and then transition to another state that will match the device's output table with the capture groups. This helps ensure the regex patterns for the capture groups are attempting to match the correct information, and allows templates to easily add additional States for tables that have different headings. Example:\n\n*Raw Output*\n```\n... omitted\nNetwork Next Hop Metric LocPrf Weight Path\n*> 111.111.111.111/32 112.112.112.112 4294967295 4294967295 65535 1000 1000 1000 i\n```\n\n*Sample Template*\n```\nStart\n# Checking for header\n^\\s*Network\\s+Next(?:\\s+|-)[Hh]op\\s+Metric\\s+LocPrf\\s+Weight\\s+Path\\s*$$ -> BGPTable\n\nBGPTable\n ... omitted\n```\n\nEach **state** should end with `^. -> Error`. This helps to ensure we're accounting for every line within the raw output for the command. This doesn't mean we have to capture all the data as a **Value**, but we do have to account for it. In addition, it is also good to provide an expression to match blank lines, `^\\s*$$`\n\nAn example would be the following raw output:\n```\nNAME: \"3640 chassis\", DESCR: \"3640 chassis\"\nPID: , VID: 0xFF, SN: FF1045C5\n```\n\nThe template would be the following:\n```\nValue NAME (.*)\nValue DESCRIPTION (.*)\n\nStart\n ^NAME:\\s+\"${NAME}\",\\s*DESCR:\\s+\"${DESCRIPTION}\"\n ^PID:\\s*,\\s*VID:\\s*\\S+,\\s*SN:\\s*\\S+\n ^\\s*$$\n ^. -> Error\n```\n\nTaking a look at the example template above, you notice that we're using **\\s*** and **\\s+**. These are the preferred way to match space characters, and should be used over the literal space character. For example, `This\\s+is\\s+preferred\\s*$$` vs `This is not preferred$$`\n\n- **\\s*** accounts for zero or more spaces (use when the output may or may not have a space between characters)\n- **\\s+** accounts for one or more spaces (use when output will have a space, but could have more than one space)\n\n#### Index File\n\nThe Index file binds the templates to the commands being run. Special care has been taken on ordering, as there is potential for issues. e.g. `show ip route` picking up for `show ip router vrf `. We have used a combination of ordering, as defined:\n\n - OS in alphabetical order\n - Template name in length order\n - When length is the same, use alphabetical order of command name\n - Keep space between OS's\n\nExample:\n\n```\nTemplate, Hostname, Platform, Command\n\n# same os, same length, used alphabetical order of command name\narista_eos_show_mlag.template, .*, arista_eos, sh[[ow]] ml[[ag]]\narista_eos_show_vlan.template, .*, arista_eos, sh[[ow]] vl[[an]]\n\n# os in alphabetical order and space between cisco_asa and arista_eos\ncisco_asa_dir.template, .*, cisco_asa, dir\n\n# same os, template name length different and space between cisco_asa and cisco_ios\ncisco_ios_show_capability_feature_routing.template, .*, cisco_ios, sh[[ow]] cap[[ability]] f[[eature]] r[[outing]]\ncisco_ios_show_interface_transceiver.template, .*, cisco_ios, sh[[ow]] int[[erface]] trans[[ceiver]]\ncisco_ios_show_cdp_neighbors_detail.template, .*, cisco_ios, sh[[ow]] c[[dp]] neig[[hbors]] det[[ail]]\n```\n\n#### Tests\nTests will be located in `./tests` with the following hierarchy:\n- `./tests/{{ vendor_os }}/{{ command_name }}/`\n\nThe `{{ command_name }}` directory should include the `.raw` file that includes the raw output of the command to be parsed, and the `.parsed` file of the returned structured data.\n```bash\n$ ls tests/cisco_ios/show_clock/\ncisco_ios_show_clock.parsed\ncisco_ios_show_clock.raw\n$ \n```\n\n##### Raw version of input text\n\nThe raw text file should contain **only** the output of the CLI command to be parsed. It should **not** contain the CLI command itself.\n\nAn example of the proper format is shown below:\n\n```bash\n$ cat tests/cisco_ios/show_clock/cisco_ios_show_clock.raw\n*18:57:38.347 UTC Mon Oct 19 2015\n$ \n```\n\n##### YAML file containing expected parsed dictionary\n\nThe parsed file should match the data that is returned from the `parse_output` function discussed in the beginning. Dictionary keys should be in lowercase.\n\nThe parsed text file should be placed in a directory in the `./tests` directory with the same name as the template file but replace `.template` file extension with `.parsed`. The raw text file and the parsed text file should be in the same directory.\n**ex. ./tests/cisco_ios/show_clock/**\n\nThere is an available helper that uses **Ansible** and **ntc-ansible** custom modules to create the parsed file automatically into the correct format. Helpers are located within `./helpers/`.\n\nAn example of the proper format is shown below:\n```bash\n$ cat ./tests/cisco_ios/show_clock/cisco_ios_show_clock.parsed\n---\nparsed_sample:\n - time: \"18:57:38.347\"\n timezone: \"UTC\"\n dayweek: \"Mon\"\n month: \"Oct\"\n day: \"19\"\n year: \"2015\"\n$ \n```\n\nMultiple `raw` and `parsed` files are supported per directory, and are encouraged, as there are differences depending on version, length, etc. Additional test files and more real life data helps ensure backwards compatibility is maintained as each template is updated and merged into the repo.\n\n### Updating/Fixing Existing Templates\nWhen either fixing a bug within a template or adding additional **Values** to be captured, additional test files should be added to ensure backwards compatibility and that the new data is being parsed correctly.\n\nTo add additional raw/parsed tests for a command:\n- Navigate to `./tests/{{ vendor_os }}/{{ command_name }}/`\n- Create new `.raw` and `.parsed` files within the directory, preferrably with a name identifying why the data is unique:\n * Existing raw: `./tests/cisco_ios/show_version/cisco_ios_show_version.raw`\n * New raw: `./tests/cisco_ios/show_version/cisco_ios_show_version_stack_platforms.raw`\n * Existing parsed: `./tests/cisco_ios/show_version/cisco_ios_show_version.parsed`\n * New parsed: `./tests/cisco_ios/show_version/cisco_ios_show_version_stack_platforms.parsed`\n\n#### Testing\nYou can test your changes locally within your Git branch before submitting a PR. If you do not have **tox** already installed, you can do that using pip or your systems package manager. Tox should be ran inside the **ntc-templates** root directory. The tox file is configured to run against python3.6, so either python3.6 needs to be available, or the tox.ini file will need to be updated with an available Python version.\n```bash\n$ tox\nGLOB sdist-make: /home/admin/ntc-templates/setup.py\npy36 inst-nodeps: /home/admin/ntc-templates/.tox/dist/ntc_templates-1.1.0.zip\npy36 installed: atomicwrites==1.3.0,attrs==19.1.0,importlib-metadata==0.18,more-itertools==7.1.0,ntc-templates==1.1.0,packaging==19.0,pkg-resources==0.0.0,pluggy==0.12.0,py==1.8.0,pyparsing==2.4.0,pytest==5.0.1,PyYAML==5.1.1,six==1.12.0,terminal==0.4.0,textfsm==0.4.1,wcwidth==0.1.7,zipp==0.5.2\npy36 runtests: PYTHONHASHSEED='1913863515'\npy36 runtests: commands[0] | pytest\n=============================================================================== test session starts ================================================================================\nplatform linux -- Python 3.6.8, pytest-5.0.1, py-1.8.0, pluggy-0.12.0\nrootdir: /home/admin/ntc-templates\ncollected 364 items\n\ntests/test_index_order.py . [ 0%]\ntests/test_structured_data_against_parsed_reference_files.py ............................................................................................................... [ 30%]\n............................................................................................................................................................................ [ 78%]\n............................................................................... [ 99%]\ntests/test_testcases_exists.py . [100%]\n\n=========================================================================== 364 passed in 15.69 seconds ============================================================================\n_____________________________________________________________________________________ summary ______________________________________________________________________________________\n py36: commands succeeded\n congratulations :)\n```\n\nQuestions\n---------\n\nFor any questions or comments, please feel free to swing by the [networktocode slack channel](https://networktocode.slack.com).\n\nSign up [here](http://slack.networktocode.com/)\n\n\nRelease History\n---------------\n\n1.0.0\n+++++\n\n* First initial release\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/networktocode/ntc-templates", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "ntc-templates", "package_url": "https://pypi.org/project/ntc-templates/", "platform": "", "project_url": "https://pypi.org/project/ntc-templates/", "project_urls": { "Homepage": "https://github.com/networktocode/ntc-templates" }, "release_url": "https://pypi.org/project/ntc-templates/1.2.1/", "requires_dist": [ "textfsm", "terminal" ], "requires_python": "", "summary": "Package to return structured data from the output of network devices.", "version": "1.2.1" }, "last_serial": 5887942, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "4e560111bde8d19e5dcf59f04ceaa222", "sha256": "b9a5a8f843e85ec4078271b3320e3a397529f3044b5d49030830041821fa586f" }, "downloads": -1, "filename": "ntc_templates-1.0.0.tar.gz", "has_sig": false, "md5_digest": "4e560111bde8d19e5dcf59f04ceaa222", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 110500, "upload_time": "2018-07-05T12:53:25", "url": "https://files.pythonhosted.org/packages/2d/8b/763724f71832002b4f9800515501c2bf3384dec8f283bf7d1fd987245e83/ntc_templates-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "d8045996811ef720cb20afd358c804d7", "sha256": "3b1648121047e2c6fd861427cc1c9acd8c18a912d5a19f2bd54037930a958e1d" }, "downloads": -1, "filename": "ntc_templates-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "d8045996811ef720cb20afd358c804d7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 172157, "upload_time": "2019-04-24T20:58:27", "url": "https://files.pythonhosted.org/packages/18/6a/c2bd05ab032319063034f337bc2e7b457beaa5896a6a7aac927f3fc34f53/ntc_templates-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0733712c83432ff05da63629e2c71488", "sha256": "40bcc2f922baefcdebff37908b090971e120d685788470d2d62b4dc2fef3c7f4" }, "downloads": -1, "filename": "ntc_templates-1.1.0.tar.gz", "has_sig": false, "md5_digest": "0733712c83432ff05da63629e2c71488", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 88828, "upload_time": "2019-04-24T20:58:29", "url": "https://files.pythonhosted.org/packages/a8/fe/8dc71398b1b47fbe94e689f9d8d1fc35e80984e5041ed837d134b69d50a9/ntc_templates-1.1.0.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "a97dc210b28139add8c35d289d41ad3d", "sha256": "17ecc972803667ddb856bd141e3a9ca22507a758757b8a79ec53483c24d66fc0" }, "downloads": -1, "filename": "ntc_templates-1.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a97dc210b28139add8c35d289d41ad3d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 179277, "upload_time": "2019-09-26T01:35:57", "url": "https://files.pythonhosted.org/packages/7f/a9/13e5998fb651027567b904ee1be11a304a76fa6fd9a42f9cb4003e45ccd4/ntc_templates-1.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4574e39eb1cac44a8627ef645916e51b", "sha256": "e8afcddde4bc08f0ba8ab6f964be097c848bc2162467490f502e80827dd4bf4d" }, "downloads": -1, "filename": "ntc_templates-1.2.1.tar.gz", "has_sig": false, "md5_digest": "4574e39eb1cac44a8627ef645916e51b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 98527, "upload_time": "2019-09-26T01:36:00", "url": "https://files.pythonhosted.org/packages/a4/9c/7103d3d22d9d874eef578bdd32e942e0c820d9d7f533352ac14a9aa20f93/ntc_templates-1.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a97dc210b28139add8c35d289d41ad3d", "sha256": "17ecc972803667ddb856bd141e3a9ca22507a758757b8a79ec53483c24d66fc0" }, "downloads": -1, "filename": "ntc_templates-1.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a97dc210b28139add8c35d289d41ad3d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 179277, "upload_time": "2019-09-26T01:35:57", "url": "https://files.pythonhosted.org/packages/7f/a9/13e5998fb651027567b904ee1be11a304a76fa6fd9a42f9cb4003e45ccd4/ntc_templates-1.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4574e39eb1cac44a8627ef645916e51b", "sha256": "e8afcddde4bc08f0ba8ab6f964be097c848bc2162467490f502e80827dd4bf4d" }, "downloads": -1, "filename": "ntc_templates-1.2.1.tar.gz", "has_sig": false, "md5_digest": "4574e39eb1cac44a8627ef645916e51b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 98527, "upload_time": "2019-09-26T01:36:00", "url": "https://files.pythonhosted.org/packages/a4/9c/7103d3d22d9d874eef578bdd32e942e0c820d9d7f533352ac14a9aa20f93/ntc_templates-1.2.1.tar.gz" } ] }