-
Notifications
You must be signed in to change notification settings - Fork 557
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
45 changed files
with
6,654 additions
and
271 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
FROM debian:stretch | ||
|
||
## Install min deps | ||
RUN apt-get update | ||
|
||
COPY ./ /var/cache/napalm/ | ||
|
||
## Install NAPALM & underlying libraries dependencies | ||
RUN apt-get install -y python-cffi python-dev libxslt1-dev libssl-dev libffi-dev \ | ||
&& apt-get install -y python-pip \ | ||
&& pip install -U cffi \ | ||
&& pip install -U cryptography \ | ||
&& pip install /var/cache/napalm/ | ||
|
||
RUN rm -rf /var/lib/apt/lists/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,4 @@ Tutorials | |
extend_driver | ||
wrapup | ||
ansible-napalm | ||
mock_driver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
Unit tests: Mock driver | ||
======================= | ||
|
||
A mock driver is a software that imitates the response pattern of another | ||
system. It is meant to do nothing but returns the same predictable result, | ||
usually of the cases in a testing environment. | ||
|
||
A driver `mock` can mock all actions done by a common napalm driver. It can be | ||
used for unit tests, either to test napalm itself or inside external projects | ||
making use of napalm. | ||
|
||
|
||
Overview | ||
-------- | ||
|
||
For any action, the ``mock`` driver will use a file matching a specific pattern | ||
to return its content as a result. | ||
|
||
Each of these files will be located inside a directory specified at the driver | ||
initialization. Their names depend on the entire call name made to the | ||
driver, and about their order in the call stack. | ||
|
||
|
||
Replacing a standard driver by a ``mock`` | ||
----------------------------------------- | ||
|
||
Get the driver in napalm:: | ||
|
||
>>> import napalm | ||
>>> driver = napalm.get_network_driver('mock') | ||
|
||
And instantiate it with any host and credentials:: | ||
|
||
device = driver( | ||
hostname='foo', username='user', password='pass', | ||
optional_args={'path': path_to_results} | ||
) | ||
|
||
Like other drivers, ``mock`` takes optional arguments: | ||
|
||
- ``path`` - Required. Directory where results files are located | ||
|
||
Open the driver:: | ||
|
||
>>> device.open() | ||
|
||
A user should now be able to call any function of a standard driver:: | ||
|
||
>>> device.get_network_instances() | ||
|
||
But should get an error because no mocked data is yet written:: | ||
|
||
NotImplementedError: You can provide mocked data in get_network_instances.1 | ||
|
||
|
||
Mocked data | ||
----------- | ||
|
||
We will use ``/tmp/mock`` as an example of a directory that will contain | ||
our mocked data. Define a device using this path:: | ||
|
||
>>> with driver('foo', 'user', 'pass', optional_args={'path': '/tmp/mock'}) as device: | ||
|
||
Mock a single call | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
In order to be able to call, for example, ``device.get_interfaces()``, a mocked | ||
data is needed. | ||
|
||
To build the file name that the driver will look for, take the function name | ||
(``get_interfaces``) and suffix it with the place of this call in the device | ||
call stack. | ||
|
||
.. note:: | ||
``device.open()`` counts as a command. Each following order of call will | ||
start at 1. | ||
|
||
Here, ``get_interfaces`` is the first call made to ``device`` after ``open()``, | ||
so the mocked data need to be put in ``/tmp/mock/get_interfaces.1``:: | ||
|
||
|
||
{ | ||
"Ethernet1/1": { | ||
"is_up": true, "is_enabled": true, "description": "", | ||
"last_flapped": 1478175306.5162635, "speed": 10000, | ||
"mac_address": "FF:FF:FF:FF:FF:FF" | ||
}, | ||
"Ethernet1/2": { | ||
"is_up": true, "is_enabled": true, "description": "", | ||
"last_flapped": 1492172106.5163276, "speed": 10000, | ||
"mac_address": "FF:FF:FF:FF:FF:FF" | ||
} | ||
} | ||
|
||
The content is the wanted result of ``get_interfaces`` in JSON, exactly as | ||
another driver would return it. | ||
|
||
Mock multiple iterative calls | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
If ``/tmp/mock/get_interfaces.1`` was defined and used, for any other call on | ||
the same device, the number of calls needs to be incremented. | ||
|
||
For example, to call ``device.get_interfaces_ip()`` after | ||
``device.get_interfaces()``, the file ``/tmp/mock/get_interfaces_ip.2`` needs | ||
to be defined:: | ||
|
||
{ | ||
"Ethernet1/1": { | ||
"ipv6": {"2001:DB8::": {"prefix_length": 64}} | ||
} | ||
} | ||
|
||
Mock a CLI call | ||
~~~~~~~~~~~~~~~ | ||
|
||
``device.cli(commands)`` calls are a bit different to mock, as a suffix | ||
corresponding to the command applied to the device needs to be added. As | ||
before, the data mocked file will start by ``cli`` and the number of calls done | ||
before (here, ``cli.1``). Then, the same process needs to be applied to each | ||
command. | ||
|
||
Each command needs to be sanitized: any special character (`` -,./\``, etc.) | ||
needs to be replaced by ``_``. Add the index of this command as it is sent to | ||
``device.cli()``. Each file then will contain the raw wanted output of its | ||
associated command. | ||
|
||
Example | ||
^^^^^^^ | ||
|
||
Example with 2 commands, ``show interface Ethernet 1/1`` and ``show interface | ||
Ethernet 1/2``. | ||
|
||
To define the mocked data, create a file ``/tmp/mock/cli.1.show_interface_Ethernet_1_1.0``:: | ||
|
||
Ethernet1/1 is up | ||
admin state is up, Dedicated Interface | ||
|
||
And a file ``/tmp/mock/cli.1.show_interface_Ethernet_1_2.1``:: | ||
|
||
Ethernet1/2 is up | ||
admin state is up, Dedicated Interface | ||
|
||
And now they can be called:: | ||
|
||
>>> device.cli(["show interface Ethernet 1/1", "show interface Ethernet 1/2"]) | ||
|
||
|
||
Mock an error | ||
~~~~~~~~~~~~~ | ||
|
||
The `mock` driver can raise an exception during a call, to simulate an error. | ||
An error definition is actually a json composed of 3 keys: | ||
|
||
* `exception`: the exception type that will be raised | ||
* `args` and `kwargs`: parameters sent to the exception constructor | ||
|
||
For example, to raise the exception `ConnectionClosedException` when calling | ||
``device.get_interfaces()``, the file ``/tmp/mock/get_interfaces.1`` needs to | ||
be defined:: | ||
|
||
{ | ||
"exception": "napalm.base.exceptions.ConnectionClosedException", | ||
"args": [ | ||
"Connection closed." | ||
], | ||
"kwargs": {} | ||
} | ||
|
||
Now calling `get_interfaces()` for the 1st time will raise an exception:: | ||
|
||
>>> device.get_interfaces() | ||
ConnectionClosedException: Connection closed | ||
|
||
As before, mock will depend on the number of calls. If a second file | ||
``/tmp/mock/get_interfaces.2`` was defined and filled with some expected data | ||
(not an exception), retrying `get_interfaces()` will run correctly if the first | ||
exception was caught. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.