Skip to content

Commit

Permalink
Merge pull request #182 from arista-eosplus/release-0.8.3
Browse files Browse the repository at this point in the history
Release 0.8.3
  • Loading branch information
andriirr authored Jan 26, 2020
2 parents 5032e25 + 58e08e8 commit 5889560
Show file tree
Hide file tree
Showing 40 changed files with 892 additions and 317 deletions.
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

0 comments on commit 5889560

Please sign in to comment.