Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.8.3 #182

Merged
merged 26 commits into from
Jan 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
76bc7ca
Merge 'release-0.8.2' into develop
jerearista Feb 9, 2018
27da089
Bump dev version
jerearista Feb 9, 2018
722f615
Add development requirements file
jerearista Feb 9, 2018
46aaa8d
Fixing typo in bgp.py
alexfeig Apr 16, 2018
3ef84ba
Remove leaked base64 authentication string in debug logs
xavierhardy Jul 28, 2018
96a74fa
Remove useless requirements-dev.txt file
xavierhardy Jul 28, 2018
a58f392
Add ability to use eapi with certs.
mharista Jun 6, 2019
2807357
Add kwargs handling to HttpsEapiCertConnection class.
mharista Jun 6, 2019
bd96810
Remove print statements.
mharista Jun 6, 2019
eff975e
Update docs for new certificate parameters.
mharista Jun 26, 2019
35557de
Merge pull request #172 from arista-eosplus/certs
mharista Jun 26, 2019
9dbd98c
Updated imp usages to importlib.
mharista Nov 6, 2019
3a0c8ff
Remove old imp code and print statements. Fix flake8 issues.
mharista Nov 6, 2019
65be6c0
Add import_module comment back in.
mharista Nov 6, 2019
add22a6
Merge pull request #178 from arista-eosplus/issue177
mharista Nov 6, 2019
5174ae6
Update acl.py
kirankumarcelestial Nov 11, 2019
8cc1ee8
Merge pull request #180 from kirankumarcelestial/develop
mharista Nov 13, 2019
54bb000
Add 4.20.0F and 4.21.3F command syntax change
Dec 6, 2019
b906e45
Add 'peer-address heartbeat' (4.20.0F), vrrp coniguration CLI change …
Dec 10, 2019
c896e69
Add EOS version check
andriirr Dec 16, 2019
a74e21e
Fix 'test_get_interface_wo_ip_adddress' test, ssh-key parser, cleanup
andriirr Dec 16, 2019
d25639b
Fix test configuration, typos
andriirr Jan 2, 2020
9dfd1f7
Fix test eapi access details
andriirr Jan 2, 2020
0f6ad04
Simplify version checks, fix unittests for commands changed
andriirr Jan 14, 2020
b8b8f32
Merge pull request #181 from andriirr/develop
andriirr Jan 17, 2020
58e08e8
Add release version 0.8.3
andriirr Jan 26, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: python

python:
- '2.7'
- '3.4'
- '3.8'

install: pip install -r dev-requirements.txt

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ VERSION := $(shell cat VERSION)
all: clean check pep8 flake8 tests

pep8:
-pep8 -r --ignore=E402,E731,E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 pyeapi/ test/
pycodestyle -r --ignore=E402,E731,E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 pyeapi/ test/

pyflakes:
pyflakes pyeapi/ test/
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.2
0.8.3
7 changes: 2 additions & 5 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
netaddr
-r requirements.txt
mock
coveralls
twine
check-manifest
pep8
pycodestyle
pyflakes
coverage
sphinx
sphinxcontrib-napoleon
flake8
flake8-print
flake8-debugger
pep8-naming


28 changes: 27 additions & 1 deletion docs/configfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ The following configuration options are available for defining node entries:
- http_local (available in EOS 4.14.5 or later)
- http
- https
- https_certs

:port: Configures the port to use for the eAPI connection. A default
port is used if this parameter is absent, based on the transport setting
using the following values:

- transport: http, default port: 80
- transport: https, deafult port: 443
- transport: https, default port: 443
- transport: https_certs, default port: 443
- transport: http_local, default port: 8080
- transport: socket, default port: n/a

Expand All @@ -62,6 +64,7 @@ Transport eapi.conf Required Script run from Authentication Required
=========== ================== =============== ========================
http Yes On/Off-switch Yes
https Yes On/Off-switch Yes
https_certs Yes On/Off-switch Yes (Auth done via certs, not un/pw)
http_local Yes On-switch only No
socket No On-switch only No
=========== ================== =============== ========================
Expand Down Expand Up @@ -169,6 +172,29 @@ As the table above indicates, a pyeapi configuration file is required in
username: admin
password: admin

Using HTTPS with Certificates
=============================

The https_certs transport options allows users to do authentication for pyeapi
with certificates instead of username/password. This requires functional
certificate chains are setup, copied to the proper location and trusted by
EOS beforehand. The ca_file parameter is optional. If provided the switches
certificate will also be validated against the provided CA cert. If no CA cert
is provided then no server side validation will be done.

.. code-block:: console

[connection:veos01]
transport: https_certs
cert_file: /path/to/certificate/file
key_file: /path/to/private/key/file
ca_file: /path/to/CA/certificate/file

[connection:veos02]
transport: https_certs
cert_file: /path/to/certificate/file
key_file: /path/to/private/key/file

*******************
The DEFAULT Section
*******************
Expand Down
1 change: 1 addition & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ include:

- HTTP
- HTTPS
- HTTPS Certificates
- HTTP Local
- Unix Socket

Expand Down
25 changes: 25 additions & 0 deletions docs/release-notes-0.8.3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Release 0.8.3
-------------

2020-01-26

New Modules
^^^^^^^^^^^


Enhancements
^^^^^^^^^^^^

* Support eapi command revision syntax (`181 <https://github.com/arista-eosplus/pyeapi/pull/181>`_)

* Add ability to use pyeapi with certificates

* Added check for 'match' statement to be valid before parsing regex ACL

Fixed
^^^^^

Known Caveats
^^^^^^^^^^^^^


2 changes: 1 addition & 1 deletion pyeapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
__version__ = '0.8.2'
__version__ = '0.8.3'
__author__ = 'Arista EOS+'


Expand Down
4 changes: 4 additions & 0 deletions pyeapi/api/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class BaseEntity(object):
def __init__(self, node):
self.node = node

@property
def version_number(self):
return self.node.version_number

@property
def config(self):
return self.node.running_config
Expand Down
23 changes: 12 additions & 11 deletions pyeapi/api/acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,17 +243,18 @@ def _parse_entries(self, config):
entries = dict()
for item in re.finditer(r'\d+ [p|d].*$', config, re.M):
match = self.entry_re.match(item.group(0))
entry = dict()
entry['action'] = match.group(2)
entry['protocol'] = match.group(3)
entry['srcaddr'] = match.group(5) or 'any'
entry['srclen'] = match.group(6)
entry['srcport'] = match.group(7)
entry['dstaddr'] = match.group(9) or 'any'
entry['dstlen'] = match.group(10)
entry['dstport'] = match.group(12)
entry['other'] = match.group(13)
entries[match.group(1)] = entry
if match:
entry = dict()
entry['action'] = match.group(2)
entry['protocol'] = match.group(3)
entry['srcaddr'] = match.group(5) or 'any'
entry['srclen'] = match.group(6)
entry['srcport'] = match.group(7)
entry['dstaddr'] = match.group(9) or 'any'
entry['dstlen'] = match.group(10)
entry['dstport'] = match.group(12)
entry['other'] = match.group(13)
entries[match.group(1)] = entry
return dict(entries=entries)

def create(self, name):
Expand Down
22 changes: 17 additions & 5 deletions pyeapi/api/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,10 @@ def getall(self):
return collection

def _parse_peer_group(self, config, name):
regexp = r'neighbor {} peer-group ([^\s]+)'.format(name)
if self.version_number >= '4.23':
regexp = r'neighbor {} peer group ([^\s]+)'.format(name)
else:
regexp = r'neighbor {} peer-group ([^\s]+)'.format(name)
match = re.search(regexp, config)
value = match.group(1) if match else None
return dict(peer_group=value)
Expand Down Expand Up @@ -234,7 +237,7 @@ def _parse_description(self, config, name):
return dict(description=value)

def _parse_next_hop_self(self, config, name):
exp = 'no neighobr {} next-hop-self'.format(name)
exp = 'no neighbor {} next-hop-self'.format(name)
value = exp in config
return dict(next_hop_self=not value)

Expand Down Expand Up @@ -263,7 +266,12 @@ def create(self, name):
def delete(self, name):
response = self.configure('no neighbor {}'.format(name))
if not response:
response = self.configure('no neighbor {} peer-group'.format(name))
if self.version_number >= '4.23':
response = self.configure('no neighbor {} '
'peer group'.format(name))
else:
response = self.configure('no neighbor {} '
'peer-group'.format(name))
return response

def configure(self, cmd):
Expand All @@ -280,8 +288,12 @@ def command_builder(self, name, cmd, value, default, disable):

def set_peer_group(self, name, value=None, default=False, disable=False):
if not self.ispeergroup(name):
cmd = self.command_builder(name, 'peer-group', value, default,
disable)
if self.version_number >= '4.23':
cmd = self.command_builder(name, 'peer group', value, default,
disable)
else:
cmd = self.command_builder(name, 'peer-group', value, default,
disable)
return self.configure(cmd)
return False

Expand Down
11 changes: 8 additions & 3 deletions pyeapi/api/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,16 @@ def set_vrf(self, name, vrf, default=False, disable=False):
True if the operation succeeds otherwise False is returned
"""
commands = ['interface %s' % name]
commands.append(self.command_builder('vrf forwarding', vrf,
default=default, disable=disable))
if self.version_number >= '4.23':
commands.append(self.command_builder('vrf', vrf,
default=default,
disable=disable))
else:
commands.append(self.command_builder('vrf forwarding', vrf,
default=default,
disable=disable))
return self.configure(commands)


class PortchannelInterface(BaseInterface):

def __str__(self):
Expand Down
2 changes: 1 addition & 1 deletion pyeapi/api/mlag.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def _parse_peer_address(self, config):
dict: A dict object that is intended to be merged into the
resource dict
"""
match = re.search(r'peer-address ([^\s]+)', config)
match = re.search(r'peer-address (\d+\.\d+\.\d+\.\d+)$', config)
value = match.group(1) if match else None
return dict(peer_address=value)

Expand Down
20 changes: 16 additions & 4 deletions pyeapi/api/ntp.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ def get(self):
return response

def _parse_source_interface(self, config):
match = re.search(r'^ntp source ([^\s]+)', config, re.M)
if self.version_number >= '4.23':
match = re.search(r'^ntp local-interface ([^\s]+)', config, re.M)
else:
match = re.search(r'^ntp source ([^\s]+)', config, re.M)
value = match.group(1) if match else None
return dict(source_interface=value)

Expand Down Expand Up @@ -118,7 +121,10 @@ def delete(self):
Returns:
True if the operation succeeds, otherwise False.
"""
cmd = self.command_builder('ntp source', disable=True)
if self.version_number >= '4.23':
cmd = self.command_builder('ntp local-interface', disable=True)
else:
cmd = self.command_builder('ntp source', disable=True)
return self.configure(cmd)

def default(self):
Expand All @@ -127,7 +133,10 @@ def default(self):
Returns:
True if the operation succeeds, otherwise False.
"""
cmd = self.command_builder('ntp source', default=True)
if self.version_number >= '4.23':
cmd = self.command_builder('ntp local-interface', default=True)
else:
cmd = self.command_builder('ntp source', default=True)
return self.configure(cmd)

def set_source_interface(self, name):
Expand All @@ -139,7 +148,10 @@ def set_source_interface(self, name):
Returns:
True if the operation succeeds, otherwise False.
"""
cmd = self.command_builder('ntp source', value=name)
if self.version_number >= '4.23':
cmd = self.command_builder('ntp local-interface', value=name)
else:
cmd = self.command_builder('ntp source', value=name)
return self.configure(cmd)

def add_server(self, name, prefer=False):
Expand Down
4 changes: 2 additions & 2 deletions pyeapi/api/routemaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def set_match_statements(self, name, action, seqno, statements):
"""
try:
current_statements = self.get(name)[action][seqno]['match']
except:
except Exception:
current_statements = []

commands = list()
Expand Down Expand Up @@ -275,7 +275,7 @@ def set_set_statements(self, name, action, seqno, statements):
"""
try:
current_statements = self.get(name)[action][seqno]['set']
except:
except Exception:
current_statements = []

commands = list()
Expand Down
6 changes: 3 additions & 3 deletions pyeapi/api/staticroute.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ def getall(self):
# Get the four identifying components
ip_dest = match[0]
next_hop = match[1]
next_hop_ip = None if match[2] is '' else match[2]
next_hop_ip = None if match[2] == '' else match[2]
distance = int(match[3])

# Create the data dict with the remaining components
data = {}
data['tag'] = None if match[4] is '' else int(match[4])
data['route_name'] = None if match[5] is '' else match[5]
data['tag'] = None if match[4] == '' else int(match[4])
data['route_name'] = None if match[5] == '' else match[5]

# Build the complete dict entry from the four components
# and the data.
Expand Down
2 changes: 1 addition & 1 deletion pyeapi/api/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def _parse_banners(self):
into the resource dict
"""
motd_value = login_value = None
matches = re.findall('^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n',
matches = re.findall(r'^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n',
self.config, re.DOTALL | re.M)
for match in matches:
if match[0].strip() == "motd":
Expand Down
Loading