From 10b27145b0fdeee767d26613fd1768b9768ab099 Mon Sep 17 00:00:00 2001 From: chieto-arista <133874211+chieto-arista@users.noreply.github.com> Date: Wed, 16 Aug 2023 19:06:59 +0100 Subject: [PATCH 01/24] Update VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 21e8796..9598a4c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.3 +1.0.3-rc0 From 6ada0c58995a43ce398cc1e38103865e90cf962b Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 13 Sep 2023 11:22:11 -0400 Subject: [PATCH 02/24] some physical duts supports only up to 8 min-link values, adopting the change --- test/system/test_api_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/system/test_api_interfaces.py b/test/system/test_api_interfaces.py index 96139bf..18738ab 100644 --- a/test/system/test_api_interfaces.py +++ b/test/system/test_api_interfaces.py @@ -390,7 +390,7 @@ def test_get_lacp_mode_with_default(self): def test_minimum_links_valid(self): for dut in self.duts: - minlinks = random_int(1, 16) + minlinks = random_int(1, 8) # some physical duts may have only 8 links dut.config(['no interface Port-Channel1', 'interface Port-Channel1']) result = dut.api('interfaces').set_minimum_links('Port-Channel1', From 954f48a2e0840317737d1478f6d9ee2884288762 Mon Sep 17 00:00:00 2001 From: nitzan-tz Date: Wed, 18 Oct 2023 18:34:50 +0300 Subject: [PATCH 03/24] add apiVersion parameter Add option to specify the API version as EOS doesn't return all VRFs for the command "show ip route vrf all summary" in version 1 of the API. See Arista case 501384. Example connection.execute('show ip route vrf all summary',apiVersion='latest') --- pyeapi/eapilib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index 3670281..e9ead43 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -346,6 +346,8 @@ def request(self, commands, encoding=None, reqid=None, **kwargs): reqid = id(self) if reqid is None else reqid params = {'version': 1, 'cmds': commands, 'format': encoding} streaming = False + if 'apiVersion' in kwargs: + params['version'] = kwargs['apiVersion'] if 'autoComplete' in kwargs: params['autoComplete'] = kwargs['autoComplete'] if 'expandAliases' in kwargs: From 7070b2d81fab48f0a15900ff0953c1cc9700b67b Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Mon, 4 Dec 2023 23:35:57 +0100 Subject: [PATCH 04/24] fix for issue #286 --- pyeapi/client.py | 93 +++++++++++++++++++++++++------ test/fixtures/running_config.text | 7 +++ 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index 16bf300..c7340fd 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -718,29 +718,88 @@ def _chunkify( self, config, indent=0 ): last parsed (sub)section, which in turn may contain sub-sections """ def is_subsection_present( section, indent ): - return any( [line[ indent ] == ' ' for line in section] ) + return any( line[ indent ] == ' ' for line in section ) + def get_indent( line ): + return len( line ) - len( line.lstrip() ) sections = {} key = None + banner = None for line in config.splitlines( keepends=True )[ indent > 0: ]: - # indent > 0: no need processing subsection line, which is 1st line - if line[ indent ] == ' ': # section continuation - sections[key] += line + line_rs = line.rstrip() + if indent == 0: + if banner: + sections[ banner ] += line + if line == 'EOF\n': + banner = None + continue + if line.startswith( 'banner ' ): + banner = line_rs + sections[ banner ] = line + continue + if get_indent( line_rs ) > indent: # i.e. subsection line + # key is always expected to be set by now + sections[ key ] += line continue - # new section is found (if key is not None) - if key: # process prior (last recorded) section - lines = sections[key].splitlines()[ 1: ] - if len( lines ): # section may contain sub-sections - ind = len( lines[0] ) - len( lines[0].lstrip() ) - if is_subsection_present( lines, ind ): - subs = self._chunkify( sections[key], indent=ind ) - subs.update( sections ) - sections = subs - elif indent > 0: # record only subsections - del sections[key] - key = line.rstrip() - sections[key] = line + subsection = sections.get( key, '' ).splitlines()[ 1: ] + if subsection: + sub_indent = get_indent( subsection[0] ) + if is_subsection_present( subsection, sub_indent ): + parsed = self._chunkify( sections[key], indent=sub_indent ) + parsed.update( sections ) + sections = parsed + key = line_rs + sections[ key ] = line return sections + +# @lru_cache(maxsize=None) +# def _chunkify( self, config, indent=0 ): +# """parse device config and return a dict holding sections and +# sub-sections: +# - a section always begins with a line with zero indents, +# - a sub-section always begins with an indented line +# a (sub)section typically contains a begin line (with a lower indent) +# and a body (with a higher indent). A section might be degenerative (no +# body, just the section line itself), while sub-sections always contain +# a sub-section line plus some body). E.g., here's a snippet of a section +# dict: +# { ... +# 'spanning-tree mode none': 'spanning-tree mode none\n', +# ... +# 'mac security': 'mac security\n profile PR\n cipher aes256-gcm', +# ' profile PR': ' profile PR\n cipher aes256-gcm' +# ... } +# +# it's imperative that the most outer call is made with indent=0, as the +# indent parameter defines processing of nested sub-sections, i.e., if +# indent > 0, then it's a recursive call and `config` argument contains +# last parsed (sub)section, which in turn may contain sub-sections +# """ +# def is_subsection_present( section, indent ): +# return any( [line[ indent ] == ' ' for line in section] ) +# sections = {} +# key = None +# for line in config.splitlines( keepends=True )[ indent > 0: ]: +# # indent > 0: no need processing subsection line, which is 1st line +# if line[ indent ] == ' ': # section continuation +# sections[key] += line +# continue +# # new section is found (if key is not None) +# if key: # process prior (last recorded) section +# lines = sections[key].splitlines()[ 1: ] +# if len( lines ): # section may contain sub-sections +# ind = len( lines[0] ) - len( lines[0].lstrip() ) +# if is_subsection_present( lines, ind ): +# subs = self._chunkify( sections[key], indent=ind ) +# subs.update( sections ) +# sections = subs +# elif indent > 0: # record only subsections +# del sections[key] +# key = line.rstrip() +# sections[key] = line +# return sections + + def section(self, regex, config='running_config'): """Returns a section of the config diff --git a/test/fixtures/running_config.text b/test/fixtures/running_config.text index 73c07a3..d279bb5 100644 --- a/test/fixtures/running_config.text +++ b/test/fixtures/running_config.text @@ -376,6 +376,13 @@ environment fan-speed auto ! clock timezone US/Eastern ! +banner login ++++++++++++++++++++++++++++++++++++++++++ + banner: + +EOF +! + no virtual-cable ! vlan 1 From fd0c1855ebf1aa609b88f548367e65d43325fd27 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Mon, 4 Dec 2023 23:44:27 +0100 Subject: [PATCH 05/24] removed old commented code and made some text adjustments to make pep8 happy --- pyeapi/client.py | 51 ++--------------------------------------------- pyeapi/eapilib.py | 2 +- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index c7340fd..27d7a31 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -719,8 +719,10 @@ def _chunkify( self, config, indent=0 ): """ def is_subsection_present( section, indent ): return any( line[ indent ] == ' ' for line in section ) + def get_indent( line ): return len( line ) - len( line.lstrip() ) + sections = {} key = None banner = None @@ -751,55 +753,6 @@ def get_indent( line ): sections[ key ] = line return sections - -# @lru_cache(maxsize=None) -# def _chunkify( self, config, indent=0 ): -# """parse device config and return a dict holding sections and -# sub-sections: -# - a section always begins with a line with zero indents, -# - a sub-section always begins with an indented line -# a (sub)section typically contains a begin line (with a lower indent) -# and a body (with a higher indent). A section might be degenerative (no -# body, just the section line itself), while sub-sections always contain -# a sub-section line plus some body). E.g., here's a snippet of a section -# dict: -# { ... -# 'spanning-tree mode none': 'spanning-tree mode none\n', -# ... -# 'mac security': 'mac security\n profile PR\n cipher aes256-gcm', -# ' profile PR': ' profile PR\n cipher aes256-gcm' -# ... } -# -# it's imperative that the most outer call is made with indent=0, as the -# indent parameter defines processing of nested sub-sections, i.e., if -# indent > 0, then it's a recursive call and `config` argument contains -# last parsed (sub)section, which in turn may contain sub-sections -# """ -# def is_subsection_present( section, indent ): -# return any( [line[ indent ] == ' ' for line in section] ) -# sections = {} -# key = None -# for line in config.splitlines( keepends=True )[ indent > 0: ]: -# # indent > 0: no need processing subsection line, which is 1st line -# if line[ indent ] == ' ': # section continuation -# sections[key] += line -# continue -# # new section is found (if key is not None) -# if key: # process prior (last recorded) section -# lines = sections[key].splitlines()[ 1: ] -# if len( lines ): # section may contain sub-sections -# ind = len( lines[0] ) - len( lines[0].lstrip() ) -# if is_subsection_present( lines, ind ): -# subs = self._chunkify( sections[key], indent=ind ) -# subs.update( sections ) -# sections = subs -# elif indent > 0: # record only subsections -# del sections[key] -# key = line.rstrip() -# sections[key] = line -# return sections - - def section(self, regex, config='running_config'): """Returns a section of the config diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index e9ead43..f3e01a2 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -347,7 +347,7 @@ def request(self, commands, encoding=None, reqid=None, **kwargs): params = {'version': 1, 'cmds': commands, 'format': encoding} streaming = False if 'apiVersion' in kwargs: - params['version'] = kwargs['apiVersion'] + params['version'] = kwargs['apiVersion'] if 'autoComplete' in kwargs: params['autoComplete'] = kwargs['autoComplete'] if 'expandAliases' in kwargs: From 025a40fab2d286da7ff9fbd6265dc0454cc4af01 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Tue, 5 Dec 2023 23:28:04 +0100 Subject: [PATCH 06/24] reverting to legacy interface exposure - to prevent failures with newer EOS --- test/lib/systestlib.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/lib/systestlib.py b/test/lib/systestlib.py index 3c0834f..3721455 100644 --- a/test/lib/systestlib.py +++ b/test/lib/systestlib.py @@ -33,6 +33,7 @@ import random from testlib import get_fixture +from pyeapi.utils import CliVariants import pyeapi.client @@ -48,9 +49,16 @@ def setUp(self): self.duts = list() for name in config.sections(): - if name.startswith('connection:') and 'localhost' not in name: - name = name.split(':')[1] - self.duts.append(pyeapi.client.connect_to(name)) + if not name.startswith('connection:'): + continue + if 'localhost' in name: + continue + name = name.split(':')[1] + self.duts.append( pyeapi.client.connect_to(name) ) + # revert to a legacy behavior for interface availability + if self.duts[ -1 ]: + self.duts[ -1 ].config( CliVariants( + 'service interface inactive expose', 'enable') ) def sort_dict_by_keys(self, d): keys = sorted(d.keys()) From 2386f88975cac5faefb8bf8546bc5ae1363cbc85 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 6 Dec 2023 00:11:02 +0100 Subject: [PATCH 07/24] added a false positive case to UT fixture for banner section --- pyeapi/client.py | 2 +- test/fixtures/running_config.text | 33 +++++++++++++++---------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index 27d7a31..582acfe 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -731,7 +731,7 @@ def get_indent( line ): if indent == 0: if banner: sections[ banner ] += line - if line == 'EOF\n': + if line_rs == 'EOF': banner = None continue if line.startswith( 'banner ' ): diff --git a/test/fixtures/running_config.text b/test/fixtures/running_config.text index d279bb5..247d472 100644 --- a/test/fixtures/running_config.text +++ b/test/fixtures/running_config.text @@ -376,13 +376,6 @@ environment fan-speed auto ! clock timezone US/Eastern ! -banner login -+++++++++++++++++++++++++++++++++++++++++ - banner: - -EOF -! - no virtual-cable ! vlan 1 @@ -411,6 +404,22 @@ vlan 300 state active no private-vlan ! +banner login ++++++++++++++++++++++++++++++++++++++++++ + banner: + +vlan 1 +this +is the loging ban +that would b emult +EOF +! + +banner motd +this text +can be multine +EOF +! interface Port-Channel10 no description no shutdown @@ -2113,16 +2122,6 @@ no ip tacacs source-interface ! no vxlan vni notation dotted ! -banner login -this -is the loging ban -that would b emult -EOF -banner motd -this text -can be multine -EOF -! system coredump compressed ! no dot1x system-auth-control From 92ea00d418ccc2e9ae827057e28cbac7cd76c4d5 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 6 Dec 2023 00:47:19 +0100 Subject: [PATCH 08/24] a very minor optimization for the updated code --- pyeapi/client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index 582acfe..ac334c8 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -742,8 +742,7 @@ def get_indent( line ): # key is always expected to be set by now sections[ key ] += line continue - subsection = sections.get( key, '' ).splitlines()[ 1: ] - if subsection: + if subsection := sections.get( key, '' ).splitlines()[ 1: ]: sub_indent = get_indent( subsection[0] ) if is_subsection_present( subsection, sub_indent ): parsed = self._chunkify( sections[key], indent=sub_indent ) From afa6ded859741a820eaeccdfa5e1444f990f0ca2 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 6 Dec 2023 13:14:36 +0100 Subject: [PATCH 09/24] reverting last change, due to incompatibility with py3.7 --- pyeapi/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index ac334c8..582acfe 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -742,7 +742,8 @@ def get_indent( line ): # key is always expected to be set by now sections[ key ] += line continue - if subsection := sections.get( key, '' ).splitlines()[ 1: ]: + subsection = sections.get( key, '' ).splitlines()[ 1: ] + if subsection: sub_indent = get_indent( subsection[0] ) if is_subsection_present( subsection, sub_indent ): parsed = self._chunkify( sections[key], indent=sub_indent ) From 59c1cdab1e191163f0179b46ba071919e92bed65 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Wed, 28 Feb 2024 12:43:09 +0100 Subject: [PATCH 10/24] cleanup old "mock" leftovers --- dev-requirements.txt | 1 - setup.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 55ef3ec..a929ba7 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,4 @@ -r requirements.txt -mock coveralls twine check-manifest diff --git a/setup.py b/setup.py index 6f5b9d4..56897e3 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,7 @@ # $ pip install -e .[dev,test] extras_require={ 'dev': ['check-manifest', 'pep8', 'pyflakes', 'twine'], - 'test': ['coverage', 'mock'], + 'test': ['coverage'], }, ) From 1f2d8e1fa61566082ccb11a1a17e0f3d8a0c89df Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 3 Apr 2024 20:55:31 +0200 Subject: [PATCH 11/24] Migrate to importlib --- test/unit/test_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/test_client.py b/test/unit/test_client.py index 3472951..0136add 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -32,7 +32,7 @@ import sys import os import unittest -import imp +import importlib sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) @@ -227,7 +227,7 @@ class TestClient(unittest.TestCase): def setUp(self): if 'EAPI_CONF' in os.environ: del os.environ['EAPI_CONF'] - imp.reload(pyeapi.client) + importlib.reload(pyeapi.client) def test_load_config_for_connection_with_filename(self): conf = get_fixture('eapi.conf') From c508b63294c109f4626b99ffc2c549cefc26ae76 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Fri, 2 Aug 2024 15:48:50 +0200 Subject: [PATCH 12/24] forced modules generation for html format --- docs/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index e7c16e6..dc58d3b 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -55,12 +55,13 @@ clean: rm -rf $(APIDIR)/* html: + make modules $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." modules: - python $(CWD)/generate_modules.py + python3 $(CWD)/generate_modules.py docs: clean modules html From 7429cb11c85eeda4a503767d1a6552342ea73385 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Fri, 2 Aug 2024 16:38:09 +0200 Subject: [PATCH 13/24] forced modules generation for html format --- .readthedocs.yaml | 6 +++++- docs/Makefile | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index e8f8c59..560b2ab 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -13,6 +13,10 @@ build: # nodejs: "20" # rust: "1.70" # golang: "1.20" + jobs: + pre_install: + - make modules + # Build documentation in the "docs/" directory with Sphinx sphinx: @@ -33,4 +37,4 @@ python: install: - requirements: dev-requirements.txt - method: pip - path: . \ No newline at end of file + path: . diff --git a/docs/Makefile b/docs/Makefile index dc58d3b..2fff752 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -55,7 +55,6 @@ clean: rm -rf $(APIDIR)/* html: - make modules $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." From 7dc454687e89f28fd2fbc967df5ed7890ac7b1c0 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Fri, 2 Aug 2024 18:16:08 +0200 Subject: [PATCH 14/24] forced modules generation for html format --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 560b2ab..567790d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -14,7 +14,7 @@ build: # rust: "1.70" # golang: "1.20" jobs: - pre_install: + pre_build: - make modules From 54b3cf2c15a7afeecfa0304654805da951ac613f Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Fri, 2 Aug 2024 18:35:11 +0200 Subject: [PATCH 15/24] forced modules generation for html format --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 567790d..9a69d5a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -15,7 +15,7 @@ build: # golang: "1.20" jobs: pre_build: - - make modules + - make -C docs modules # Build documentation in the "docs/" directory with Sphinx From b6163170567f9d5e2f732195d7f437485446bac4 Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Sat, 3 Aug 2024 02:05:04 +0200 Subject: [PATCH 16/24] Update ci.yml adding pull_request_target to let run CI on the externally forked PRs --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa73838..4bebc38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ --- name: CI -on: [ pull_request, workflow_dispatch ] +on: [ pull_request, workflow_dispatch, pull_request_target ] jobs: build: runs-on: ubuntu-latest From b4c55233c39a2f0b1a1711ccf7a448e55c268919 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 14 Aug 2024 15:28:35 +0200 Subject: [PATCH 17/24] fixing system test issue where non-existent interface could be selected --- test/lib/systestlib.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/lib/systestlib.py b/test/lib/systestlib.py index 3721455..1c1d8e4 100644 --- a/test/lib/systestlib.py +++ b/test/lib/systestlib.py @@ -66,9 +66,15 @@ def sort_dict_by_keys(self, d): def random_interface(dut, exclude=None): + # interfaces read in 'show run all' and those actually present may differ, + # thus interface list must be picked from the actually present + if not getattr( random_interface, 'present', False ): + random_interface.present = dut.run_commands( + 'show interfaces', send_enable=False )[ 0 ][ 'interfaces' ].keys() exclude = [] if exclude is None else exclude interfaces = dut.api('interfaces') - names = [name for name in list(interfaces.keys()) if name.startswith('Et')] + names = [ name for name in list(interfaces.keys()) if name.startswith('Et') ] + names = [ name for name in names if name in random_interface.present ] exclude_interfaces = dut.settings.get('exclude_interfaces', []) if exclude_interfaces: From 4c9381aa91cff42c17fc871607d9946fba460c84 Mon Sep 17 00:00:00 2001 From: Dmitry Lyssenko Date: Wed, 14 Aug 2024 20:51:20 +0200 Subject: [PATCH 18/24] fixing system test issue where mlag test fails on Ethernet1 --- test/system/test_api_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/system/test_api_interfaces.py b/test/system/test_api_interfaces.py index 18738ab..453fef4 100644 --- a/test/system/test_api_interfaces.py +++ b/test/system/test_api_interfaces.py @@ -44,7 +44,7 @@ class TestResourceInterfaces(DutSystemTest): def test_get(self): for dut in self.duts: - intf = random_interface(dut) + intf = random_interface( dut, exclude=['Ethernet1'] ) dut.config(['default interface %s' % intf, 'interface %s' % intf, 'description this is a test', From 7f16691f877682f8b66048f699a58ba7ff7c4c29 Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Sat, 17 Aug 2024 01:58:28 +0200 Subject: [PATCH 19/24] updated number for invalid link Number of supported link in port-channels, keep growing. Hope newly defined invalid number will hold for a while --- test/system/test_api_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/system/test_api_interfaces.py b/test/system/test_api_interfaces.py index 453fef4..1d5a1c2 100644 --- a/test/system/test_api_interfaces.py +++ b/test/system/test_api_interfaces.py @@ -403,7 +403,7 @@ def test_minimum_links_valid(self): def test_minimum_links_invalid_value(self): for dut in self.duts: - minlinks = random_int(129, 256) # some duts may support up to 128 + minlinks = 1025 # hope it will hold for a while result = dut.api( 'interfaces').set_minimum_links('Port-Channel1', minlinks) self.assertFalse(result) From 6dfe6bea90e5bfffaa92241b6a5b069ea241221d Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:49:53 +0200 Subject: [PATCH 20/24] Create release-notes-1.0.r.rst release notes for the new release --- docs/release-notes-1.0.r.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/release-notes-1.0.r.rst diff --git a/docs/release-notes-1.0.r.rst b/docs/release-notes-1.0.r.rst new file mode 100644 index 0000000..48c7e8b --- /dev/null +++ b/docs/release-notes-1.0.r.rst @@ -0,0 +1,22 @@ +Release 1.0.4 +------------- + +2024-08-19 + \- the major reason for this release is to fix documentation issue on `readthedocs `_ site + +New Modules +^^^^^^^^^^^ + +Enhancements +^^^^^^^^^^^^ + +Fixed +^^^^^ +* System test fixes ( `#285 `_, `#291 `_, + `#302 `_, `#303 `_ ) +* Fixed PR `#289 `_: allow specifying API version in requests. +* Fixed PR `#286 `_: a regression introduced by PR #220, where parsing a non-empty banner section may fail +* Fixed *modules* section on `readthedocs `_ site (PR `#300 `_) + +Known Caveats +^^^^^^^^^^^^^ From b7ffe06f19ad8d55bd9e0c20bce17f54e8e9b40b Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Mon, 19 Aug 2024 21:49:34 +0200 Subject: [PATCH 21/24] Update VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9598a4c..ee90284 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.3-rc0 +1.0.4 From dff476ce03e1bf89ff124fc78fa583757b0302bf Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Mon, 19 Aug 2024 21:50:17 +0200 Subject: [PATCH 22/24] Update __init__.py --- pyeapi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyeapi/__init__.py b/pyeapi/__init__.py index f1bb9c3..8b3a217 100644 --- a/pyeapi/__init__.py +++ b/pyeapi/__init__.py @@ -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__ = '1.0.3' +__version__ = '1.0.4' __author__ = 'Arista EOS+' From 2a93891f06c3b14e4393631f27aa624f1d97be82 Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:01:32 +0200 Subject: [PATCH 23/24] Create release-notes-1.0.4.rst Release notes for 1.0.4 --- docs/release-notes-1.0.4.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/release-notes-1.0.4.rst diff --git a/docs/release-notes-1.0.4.rst b/docs/release-notes-1.0.4.rst new file mode 100644 index 0000000..48c7e8b --- /dev/null +++ b/docs/release-notes-1.0.4.rst @@ -0,0 +1,22 @@ +Release 1.0.4 +------------- + +2024-08-19 + \- the major reason for this release is to fix documentation issue on `readthedocs `_ site + +New Modules +^^^^^^^^^^^ + +Enhancements +^^^^^^^^^^^^ + +Fixed +^^^^^ +* System test fixes ( `#285 `_, `#291 `_, + `#302 `_, `#303 `_ ) +* Fixed PR `#289 `_: allow specifying API version in requests. +* Fixed PR `#286 `_: a regression introduced by PR #220, where parsing a non-empty banner section may fail +* Fixed *modules* section on `readthedocs `_ site (PR `#300 `_) + +Known Caveats +^^^^^^^^^^^^^ From 4e75a7c9840e7df592c6f3ef4b1e1210a8540aa0 Mon Sep 17 00:00:00 2001 From: dlyssenko <88390151+dlyssenko@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:01:56 +0200 Subject: [PATCH 24/24] Delete docs/release-notes-1.0.r.rst --- docs/release-notes-1.0.r.rst | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 docs/release-notes-1.0.r.rst diff --git a/docs/release-notes-1.0.r.rst b/docs/release-notes-1.0.r.rst deleted file mode 100644 index 48c7e8b..0000000 --- a/docs/release-notes-1.0.r.rst +++ /dev/null @@ -1,22 +0,0 @@ -Release 1.0.4 -------------- - -2024-08-19 - \- the major reason for this release is to fix documentation issue on `readthedocs `_ site - -New Modules -^^^^^^^^^^^ - -Enhancements -^^^^^^^^^^^^ - -Fixed -^^^^^ -* System test fixes ( `#285 `_, `#291 `_, - `#302 `_, `#303 `_ ) -* Fixed PR `#289 `_: allow specifying API version in requests. -* Fixed PR `#286 `_: a regression introduced by PR #220, where parsing a non-empty banner section may fail -* Fixed *modules* section on `readthedocs `_ site (PR `#300 `_) - -Known Caveats -^^^^^^^^^^^^^