1
0
Fork 0

Compare commits

...

10 commits

Author SHA1 Message Date
53654251b9
Updating source url in copyright.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:19:40 +01:00
952ea9f521
Releasing debian version 1.4.0+dfsg-1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:19:29 +01:00
9652dd6fff
Updating to standards-version 4.7.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:19:25 +01:00
e41c607fb3
Updating copyright for 2024.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:19:04 +01:00
c306a1dcc2
Merging upstream version 1.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:18:51 +01:00
295cee048d
Releasing debian version 1.3.2+dfsg-1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:18:28 +01:00
aa182b4768
Merging upstream version 1.3.2+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:18:14 +01:00
77fa26eaf5
Releasing debian version 1.3.1+dfsg-5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:17:41 +01:00
9df2219874
Manually removing some files that pybuild doesn't clean up during build (Closes: #1044183).
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:17:38 +01:00
e61f06ddc1
Releasing debian version 1.3.1+dfsg-4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-05 14:17:25 +01:00
17 changed files with 648 additions and 501 deletions

View file

@ -49,7 +49,9 @@ coverage_report:
pep8: pep8:
-pep8 -r --max-line-length=120 --ignore=$(PEP8_IGNORE) cvprac/ -pep8 -r --max-line-length=120 --ignore=$(PEP8_IGNORE) cvprac/
-pep8 -r --max-line-length=120 --ignore=$(PEP8_IGNORE),E402 test/ -pep8 -r --max-line-length=120 --ignore=$(PEP8_IGNORE),E402 test/lib/
-pep8 -r --max-line-length=120 --ignore=$(PEP8_IGNORE),E402 test/system/
-pep8 -r --ignore=$(PEP8_IGNORE),E402,E501 test/unit/
pyflakes: pyflakes:
pyflakes cvprac/ test/ pyflakes cvprac/ test/

View file

@ -4,25 +4,31 @@
## Table of Contents ## Table of Contents
1. [Overview](#overview) - [Arista Cloudvision® Portal RESTful API Client](#arista-cloudvision-portal-restful-api-client)
- [Table of Contents](#table-of-contents)
- [Overview](#overview)
- [Requirements](#requirements) - [Requirements](#requirements)
1. [Installation](#installation) - [Installation](#installation)
- [Development: Run from Source](#development-run-from-source) - [Development: Run from Source](#development-run-from-source)
1. [Getting Started](#getting-started) - [Step 1: Clone the cvprac Github repo](#step-1-clone-the-cvprac-github-repo)
- [Step 2: Check out the desired version or branch](#step-2-check-out-the-desired-version-or-branch)
- [Step 3: Install cvprac using Pip with -e switch](#step-3-install-cvprac-using-pip-with--e-switch)
- [Step 4: Install cvprac development requirements](#step-4-install-cvprac-development-requirements)
- [Getting Started](#getting-started)
- [Connecting](#connecting) - [Connecting](#connecting)
- [CVP On Premises](#cvp-on-premises) - [CVP On Premises](#cvp-on-premises)
- [CVaaS](#cvaas) - [CVaaS](#cvaas)
- [CVP Version Handling](#cvp-version-handling) - [CVP Version Handling](#cvp-version-handling)
- [Examples](#examples) - [Examples](#examples)
1. [Notes For API Class Usage](#notes-for-api-class-usage) - [Notes for API Class Usage](#notes-for-api-class-usage)
- [Containers](#containers) - [Containers](#containers)
1. [Testing](#testing) - [Testing](#testing)
1. [Contact or Questions](#contact-or-questions) - [Contact or Questions](#contact-or-questions)
1. [Contributing](#contributing) - [Contributing](#contributing)
- [Working With Git](#working-with-git) - [Working With Git](#working-with-git)
- [Submitting Pull Requests](#submitting-pull-requests) - [Submitting Pull Requests](#submitting-pull-requests)
- [Pull Request Semantics](#pull-request-semantics) - [Pull Request Semantics](#pull-request-semantics)
1. [License](#license) - [License](#license)
## Overview ## Overview
@ -151,7 +157,7 @@ examples below demonstrate connecting to CVP On Premises setups.
### CVaaS ### CVaaS
CVaaS is CloudVision as a Service. Users with CVaaS must use a REST API CVaaS is CloudVision as a Service. Users with CVaaS must use a REST API
token for accessing CVP with REST APIs. token (service account tokens) for accessing CVP with REST APIs.
- In the case where users authenticate with CVP (CVaaS) using Oauth a - In the case where users authenticate with CVP (CVaaS) using Oauth a
- REST API token is required to be generated and used for running REST - REST API token is required to be generated and used for running REST
@ -170,6 +176,22 @@ generic in this sense. If you are using the cvaas\_token parameter
please convert to api\_token because the cvaas\_token parameter will be please convert to api\_token because the cvaas\_token parameter will be
deprecated in the future. deprecated in the future.
Please note that the correct regional URL where the CVaaS tenant is deployed must be used. The following are the
cluster URLs used in production:
| Region | URL |
|--------|-----|
| United States 1a | [www.arista.io](https://www.arista.io) |
| United States 1c| [www.cv-prod-us-central1-c.arista.io](https://www.cv-prod-us-central1-c.arista.io)|
| Canada | [www.cv-prod-na-northeast1-b.arista.io](https://www.cv-prod-na-northeast1-b.arista.io)|
| Europe West 2| [www.cv-prod-euwest-2.arista.io](https://www.cv-prod-euwest-2.arista.io)|
| Japan| [www.cv-prod-apnortheast-1.arista.io](https://www.cv-prod-apnortheast-1.arista.io)|
| Australia | [www.cv-prod-ausoutheast-1.arista.io](https://www.cv-prod-ausoutheast-1.arista.io)|
!!! Warning
URLs without `www` are not supported.
### CVP Version Handling ### CVP Version Handling
The CVP RESTful APIs often change between releases of CVP. Cvprac The CVP RESTful APIs often change between releases of CVP. Cvprac

View file

@ -1 +1 @@
1.3.1 1.4.0

View file

@ -32,5 +32,5 @@
''' RESTful API Client class for Cloudvision(R) Portal ''' RESTful API Client class for Cloudvision(R) Portal
''' '''
__version__ = '1.3.1' __version__ = '1.4.0'
__author__ = 'Arista Networks, Inc.' __author__ = 'Arista Networks, Inc.'

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,9 @@
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
# pylint: disable=too-many-branches,too-many-statements,too-many-locals,too-many-lines
''' RESTful API Client class for Cloudvision(R) Portal ''' RESTful API Client class for Cloudvision(R) Portal
This module provides a RESTful API client for Cloudvision(R) Portal (CVP) This module provides a RESTful API client for Cloudvision(R) Portal (CVP)
@ -96,25 +99,31 @@ import json
import logging import logging
from logging.handlers import SysLogHandler from logging.handlers import SysLogHandler
from itertools import cycle from itertools import cycle
from pkg_resources import parse_version from packaging.version import parse
import requests import requests
from requests.exceptions import ConnectionError, HTTPError, Timeout, \ from requests.exceptions import ( # pylint: disable=redefined-builtin
ReadTimeout, TooManyRedirects, JSONDecodeError ConnectionError,
HTTPError,
Timeout,
ReadTimeout,
TooManyRedirects,
JSONDecodeError
)
from cvprac.cvp_api import CvpApi from cvprac.cvp_api import CvpApi
from cvprac.cvp_client_errors import CvpApiError, CvpLoginError, \ from cvprac.cvp_client_errors import CvpApiError, CvpLoginError, \
CvpRequestError, CvpSessionLogOutError CvpRequestError, CvpSessionLogOutError
class CvpClient(object): class CvpClient():
''' Use this class to create a persistent connection to CVP. ''' Use this class to create a persistent connection to CVP.
''' '''
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
# Maximum number of times to retry a get or post to the same # Maximum number of times to retry a get or post to the same
# CVP node. # CVP node.
NUM_RETRY_REQUESTS = 3 NUM_RETRY_REQUESTS = 3
LATEST_API_VERSION = 8.0 LATEST_API_VERSION = 9.0
def __init__(self, logger='cvprac', syslog=False, filename=None, def __init__(self, logger='cvprac', syslog=False, filename=None,
log_level='INFO'): log_level='INFO'):
@ -212,7 +221,8 @@ class CvpClient(object):
self.version = version self.version = version
self.log.info('Version %s', version) self.log.info('Version %s', version)
# Set apiversion to latest available API version for CVaaS # Set apiversion to latest available API version for CVaaS
# Set apiversion to 8.0 for 2022.1.x # Set apiversion to 9.0 for 2023.1.x
# Set apiversion to 8.0 for 2022.1.x - 2022.3.x
# Set apiversion to 7.0 for 2021.3.x # Set apiversion to 7.0 for 2021.3.x
# Set apiversion to 6.0 for 2021.2.x # Set apiversion to 6.0 for 2021.2.x
# Set apiversion to 5.0 for 2020.2.4 through 2021.1.x # Set apiversion to 5.0 for 2020.2.4 through 2021.1.x
@ -232,25 +242,37 @@ class CvpClient(object):
' Appending 0. Updated Version String - %s', ' Appending 0. Updated Version String - %s',
".".join(version_components)) ".".join(version_components))
full_version = ".".join(version_components) full_version = ".".join(version_components)
if parse_version(full_version) >= parse_version('2022.1.0'): if parse(full_version) >= parse('2024.1.0'):
self.log.info('Setting API version to v12')
self.apiversion = 12.0
elif parse(full_version) >= parse('2023.3.0'):
self.log.info('Setting API version to v11')
self.apiversion = 11.0
elif parse(full_version) >= parse('2023.2.0'):
self.log.info('Setting API version to v10')
self.apiversion = 10.0
elif parse(full_version) >= parse('2023.1.0'):
self.log.info('Setting API version to v9')
self.apiversion = 9.0
elif parse(full_version) >= parse('2022.1.0'):
self.log.info('Setting API version to v8') self.log.info('Setting API version to v8')
self.apiversion = 8.0 self.apiversion = 8.0
elif parse_version(full_version) >= parse_version('2021.3.0'): elif parse(full_version) >= parse('2021.3.0'):
self.log.info('Setting API version to v7') self.log.info('Setting API version to v7')
self.apiversion = 7.0 self.apiversion = 7.0
elif parse_version(full_version) >= parse_version('2021.2.0'): elif parse(full_version) >= parse('2021.2.0'):
self.log.info('Setting API version to v6') self.log.info('Setting API version to v6')
self.apiversion = 6.0 self.apiversion = 6.0
elif parse_version(full_version) >= parse_version('2020.2.4'): elif parse(full_version) >= parse('2020.2.4'):
self.log.info('Setting API version to v5') self.log.info('Setting API version to v5')
self.apiversion = 5.0 self.apiversion = 5.0
elif parse_version(full_version) >= parse_version('2020.1.1'): elif parse(full_version) >= parse('2020.1.1'):
self.log.info('Setting API version to v4') self.log.info('Setting API version to v4')
self.apiversion = 4.0 self.apiversion = 4.0
elif parse_version(full_version) >= parse_version('2019.0.0'): elif parse(full_version) >= parse('2019.0.0'):
self.log.info('Setting API version to v3') self.log.info('Setting API version to v3')
self.apiversion = 3.0 self.apiversion = 3.0
elif parse_version(full_version) >= parse_version('2018.2.0'): elif parse(full_version) >= parse('2018.2.0'):
self.log.info('Setting API version to v2') self.log.info('Setting API version to v2')
self.apiversion = 2.0 self.apiversion = 2.0
else: else:
@ -374,13 +396,12 @@ class CvpClient(object):
self.error_msg = '\n' self.error_msg = '\n'
for _ in range(0, num_nodes): for _ in range(0, num_nodes):
host = next(self.node_pool) host = next(self.node_pool)
self.url_prefix = ('https://%s:%d/web' % (host, self.port or 443)) self.url_prefix = f"https://{host}:{self.port or 443}/web"
self.url_prefix_short = ('https://%s:%d' self.url_prefix_short = f"https://{host}:{self.port or 443}"
% (host, self.port or 443))
error = self._reset_session() error = self._reset_session()
if error is None: if error is None:
break break
self.error_msg += '%s: %s\n' % (host, error) self.error_msg += f"{host}: {error}\n"
def _reset_session(self): def _reset_session(self):
''' Get a new request session and try logging into the current ''' Get a new request session and try logging into the current
@ -424,23 +445,20 @@ class CvpClient(object):
if 'Unauthorized' in response.reason: if 'Unauthorized' in response.reason:
# Check for 'Unauthorized' User error because this is how # Check for 'Unauthorized' User error because this is how
# CVP responds to a logged out users requests in 2018.x. # CVP responds to a logged out users requests in 2018.x.
msg = '%s: Request Error: %s' % (prefix, response.reason) msg = f"{prefix}: Request Error: {response.reason}"
self.log.error(msg) self.log.error(msg)
raise CvpApiError(msg) raise CvpApiError(msg)
if 'User is unauthorized' in response.text: if 'User is unauthorized' in response.text:
# Check for 'User is unauthorized' response text because this # Check for 'User is unauthorized' response text because this
# is how CVP responds to a logged out users requests in 2019.x. # is how CVP responds to a logged out users requests in 2019.x.
msg = '%s: Request Error: User is unauthorized' % prefix msg = f"{prefix}: Request Error: User is unauthorized"
self.log.error(msg) self.log.error(msg)
raise CvpApiError(msg) raise CvpApiError(msg)
else: msg = f"{prefix}: Request Error: {response.reason} - {response.text}"
msg = '%s: Request Error: %s - %s' % (prefix, response.reason,
response.text)
self.log.error(msg)
raise CvpRequestError(msg) raise CvpRequestError(msg)
if 'LOG OUT MESSAGE' in response.text: if 'LOG OUT MESSAGE' in response.text:
msg = ('%s: Request Error: session logged out' % prefix) msg = f"{prefix}: Request Error: session logged out"
raise CvpSessionLogOutError(msg) raise CvpSessionLogOutError(msg)
joutput = json_decoder(response.text) joutput = json_decoder(response.text)
@ -456,9 +474,9 @@ class CvpClient(object):
# Build the error message from all the errors. # Build the error message from all the errors.
err_msg = error_list[0] err_msg = error_list[0]
for idx in range(1, len(error_list)): for idx in range(1, len(error_list)):
err_msg = '%s\n%s' % (err_msg, error_list[idx]) err_msg = f"{err_msg}\n{error_list[idx]}"
msg = ('%s: Request Error: %s' % (prefix, err_msg)) msg = f"{prefix}: Request Error: {err_msg}"
self.log.error(msg) self.log.error(msg)
raise CvpApiError(msg) raise CvpApiError(msg)
@ -473,8 +491,7 @@ class CvpClient(object):
response status is not OK. response status is not OK.
''' '''
if not response.ok: if not response.ok:
msg = '%s: Request Error: %s - %s' % (prefix, response.reason, msg = f"{prefix}: Request Error: {response.reason} - {response.text}"
response.text)
self.log.error(msg) self.log.error(msg)
raise CvpRequestError(msg) raise CvpRequestError(msg)
@ -508,7 +525,7 @@ class CvpClient(object):
self.headers.pop('APP_SESSION_ID', None) self.headers.pop('APP_SESSION_ID', None)
if self.api_token is not None: if self.api_token is not None:
return self._set_headers_api_token() return self._set_headers_api_token()
elif self.is_cvaas: if self.is_cvaas:
raise CvpLoginError('CVaaS only supports API token authentication.' raise CvpLoginError('CVaaS only supports API token authentication.'
' Please create an API token and provide it' ' Please create an API token and provide it'
' via the api_token parameter in combination' ' via the api_token parameter in combination'
@ -547,7 +564,7 @@ class CvpClient(object):
headers=self.headers, headers=self.headers,
timeout=self.connect_timeout, timeout=self.connect_timeout,
verify=self.cert) verify=self.cert)
self._is_good_response(response, 'Authenticate: %s' % url) self._is_good_response(response, f"Authenticate: {url}")
self.cookies = response.cookies self.cookies = response.cookies
self.headers['APP_SESSION_ID'] = response.json()['sessionId'] self.headers['APP_SESSION_ID'] = response.json()['sessionId']
@ -557,10 +574,20 @@ class CvpClient(object):
''' '''
# If using an API token there is no need to run a Login API. # If using an API token there is no need to run a Login API.
# Simply add the token into the headers or cookies # Simply add the token into the headers or cookies
self.headers['Authorization'] = 'Bearer %s' % self.api_token self.headers['Authorization'] = f"Bearer {self.api_token}"
# Alternative to adding token to headers it can be added to # Alternative to adding token to headers it can be added to
# cookies as shown below. # cookies as shown below.
# self.cookies = {'access_token': self.api_token} # self.cookies = {'access_token': self.api_token}
url = self.url_prefix_short + '/api/v1/rest/'
response = self.session.get(
url,
cookies=self.cookies,
headers=self.headers,
timeout=self.connect_timeout,
verify=self.cert
)
# Verify that the generic request was successful
self._is_good_response(response, f"Authenticate: {url}")
def logout(self): def logout(self):
''' '''
@ -572,7 +599,7 @@ class CvpClient(object):
self.log.info('User logged out.') self.log.info('User logged out.')
self.session = None self.session = None
else: else:
err = 'Error trying to logout %s' % response err = f"Error trying to logout {response}"
self.log.error(err) self.log.error(err)
def _make_request(self, req_type, url, timeout, data=None, def _make_request(self, req_type, url, timeout, data=None,
@ -688,8 +715,8 @@ class CvpClient(object):
try: try:
resp_data = response.json() resp_data = response.json()
if (resp_data is not None and 'result' in resp_data if (resp_data is not None and 'result' in resp_data and
and '/resources/' in full_url): '/resources/' in full_url):
# Resource APIs use JSON streaming and will return # Resource APIs use JSON streaming and will return
# multiple JSON objects during GetAll type API # multiple JSON objects during GetAll type API
# calls. We are wrapping the multiple objects into # calls. We are wrapping the multiple objects into
@ -710,12 +737,10 @@ class CvpClient(object):
err_str) err_str)
if 'Extra data' in str(error): if 'Extra data' in str(error):
self.log.debug('Found multiple objects or NO objects in' self.log.debug('Found multiple objects or NO objects in'
'response data. Attempt to decode') ' response data. Attempt to decode')
decoded_data = json_decoder(response.text) decoded_data = json_decoder(response.text)
return {'data': decoded_data} return {'data': decoded_data}
else: self.log.error("Unknown format for JSONDecodeError - %s", err_str)
self.log.error('Unknown format for JSONDecodeError - %s',
err_str)
raise error raise error
def _send_request(self, req_type, full_url, timeout, data=None, def _send_request(self, req_type, full_url, timeout, data=None,
@ -783,7 +808,7 @@ class CvpClient(object):
timeout=timeout, timeout=timeout,
verify=self.cert) verify=self.cert)
else: else:
fhs = dict() fhs = {}
fhs['Accept'] = self.headers['Accept'] fhs['Accept'] = self.headers['Accept']
if 'APP_SESSION_ID' in self.headers: if 'APP_SESSION_ID' in self.headers:
fhs['APP_SESSION_ID'] = self.headers[ fhs['APP_SESSION_ID'] = self.headers[
@ -818,8 +843,7 @@ class CvpClient(object):
continue continue
try: try:
self._is_good_response(response, '%s: %s ' % self._is_good_response(response, f"{req_type}: {full_url} ")
(req_type, full_url))
except CvpSessionLogOutError as error: except CvpSessionLogOutError as error:
self.log.debug(error) self.log.debug(error)
# Retry the request to the same node if there was a CVP session # Retry the request to the same node if there was a CVP session
@ -828,7 +852,6 @@ class CvpClient(object):
# be retried on the same node. # be retried on the same node.
if req_try + 1 == self.NUM_RETRY_REQUESTS: if req_try + 1 == self.NUM_RETRY_REQUESTS:
raise error raise error
else:
self._reset_session() self._reset_session()
if not self.session: if not self.session:
raise error raise error
@ -847,12 +870,10 @@ class CvpClient(object):
# will be retried on the same node. # will be retried on the same node.
if req_try + 1 == self.NUM_RETRY_REQUESTS: if req_try + 1 == self.NUM_RETRY_REQUESTS:
raise error raise error
else:
self._reset_session() self._reset_session()
if not self.session: if not self.session:
raise error raise error
continue continue
else:
# pylint: disable=raising-bad-type # pylint: disable=raising-bad-type
raise error raise error
return response return response

31
debian/changelog vendored
View file

@ -1,3 +1,34 @@
cvprac (1.4.0+dfsg-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 1.4.0+dfsg.
* Updating copyright for 2024.
* Updating to standards-version 4.7.0.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Sat, 18 May 2024 07:27:32 +0200
cvprac (1.3.2+dfsg-1) sid; urgency=medium
* Uploading to sid.
* Merging upstream version 1.3.2+dfsg.
-- Daniel Baumann <mail@daniel-baumann.ch> Sun, 17 Dec 2023 11:37:55 +0100
cvprac (1.3.1+dfsg-5) sid; urgency=medium
* Uploading to sid.
* Manually removing some files that pybuild doesn't clean up during
build (Closes: #1044183).
-- Daniel Baumann <daniel.baumann@progress-linux.org> Mon, 14 Aug 2023 10:20:11 +0200
cvprac (1.3.1+dfsg-4) sid; urgency=medium
* Uploading to sid.
* Adding missing coma in watch file.
-- Daniel Baumann <daniel.baumann@progress-linux.org> Sat, 24 Jun 2023 19:32:43 +0200
cvprac (1.3.1+dfsg-3) sid; urgency=medium cvprac (1.3.1+dfsg-3) sid; urgency=medium
* Uploading to sid. * Uploading to sid.

2
debian/control vendored
View file

@ -8,7 +8,7 @@ Build-Depends:
python3-all, python3-all,
python3-setuptools, python3-setuptools,
Rules-Requires-Root: no Rules-Requires-Root: no
Standards-Version: 4.6.2 Standards-Version: 4.7.0
Homepage: https://github.com/aristanetworks/cvprac Homepage: https://github.com/aristanetworks/cvprac
Vcs-Browser: https://git.progress-linux.org/users/daniel.baumann/debian/packages/cvprac Vcs-Browser: https://git.progress-linux.org/users/daniel.baumann/debian/packages/cvprac
Vcs-Git: https://git.progress-linux.org/users/daniel.baumann/debian/packages/cvprac Vcs-Git: https://git.progress-linux.org/users/daniel.baumann/debian/packages/cvprac

6
debian/copyright vendored
View file

@ -1,16 +1,16 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: cvprac Upstream-Name: cvprac
Upstream-Contact: https://github.com/aristanetworks/cvprac/issues Upstream-Contact: https://github.com/aristanetworks/cvprac/issues
Source: https://github.com/aristanetworks/cvprac/releases Source: https://github.com/aristanetworks/cvprac/tags
Files-Excluded: Files-Excluded:
test test
Files: * Files: *
Copyright: 2017-2023, Arista Networks, Inc. Copyright: 2017-2024 Arista Networks, Inc.
License: BSD-3-clause License: BSD-3-clause
Files: debian/* Files: debian/*
Copyright: 2023 Daniel Baumann <daniel.baumann@progress-linux.org> Copyright: 2023-2024 Daniel Baumann <daniel.baumann@progress-linux.org>
License: BSD-3-clause License: BSD-3-clause
License: BSD-3-clause License: BSD-3-clause

4
debian/rules vendored
View file

@ -5,5 +5,9 @@ export PYBUILD_NAME=cvprac
%: %:
dh ${@} --buildsystem=pybuild dh ${@} --buildsystem=pybuild
execute_after_dh_auto_clean:
# help pybuild
rm -rf *.egg-info
override_dh_auto_test: override_dh_auto_test:
# disabled # disabled

View file

@ -1,6 +1,5 @@
check-manifest check-manifest
coverage coverage
mock
pdoc pdoc
pep8 pep8
pyflakes pyflakes

View file

@ -5,10 +5,12 @@ to help users interact with Arista CloudVision easily and automate the provision
## Table of Contents ## Table of Contents
1. [Authentication](#authentication) - [cvprac labs](#cvprac-labs)
- [Table of Contents](#table-of-contents)
- [Authentication](#authentication)
- [Password Authentication](#password-authentication) - [Password Authentication](#password-authentication)
- [Service Account Token Authentication](#service-account-token-authentication) - [Service Account Token Authentication](#service-account-token-authentication)
1. [Known Limitations](#known-limitations) - [Known Limitations](#known-limitations)
## Authentication ## Authentication
@ -60,6 +62,8 @@ clnt = CvpClient()
clnt.connect(nodes=['10.83.13.33'], username='',password='',api_token=token) clnt.connect(nodes=['10.83.13.33'], username='',password='',api_token=token)
``` ```
> Note that for CVaaS the correct regional URL must be used including `www.`. Please refer to the main page's [README.md](../../README.md#cvaas)
## Known Limitations ## Known Limitations
- for any APIs that interact with EOS devices, the service account name must match the name of the username - for any APIs that interact with EOS devices, the service account name must match the name of the username

View file

@ -7,7 +7,7 @@
import argparse import argparse
import ssl import ssl
import sys import sys
from pkg_resources import parse_version from packaging.version import parse
from getpass import getpass from getpass import getpass
from cvprac.cvp_client import CvpClient from cvprac.cvp_client import CvpClient
import requests.packages.urllib3 import requests.packages.urllib3
@ -56,7 +56,7 @@ def main():
# Get the current CVP version # Get the current CVP version
cvp_release = clnt.api.get_cvp_info()['version'] cvp_release = clnt.api.get_cvp_info()['version']
if parse_version(cvp_release) < parse_version('2020.3.0'): if parse(cvp_release) < parse('2020.3.0'):
# For older CVP, we manually trigger a compliance check # For older CVP, we manually trigger a compliance check
try: try:
clnt.api.check_compliance('root', 'container') clnt.api.check_compliance('root', 'container')

View file

@ -0,0 +1,23 @@
######
v1.3.2
######
2023-12-14
Enhancements
^^^^^^^^^^^^
* Add handling of new password change logout functionality in 2023.1.0. (`254 <https://github.com/aristanetworks/cvprac/pull/254>`_) [`mharista <https://github.com/mharista>`_]
* Add support for config validation during config assign. (`255 <https://github.com/aristanetworks/cvprac/pull/255>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Add support for config validation during config removal. (`256 <https://github.com/aristanetworks/cvprac/pull/256>`_) [`noredistribution <https://github.com/noredistribution>`_]
Fixed
^^^^^
* Add ability to use device_decommissioning for unprovisioned devices. (`253 <https://github.com/aristanetworks/cvprac/pull/253>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Add check to connect() to ensure token works. (`258 <https://github.com/aristanetworks/cvprac/pull/258>`_) [`chetryan <https://github.com/chetryan>`_]
Documentation
^^^^^^^^^^^^^
* Add documentation for CVaaS regional URLs. (`259 <https://github.com/aristanetworks/cvprac/pull/259>`_) [`noredistribution <https://github.com/noredistribution>`_]

View file

@ -0,0 +1,20 @@
######
v1.4.0
######
2024-5-6
Enhancements
^^^^^^^^^^^^
* Move from pkg_resources to packaging for Python 3.12 support. (`271 <https://github.com/aristanetworks/cvprac/pull/271>`_) [`mharista <https://github.com/mharista>`_]
* Add support for searchTopology V3 endpoint. (`275 <https://github.com/aristanetworks/cvprac/pull/275>`_) [`mharista <https://github.com/mharista>`_]
Fixed
^^^^^
* Add missing url encoding for get_user. (`264 <https://github.com/aristanetworks/cvprac/pull/264>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Updated the enrollment endpoint for CVaaS. (`269 <https://github.com/aristanetworks/cvprac/pull/269>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Add timeout to get_configlets_and_mappers(). (`270 <https://github.com/aristanetworks/cvprac/pull/270>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Update setup.py to reference python3 only. (`272 <https://github.com/aristanetworks/cvprac/pull/272>`_) [`mharista <https://github.com/mharista>`_]
* Python3 lint/format fixes. (`273 <https://github.com/aristanetworks/cvprac/pull/273>`_) [`mharista <https://github.com/mharista>`_]

View file

@ -1 +1,2 @@
requests[socks]>=2.27.0 requests[socks]>=2.27.0
packaging>=23.2

View file

@ -100,8 +100,13 @@ setup(
# Specify the Python versions you support here. In particular, ensure # Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both. # that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
], ],
# What does your project relate to? # What does your project relate to?
@ -111,7 +116,7 @@ setup(
# your project is installed. For an analysis of "install_requires" vs pip's # your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see: # requirements files see:
# https://packaging.python.org/en/latest/requirements.html # https://packaging.python.org/en/latest/requirements.html
install_requires=['requests[socks]>=2.27.0'], install_requires=['requests[socks]>=2.27.0', 'packaging>=23.2'],
# List additional groups of dependencies here (e.g. development # List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax, # dependencies). You can install these using the following syntax,