Skip to content

Commit

Permalink
Merge branch 'develop' into modify_ios_lldp_template
Browse files Browse the repository at this point in the history
  • Loading branch information
mirceaulinic authored Mar 21, 2024
2 parents b5344e7 + 077be75 commit af61c3f
Show file tree
Hide file tree
Showing 209 changed files with 7,059 additions and 2,653 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: [3.7, 3.8, 3.9, 3.10.0]
python-version: [3.8, 3.9, 3.10.9, 3.11, 3.12.0]

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

Expand Down Expand Up @@ -54,20 +54,20 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .
pip install -r requirements.txt
pip install -r requirements-dev.txt
python -m pip install -r docs/requirements.txt
pip install -r requirements-dev.txt
pip install -r requirements.txt
- name: Doctests
run: |
Expand Down
17 changes: 9 additions & 8 deletions .github/workflows/pythonpublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
pip install setuptools wheel
- name: Build
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
- name: Publish
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ env

test/unit/test_devices.py

.report.json
report.json
tags
.pytest_cache/
Expand Down
3 changes: 2 additions & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ formats: all

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.7
version: 3.8
install:
- method: pip
path: .
- requirements: docs/requirements.txt
- requirements: requirements-dev.txt
- requirements: requirements.txt
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ Install
pip install napalm
```

*Note*: Beginning with release 5.0.0 and later, NAPALM offers support for
Python 3.8+ only.

*Note*: Beginning with release 4.0.0 and later, NAPALM offers support for
Python 3.7+ only.

Expand Down
6 changes: 3 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,13 @@ def build_getters_support_matrix(app):
if not (m.startswith("_") or m in EXCLUDE_METHODS)
}

regex_name = re.compile(r"(?P<driver>\w+)\/.*::test_(?P<getter>\w+)")
regex_name = re.compile(r"test.*/(?P<driver>\w+)\/.*::test_(?P<getter>\w+)")

filename = "./support/tests/report.json"
with open(filename, "r") as f:
data = json.loads(f.read())
for test in data["report"]["tests"]:
match = regex_name.search(test["name"])
for test in data["tests"]:
match = regex_name.search(test["nodeid"])
if match:
driver = match.group("driver")
drivers.add(driver)
Expand Down
55 changes: 44 additions & 11 deletions docs/development/testing_framework.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Testing Framework
-----------------

As napalm consists of multiple drivers and all of them have to provide similar functionality, we have developed a testing framework to provide a consistent test suite for all the drivers.
As NAPALM consists of multiple drivers and all of them have to provide similar functionality, we have developed a testing framework to provide a consistent test suite for all the drivers.

Features
________
Expand Down Expand Up @@ -42,7 +42,7 @@ By default, the tests are going to be run against mocked data but you can change
* ``NAPALM_USERNAME``
* ``NAPALM_PASSWORD``
* ``NAPALM_OPTIONAL_ARGS``

Mocking the ``open`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -56,29 +56,29 @@ Multiple test cases::
(napalm) ➜ napalm-eos git:(test_framework) ✗ ls test/unit/mocked_data/test_get_bgp_neighbors
lots_of_peers no_peers normal
(napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors
...
...
test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[lots_of_peers] <- ../napalm/napalm.base/test/getters.py PASSED
test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[no_peers] <- ../napalm/napalm.base/test/getters.py PASSED
test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[normal] <- ../napalm/napalm.base/test/getters.py PASSED

Missing test cases::

(napalm) ➜ napalm-eos git:(test_framework) ✗ ls test/unit/mocked_data/test_get_bgp_neighbors
ls: test/unit/mocked_data/test_get_bgp_neighbors: No such file or directory
(napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors
...
...
test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[no_test_case_found] <- ../napalm/napalm.base/test/getters.py FAILED

========================================================= FAILURES ==========================================================
___________________________________ TestGetter.test_get_bgp_neighbors[no_test_case_found] ___________________________________

cls = <test_getters.TestGetter instance at 0x10ed5eb90>, test_case = 'no_test_case_found'

@functools.wraps(func)
def wrapper(cls, test_case):
cls.device.device.current_test = func.__name__
cls.device.device.current_test_case = test_case

try:
# This is an ugly, ugly, ugly hack because some python objects don't load
# as expected. For example, dicts where integers are strings
Expand All @@ -87,7 +87,7 @@ Missing test cases::
if test_case == "no_test_case_found":
> pytest.fail("No test case for '{}' found".format(func.__name__))
E Failed: No test case for 'test_get_bgp_neighbors' found

../napalm/napalm.base/test/getters.py:64: Failed
================================================= 1 failed in 0.12 seconds ==================================================

Expand All @@ -96,8 +96,41 @@ Method not implemented::
(napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_probes_config
...
test/unit/test_getters.py::TestGetter::test_get_probes_config[no_test_case_found] <- ../napalm/napalm.base/test/getters.py SKIPPED

================================================= 1 skipped in 0.09 seconds =================================================

Testing Matrix
--------------

NAPALM leverages [Github Actions](https://docs.github.com/en/actions) to test and lint code on commits and pull requests.
If you want to test prior to opening a pull request, you can use [nektos/act](https://github.com/nektos/act) and Docker to locally run the tests

.. code-block:: console
$ act -j std_tests
[build/std_tests-4] 🚀 Start image=catthehacker/ubuntu:act-latest
[build/std_tests-3] 🚀 Start image=catthehacker/ubuntu:act-latest
[build/std_tests-1] 🚀 Start image=catthehacker/ubuntu:act-latest
[build/std_tests-2] 🚀 Start image=catthehacker/ubuntu:act-latest
[build/std_tests-5] 🚀 Start image=catthehacker/ubuntu:act-latest
[build/std_tests-4] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
[build/std_tests-1] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
[build/std_tests-3] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
[build/std_tests-5] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
[build/std_tests-2] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
...
| ---------------------------------------------------------------------
| TOTAL 9258 1836 80%
|
| ================= 619 passed, 80 skipped, 3 warnings in 19.97s =================
[build/std_tests-5] ✅ Success - Main Run Tests
[build/std_tests-5] ⭐ Run Post Setup Python 3.11
[build/std_tests-5] 🐳 docker exec cmd=[node /var/run/act/actions/actions-setup-python@v2/dist/cache-save/index.js] user= workdir=
[build/std_tests-5] ✅ Success - Post Setup Python 3.11
[build/std_tests-5] 🏁 Job succeeded
.. _`test_getters.py`: https://github.com/napalm-automation/napalm-eos/blob/a2fc2cf6a98b0851efe4cba907086191b8f1df02/test/unit/test_getters.py
.. _`conftest.py`: https://github.com/napalm-automation/napalm-eos/blob/a2fc2cf6a98b0851efe4cba907086191b8f1df02/test/unit/conftest.py
13 changes: 9 additions & 4 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
sphinx
sphinx-rtd-theme
sphinxcontrib-napoleon
invoke
urllib3==1.26.15 # https://github.com/readthedocs/readthedocs.org/issues/10290
sphinx==1.8.6
sphinx-rtd-theme==1.2.0
sphinxcontrib-napoleon==0.7
invoke==2.0.0
jinja2==2.11.3
MarkupSafe==2.0.1
pytest==7.2.2
ansible==4.10.0
5 changes: 3 additions & 2 deletions docs/support/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ General support matrix
===================== ========== ============= ==================== ================== ============ ============ ============
**Driver Name** eos junos iosxr_netconf iosxr nxos nxos_ssh ios
**Structured data** Yes Yes Yes No Yes No No
**Minimum version** 4.15.0F 12.1 7.0 5.1.0 6.1 [#g1]_ 12.4(20)T 6.3.2
**Minimum version** 4.15.0F 12.1 7.0 5.1.0 6.1 [#g1]_ 6.3.2 12.4(20)T
**Backend library** `pyeapi`_ `junos-eznc`_ `ncclient`_ `pyIOSXR`_ `pynxos`_ `netmiko`_ `netmiko`_
**Caveats** :doc:`eos` :doc:`iosxr_netconf` :doc:`nxos` :doc:`nxos` :doc:`ios`
===================== ========== ============= ==================== ================== ============ ============ ============
Expand All @@ -38,7 +38,7 @@ _ EOS Junos IOS-XR (NETCONF) IOS-XR (XML-Agent)
===================== ========== ===== ================ ================== ============== ==============
**Config. replace** Yes Yes Yes Yes Yes Yes
**Config. merge** Yes Yes Yes Yes Yes Yes
**Commit Confirm** Yes Yes No No No No
**Commit Confirm** Yes Yes No No No Yes
**Compare config** Yes Yes Yes Yes [#c1]_ Yes [#c4]_ Yes
**Atomic Changes** Yes Yes Yes Yes Yes/No [#c5]_ Yes/No [#c5]_
**Rollback** Yes [#c2]_ Yes Yes Yes Yes/No [#c5]_ Yes
Expand Down Expand Up @@ -141,6 +141,7 @@ ____________________________________
* :code:`eos_fn0039_config` (eos) - Transform old style configuration to the new style, available beginning with EOS release 4.23.0, as per FN 0039. Beware
that enabling this option will change the configuration you're loading through NAPALM. Default: ``False`` (won't change your configuration commands).
.. versionadded:: 3.0.1
* :code:`force_cfg_session_invalid` (eos) - Force the config_session to be cleared in case of issues, like `discard_config` failure. (default: ``False``)

The transport argument
______________________
Expand Down
2 changes: 1 addition & 1 deletion docs/support/ios.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ File Operation Prompts
______________________

By default IOS will prompt for confirmation on file operations. These prompts need to be disabled before the NAPALM-ios driver performs any such operation on the device.
This can be controlled using the `auto_file_prompt` optional arguement:
This can be controlled using the `auto_file_prompt` optional argument:

* `auto_file_prompt=True` (default): NAPALM will automatically add `file prompt quiet` to the device configuration before performing file operations,
and un-configure it again afterwards. If the device already had the command in its configuration then it will be silently removed as a result, and
Expand Down
2 changes: 1 addition & 1 deletion docs/support/nxos.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ One caveat of using netutils diff of configurations is that the diff is performe

Example assuming that the device config contains:

.. code-block::
.. code-block:: bash
interface loopback0
ip address 10.1.4.4/32
Expand Down
10 changes: 4 additions & 6 deletions docs/test.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#!/bin/bash
CWD=`pwd`
TEST_RESULTS_PATH="$CWD/support/tests"
REPOBASE=$CWD/..

if [ ! -f "report.json" ]; then
if [ ! -f ".report.json" ]; then
set -e
pip install -r ../requirements.txt -r ../requirements-dev.txt
pytest --rootdir $REPOBASE -c /dev/null --json-report --cov=./ -vs $REPOBASE/test*/*/test_getters.py

set +e
py.test -c /dev/null --cov=./ -vs --json=report.json ../test*/*/test_getters.py
set -e

cp report.json $TEST_RESULTS_PATH/report.json
cp .report.json $TEST_RESULTS_PATH/report.json
fi
44 changes: 26 additions & 18 deletions docs/tutorials/extend_driver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,26 @@ Bulding on the previous example, we can create a a simple parse to return what o

.. code-block:: python
def get_my_banner(self):
command = 'show banner motd'
output = self._send_command(command)
return_vars = {}
for line in output.splitlines():
split_line = line.split()
if "Site:" == split_line[0]:
return_vars["site"] = split_line[1]
elif "Device:" == split_line[0]:
return_vars["device"] = split_line[1]
elif "Floor:" == split_line[0]:
return_vars["floor"] = split_line[1]
elif "Room:" == split_line[0]:
return_vars["room"] = split_line[1]
return return_vars
from napalm.ios.ios import IOSDriver
class CustomIOSDriver(IOSDriver):
"""Custom NAPALM Cisco IOS Handler."""
def get_my_banner(self):
command = 'show banner motd'
output = self._send_command(command)
return_vars = {}
for line in output.splitlines():
split_line = line.split()
if "Site:" == split_line[0]:
return_vars["site"] = split_line[1]
elif "Device:" == split_line[0]:
return_vars["device"] = split_line[1]
elif "Floor:" == split_line[0]:
return_vars["floor"] = split_line[1]
elif "Room:" == split_line[0]:
return_vars["room"] = split_line[1]
return return_vars
Which can build.

Expand All @@ -85,8 +89,12 @@ be able to support their own environment.

.. code-block:: python
def get_my_banner(self):
raise NotImplementedError
from napalm.ios.ios import IOSDriver
class CustomIOSDriver(IOSDriver):
"""Custom NAPALM Cisco IOS Handler."""
def get_my_banner(self):
raise NotImplementedError
This feature is meant to allow for maximum amount of flexibility, but it is up to the user to ensure they do
not run into namespace issues, and follow best practices.
Loading

0 comments on commit af61c3f

Please sign in to comment.