Skip to content

Commit

Permalink
Merge pull request #251 from dlyssenko/fix_ench_161_add_parsing_secon…
Browse files Browse the repository at this point in the history
…dary_ip

fix issue #161 - add parsing of secondary ip from interfaces
  • Loading branch information
dlyssenko authored Feb 19, 2023
2 parents b332307 + d34349a commit 7a2d236
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 29 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ pyflakes:
pyflakes pyeapi/ test/

flake8:
flake8 --ignore=E201,E202,E302,E303,E402,E731,W391 --exit-zero pyeapi/
flake8 --ignore=E201,E202,E302,E303,E402,E731,W391,N802 --max-line-length=100 test/
flake8 --ignore=E128,E201,E202,E302,E303,E402,E731,W391 --exit-zero pyeapi/
flake8 --ignore=E128,E201,E202,E302,E303,E402,E731,W391,N802 --max-line-length=100 test/

check:
check-manifest
Expand Down
35 changes: 19 additions & 16 deletions pyeapi/api/ipinterfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,18 @@
SWITCHPORT_RE = re.compile(r'no switchport$', re.M)


class Ipinterfaces(EntityCollection):
class Ipinterfaces( EntityCollection ):

def get(self, name):
def get( self, name ):
"""Returns the specific IP interface properties
The Ipinterface resource returns the following:
* name (str): The name of the interface
* address (str): The IP address of the interface in the form
of A.B.C.D/E
of A.B.C.D/E (None if no ip configured)
* secondary (list): The list of secondary IP addresses of the
interface (if any configured)
* mtu (int): The configured value for IP MTU.
Expand All @@ -75,22 +77,21 @@ def get(self, name):
the current configuration of the node. If the specified
interface does not exist then None is returned.
"""
config = self.get_block('interface %s' % name)

if name[0:2] in ['Et', 'Po'] and not SWITCHPORT_RE.search(config,
re.M):
config = self.get_block( 'interface %s' % name )
if name[ 0:2 ] in [
'Et', 'Po' ] and not SWITCHPORT_RE.search( config, re.M ):
return None

resource = dict(name=name)
resource.update(self._parse_address(config))
resource.update(self._parse_mtu(config))
resource = dict( name=name )
resource.update( self._parse_address(config) )
resource.update( self._parse_mtu(config) )
return resource

def _parse_address(self, config):
def _parse_address( self, config ):
"""Parses the config block and returns the ip address value
The provided configuration block is scaned and the configured value
for the IP address is returned as a dict object. If the IP address
The provided configuration block is scanned and the configured value
for the IP address is returned as a dict object. If the IP address
value is not configured, then None is returned for the value
Args:
Expand All @@ -99,9 +100,11 @@ def _parse_address(self, config):
Return:
dict: A dict object intended to be merged into the resource dict
"""
match = re.search(r'ip address ([^\s]+)', config)
value = match.group(1) if match else None
return dict(address=value)
match = re.findall( r'ip address ([^\s]+)', config, re.M )
primary, secondary = ( match[0],
match[1:] ) if match else ( None, None )
return dict( address=primary,
secondary=secondary ) if secondary else dict( address=primary )

def _parse_mtu(self, config):
"""Parses the config block and returns the configured IP MTU value
Expand Down
3 changes: 2 additions & 1 deletion pyeapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@

from pyeapi.eapilib import HttpEapiConnection, HttpsEapiConnection
from pyeapi.eapilib import HttpsEapiCertConnection
from pyeapi.eapilib import HttpEapiSessionConnection, HttpsEapiSessionConnection
from pyeapi.eapilib import HttpEapiSessionConnection
from pyeapi.eapilib import HttpsEapiSessionConnection
from pyeapi.eapilib import SocketEapiConnection, HttpLocalEapiConnection
from pyeapi.eapilib import CommandError

Expand Down
2 changes: 1 addition & 1 deletion pyeapi/eapilib.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ def authentication(self, username, password):
_LOGGER.exception(exc)
self.socket_error = exc
self.error = exc
error_msg = 'Socket error during eAPI authentication: %s' % str(exc)
error_msg = f'Socket error during eAPI authentication: {exc}'
raise ConnectionError(str(self), error_msg)
except ValueError as exc:
_LOGGER.exception(exc)
Expand Down
8 changes: 2 additions & 6 deletions pyeapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,6 @@ def make_iterable(value):
Returns:
An iterable object of type list
"""
if sys.version_info <= (3, 0):
# Convert unicode values to strings for Python 2
if isinstance(value, unicode):
value = str(value)
if isinstance(value, str) or isinstance(
value, dict) or isinstance(value, CliVariants):
value = [value]
Expand Down Expand Up @@ -259,5 +255,5 @@ class CliVariants:
"""
def __init__(self, *cli):
assert len( cli ) >= 2, 'must be initialized with 2 or more arguments'
self.variants = [ v if not isinstance(v, str) and isinstance(v, Iterable)
else [v] for v in cli ]
self.variants = [ v if not isinstance(v,
str) and isinstance(v, Iterable) else [v] for v in cli ]
6 changes: 6 additions & 0 deletions test/fixtures/running_config.text
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,12 @@ interface Loopback0
bfd interval 300 min_rx 300 multiplier 3
default ntp serve
!
interface Loopback2
description test fixture with secondary ip
ip address 2.2.2.2/32
ip address 3.255.255.1/24 secondary
ip address 4.255.255.1/24 secondary
!
interface Ethernet8
! the interface config is added separately covering test for issue #213
! it might be inconsistend with the rest of config, though all unit tests pass
Expand Down
11 changes: 8 additions & 3 deletions test/unit/test_api_ipinterfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,19 @@ def __init__(self, *args, **kwargs):
self.config = open(get_fixture('running_config.text')).read()

def test_get(self):
result = self.instance.get('Loopback0')
values = dict(name='Loopback0', address='1.1.1.1/32', mtu=1500)
result = self.instance.get( 'Loopback0' )
values = dict( name='Loopback0', address='1.1.1.1/32', mtu=1500 )
self.assertEqual( result, values )
# test interface with secondary ip
result = self.instance.get( 'Loopback2' )
values = dict( name='Loopback2', address='2.2.2.2/32',
secondary=['3.255.255.1/24', '4.255.255.1/24'], mtu=None )
self.assertEqual(result, values)

def test_getall(self):
result = self.instance.getall()
self.assertIsInstance(result, dict)
self.assertEqual(len(result), 3)
self.assertEqual(len(result), 4)

def test_instance_functions(self):
for intf in self.INTERFACES:
Expand Down

0 comments on commit 7a2d236

Please sign in to comment.