Merging upstream version 0.12.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f45bc3d463
commit
8d2f70e3c7
77 changed files with 23610 additions and 2331 deletions
140
eos_downloader/models/data.py
Normal file
140
eos_downloader/models/data.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
# coding: utf-8 -*-
|
||||
"""This module defines data models and mappings for image types of CloudVision and EOS on Arista.com.
|
||||
|
||||
Classes
|
||||
-------
|
||||
ImageInfo:
|
||||
A Pydantic model representing image information for a specific image type.
|
||||
DataMapping:
|
||||
A Pydantic model representing data mapping for image types of CloudVision and EOS on Arista.com.
|
||||
|
||||
Methods
|
||||
-------
|
||||
DataMapping.filename(software: AristaMapping, image_type: str, version: str) -> str:
|
||||
Generates a filename based on the provided software, image type, and version.
|
||||
|
||||
Constants
|
||||
-------
|
||||
- RTYPE_FEATURE (ReleaseType): Represents a feature release type.
|
||||
- RTYPE_MAINTENANCE (ReleaseType): Represents a maintenance release type.
|
||||
- RTYPES (List[ReleaseType]): A list containing the feature and maintenance release types.
|
||||
|
||||
Variables
|
||||
-------
|
||||
- software_mapping (DataMapping): An instance of DataMapping containing the mappings for CloudVision and EOS image types.
|
||||
"""
|
||||
|
||||
from typing import Dict, List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from eos_downloader.models.types import AristaMapping, ReleaseType
|
||||
|
||||
|
||||
RTYPE_FEATURE: ReleaseType = "F"
|
||||
RTYPE_MAINTENANCE: ReleaseType = "M"
|
||||
RTYPES: List[ReleaseType] = [RTYPE_FEATURE, RTYPE_MAINTENANCE]
|
||||
|
||||
|
||||
class ImageInfo(BaseModel):
|
||||
"""Image information for a specific image type.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
extension : str
|
||||
The file extension for the image type.
|
||||
prepend : str
|
||||
The prefix to prepend to the filename.
|
||||
"""
|
||||
|
||||
extension: str
|
||||
prepend: str
|
||||
|
||||
|
||||
class DataMapping(BaseModel):
|
||||
"""Data mapping for image types of CloudVision and EOS on Arista.com.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
CloudVision : Dict[str, ImageInfo]
|
||||
Mapping of image types to their information for CloudVision.
|
||||
EOS : Dict[str, ImageInfo]
|
||||
Mapping of image types to their information for EOS.
|
||||
|
||||
Methods
|
||||
-------
|
||||
filename(software: AristaMapping, image_type: str, version: str) -> str
|
||||
Generates a filename based on the provided software, image type, and version.
|
||||
"""
|
||||
|
||||
CloudVision: Dict[str, ImageInfo]
|
||||
EOS: Dict[str, ImageInfo]
|
||||
|
||||
def filename(self, software: AristaMapping, image_type: str, version: str) -> str:
|
||||
"""Generates a filename based on the provided software, image type, and version.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
software : AristaMapping
|
||||
The name of the software for which the filename is being generated.
|
||||
image_type : str
|
||||
The type of image for which the filename is being generated.
|
||||
version : str
|
||||
The version of the software or image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The generated filename.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the software does not have a corresponding mapping.
|
||||
ValueError
|
||||
If no configuration is found for the given image type and no default configuration is available.
|
||||
"""
|
||||
|
||||
if hasattr(self, software):
|
||||
soft_mapping = getattr(self, software)
|
||||
image_config = soft_mapping.get(image_type, None)
|
||||
if image_config is None:
|
||||
image_config = getattr(soft_mapping, "default", None)
|
||||
if image_config is None:
|
||||
raise ValueError(
|
||||
f"No default configuration found for image type {image_type}"
|
||||
)
|
||||
if image_config is not None:
|
||||
return f"{image_config.prepend}-{version}{image_config.extension}"
|
||||
raise ValueError(f"No configuration found for image type {image_type}")
|
||||
raise ValueError(f"Incorrect value for software {software}")
|
||||
|
||||
|
||||
# Data mapping for image types of CloudVision and EOS on Arista.com.
|
||||
software_mapping = DataMapping(
|
||||
CloudVision={
|
||||
"ova": {"extension": ".ova", "prepend": "cvp"},
|
||||
"rpm": {"extension": "", "prepend": "cvp-rpm-installer"},
|
||||
"kvm": {"extension": "-kvm.tgz", "prepend": "cvp"},
|
||||
"upgrade": {"extension": ".tgz", "prepend": "cvp-upgrade"},
|
||||
},
|
||||
EOS={
|
||||
"64": {"extension": ".swi", "prepend": "EOS64"},
|
||||
"INT": {"extension": "-INT.swi", "prepend": "EOS"},
|
||||
"2GB-INT": {"extension": "-INT.swi", "prepend": "EOS-2GB"},
|
||||
"cEOS": {"extension": ".tar.xz", "prepend": "cEOS-lab"},
|
||||
"cEOS64": {"extension": ".tar.xz", "prepend": "cEOS64-lab"},
|
||||
"vEOS": {"extension": ".vmdk", "prepend": "vEOS"},
|
||||
"vEOS-lab": {"extension": ".vmdk", "prepend": "vEOS-lab"},
|
||||
"EOS-2GB": {"extension": ".swi", "prepend": "EOS-2GB"},
|
||||
"RN": {"extension": "-", "prepend": "RN"},
|
||||
"SOURCE": {"extension": "-source.tar", "prepend": "EOS"},
|
||||
"default": {"extension": ".swi", "prepend": "EOS"},
|
||||
},
|
||||
)
|
||||
|
||||
# List of supported format for EOS software packages
|
||||
eos_package_format = software_mapping.EOS.keys()
|
||||
|
||||
# List of supported format for CloudVision software packages
|
||||
cvp_package_format = software_mapping.EOS.keys()
|
52
eos_downloader/models/types.py
Normal file
52
eos_downloader/models/types.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
"""
|
||||
This module defines type aliases and literals used in the eos_downloader project.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
AristaPackage : Literal
|
||||
Literal type for Arista package types. Can be either "eos" or "cvp".
|
||||
AristaMapping : Literal
|
||||
Literal type for Arista mapping types. Can be either "CloudVision" or "EOS".
|
||||
AristaVersions : Union
|
||||
Union type for supported SemVer object types. Can be either EosVersion or CvpVersion.
|
||||
ReleaseType : Literal
|
||||
Literal type for release types. Can be either "M" (maintenance) or "F" (feature).
|
||||
|
||||
Examples
|
||||
--------
|
||||
# Example usage of AristaPackage
|
||||
def get_package_type(package: AristaPackage):
|
||||
if package == "eos":
|
||||
return "Arista EOS package"
|
||||
elif package == "cvp":
|
||||
return "CloudVision Portal package"
|
||||
|
||||
# Example usage of AristaVersions
|
||||
def print_version(version: AristaVersions):
|
||||
print(f"Version: {version}")
|
||||
|
||||
# Example usage of ReleaseType
|
||||
def is_feature_release(release: ReleaseType) -> bool:
|
||||
return release == "F"
|
||||
"""
|
||||
|
||||
from typing import Literal, Union
|
||||
|
||||
import eos_downloader.logics
|
||||
|
||||
# import eos_downloader.logics.arista_server
|
||||
import eos_downloader.models.version
|
||||
|
||||
# Define the product type using Literal
|
||||
AristaPackage = Literal["eos", "cvp"]
|
||||
AristaMapping = Literal["CloudVision", "EOS"]
|
||||
|
||||
# Define list of support SemVer object type
|
||||
AristaVersions = Union[
|
||||
eos_downloader.models.version.EosVersion, eos_downloader.models.version.CvpVersion
|
||||
]
|
||||
|
||||
# List of supported release codes
|
||||
ReleaseType = Literal["M", "F"]
|
|
@ -1,13 +1,67 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
"""The module implements version management following semantic versioning principles with custom adaptations for
|
||||
Arista EOS and CloudVision Portal (CVP) software versioning schemes.
|
||||
|
||||
"""Module for EOS version management"""
|
||||
Classes
|
||||
-------
|
||||
SemVer:
|
||||
Base class implementing semantic versioning with comparison and matching capabilities.
|
||||
EosVersion:
|
||||
Specialized version handling for Arista EOS software releases.
|
||||
CvpVersion:
|
||||
Specialized version handling for CloudVision Portal releases.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
major : int
|
||||
Major version number.
|
||||
minor : int
|
||||
Minor version number.
|
||||
patch : int
|
||||
Patch version number.
|
||||
rtype : Optional[str]
|
||||
Release type (e.g., 'M' for maintenance, 'F' for feature).
|
||||
other : Any
|
||||
Additional version information.
|
||||
regex_version : ClassVar[Pattern[str]]
|
||||
Regular expression to extract version information.
|
||||
regex_branch : ClassVar[Pattern[str]]
|
||||
Regular expression to extract branch information.
|
||||
description : str
|
||||
A basic description of this class.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
# Basic SemVer usage:
|
||||
>>> version = SemVer(major=4, minor=23, patch=3)
|
||||
'4.23.3'
|
||||
|
||||
# EOS version handling:
|
||||
>>> eos = EosVersion.from_str('4.23.3M')
|
||||
>>> eos.branch
|
||||
'4.23'
|
||||
|
||||
# CVP version handling:
|
||||
>>> cvp = CvpVersion.from_str('2024.1.0')
|
||||
>>> str(cvp)
|
||||
|
||||
The module enforces version format validation through regular expressions and provides
|
||||
comprehensive comparison operations (==, !=, <, <=, >, >=) between versions.
|
||||
|
||||
Note:
|
||||
--------
|
||||
- EOS versions follow the format: <major>.<minor>.<patch>[M|F]
|
||||
- CVP versions follow the format: <year>.<minor>.<patch>
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import typing
|
||||
from typing import Any, Optional
|
||||
import logging
|
||||
from typing import Any, Optional, Pattern, ClassVar
|
||||
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
|
@ -16,163 +70,188 @@ from eos_downloader.tools import exc_to_str
|
|||
|
||||
# logger = logging.getLogger(__name__)
|
||||
|
||||
BASE_VERSION_STR = "4.0.0F"
|
||||
BASE_BRANCH_STR = "4.0"
|
||||
|
||||
RTYPE_FEATURE = "F"
|
||||
RTYPE_MAINTENANCE = "M"
|
||||
RTYPES = [RTYPE_FEATURE, RTYPE_MAINTENANCE]
|
||||
class SemVer(BaseModel):
|
||||
"""A class to represent a Semantic Version (SemVer) based on pydanntic.
|
||||
|
||||
# Regular Expression to capture multiple EOS version format
|
||||
# 4.24
|
||||
# 4.23.0
|
||||
# 4.21.1M
|
||||
# 4.28.10.F
|
||||
# 4.28.6.1M
|
||||
REGEX_EOS_VERSION = re.compile(
|
||||
r"^.*(?P<major>4)\.(?P<minor>\d{1,2})\.(?P<patch>\d{1,2})(?P<other>\.\d*)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
REGEX_EOS_BRANCH = re.compile(
|
||||
r"^.*(?P<major>4)\.(?P<minor>\d{1,2})(\.?P<patch>\d)*(\.\d)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
This class provides methods to parse, compare, and manipulate semantic versions.
|
||||
It supports standard semantic versioning with optional release type and additional version information.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> version = SemVer(major=4, minor=23, patch=3, rtype="M")
|
||||
>>> str(version)
|
||||
'4.23.3M'
|
||||
|
||||
class EosVersion(BaseModel):
|
||||
"""
|
||||
EosVersion object to play with version management in code
|
||||
>>> version2 = SemVer.from_str('4.24.1F')
|
||||
>>> version2.branch
|
||||
'4.24'
|
||||
|
||||
Since EOS is not using strictly semver approach, this class mimic some functions from semver lib for Arista EOS versions
|
||||
It is based on Pydantic and provides helpers for comparison:
|
||||
>>> version < version2
|
||||
True
|
||||
|
||||
Examples:
|
||||
>>> eos_version_str = '4.23.2F'
|
||||
>>> eos_version = EosVersion.from_str(eos_version_str)
|
||||
>>> print(f'str representation is: {str(eos_version)}')
|
||||
str representation is: 4.23.2F
|
||||
>>> version.match("<=4.24.0")
|
||||
True
|
||||
|
||||
>>> other_version = EosVersion.from_str(other_version_str)
|
||||
>>> print(f'eos_version < other_version: {eos_version < other_version}')
|
||||
eos_version < other_version: True
|
||||
>>> version.is_in_branch("4.23")
|
||||
True
|
||||
|
||||
>>> print(f'Is eos_version match("<=4.23.3M"): {eos_version.match("<=4.23.3M")}')
|
||||
Is eos_version match("<=4.23.3M"): True
|
||||
|
||||
>>> print(f'Is eos_version in branch 4.23: {eos_version.is_in_branch("4.23.0")}')
|
||||
Is eos_version in branch 4.23: True
|
||||
|
||||
Args:
|
||||
BaseModel (Pydantic): Pydantic Base Model
|
||||
Attributes
|
||||
----------
|
||||
major : int
|
||||
Major version number.
|
||||
minor : int
|
||||
Minor version number.
|
||||
patch : int
|
||||
Patch version number.
|
||||
rtype : Optional[str]
|
||||
Release type (e.g., 'M' for maintenance, 'F' for feature).
|
||||
other : Any
|
||||
Additional version information.
|
||||
regex_version : ClassVar[Pattern[str]]
|
||||
Regular expression to extract version information.
|
||||
regex_branch : ClassVar[Pattern[str]]
|
||||
Regular expression to extract branch information.
|
||||
description : str
|
||||
A basic description of this class.
|
||||
"""
|
||||
|
||||
major: int = 4
|
||||
major: int = 0
|
||||
minor: int = 0
|
||||
patch: int = 0
|
||||
rtype: Optional[str] = "F"
|
||||
rtype: Optional[str] = None
|
||||
other: Any = None
|
||||
# Regular Expression to extract version information.
|
||||
regex_version: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d{1,2})(?P<other>\.\d*)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
regex_branch: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>\d+)\.(?P<minor>\d+)(\.?P<patch>\d)*(\.\d)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
# A Basic description of this class
|
||||
description: str = "A Generic SemVer implementation"
|
||||
|
||||
@classmethod
|
||||
def from_str(cls, eos_version: str) -> EosVersion:
|
||||
def from_str(cls, semver: str) -> SemVer:
|
||||
"""Parse a string into a SemVer object.
|
||||
|
||||
This method parses a semantic version string or branch name into a SemVer object.
|
||||
It supports both standard semver format (x.y.z) and branch format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
semver : str
|
||||
The version string to parse. Can be either a semantic version
|
||||
string (e.g., "1.2.3") or a branch format.
|
||||
|
||||
Returns
|
||||
-------
|
||||
SemVer
|
||||
A SemVer object representing the parsed version.
|
||||
Returns an empty SemVer object if parsing fails.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> SemVer.from_str("1.2.3")
|
||||
SemVer(major=1, minor=2, patch=3)
|
||||
>>> SemVer.from_str("branch-1.2.3")
|
||||
SemVer(major=1, minor=2, patch=3)
|
||||
"""
|
||||
Class constructor from a string representing EOS version
|
||||
|
||||
Use regular expresion to extract fields from string.
|
||||
It supports following formats:
|
||||
- 4.24
|
||||
- 4.23.0
|
||||
- 4.21.1M
|
||||
- 4.28.10.F
|
||||
- 4.28.6.1M
|
||||
logging.debug(f"Creating SemVer object from string: {semver}")
|
||||
|
||||
Args:
|
||||
eos_version (str): EOS version in str format
|
||||
|
||||
Returns:
|
||||
EosVersion object
|
||||
"""
|
||||
logger.debug(f"receiving version: {eos_version}")
|
||||
if REGEX_EOS_VERSION.match(eos_version):
|
||||
matches = REGEX_EOS_VERSION.match(eos_version)
|
||||
if cls.regex_version.match(semver):
|
||||
matches = cls.regex_version.match(semver)
|
||||
# assert matches is not None
|
||||
assert matches is not None
|
||||
logging.debug(f"Matches version: {matches}")
|
||||
return cls(**matches.groupdict())
|
||||
if REGEX_EOS_BRANCH.match(eos_version):
|
||||
matches = REGEX_EOS_BRANCH.match(eos_version)
|
||||
if cls.regex_branch.match(semver):
|
||||
matches = cls.regex_branch.match(semver)
|
||||
# assert matches is not None
|
||||
assert matches is not None
|
||||
logging.debug(f"Matches branch: {matches}")
|
||||
return cls(**matches.groupdict())
|
||||
logger.error(f"Error occured with {eos_version}")
|
||||
return EosVersion()
|
||||
logging.error(f"Error occured with {semver}")
|
||||
return SemVer()
|
||||
|
||||
@property
|
||||
def branch(self) -> str:
|
||||
"""
|
||||
Extract branch of version
|
||||
Extract branch of version.
|
||||
|
||||
Returns:
|
||||
str: branch from version
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
Branch from version.
|
||||
"""
|
||||
return f"{self.major}.{self.minor}"
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
Standard str representation
|
||||
Standard str representation.
|
||||
|
||||
Return string for EOS version like 4.23.3M
|
||||
Return string for EOS version like 4.23.3M.
|
||||
|
||||
Returns:
|
||||
str: A standard EOS version string representing <MAJOR>.<MINOR>.<PATCH><RTYPE>
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
A standard EOS version string representing <MAJOR>.<MINOR>.<PATCH><RTYPE>.
|
||||
"""
|
||||
if self.other is None:
|
||||
return f"{self.major}.{self.minor}.{self.patch}{self.rtype}"
|
||||
return f"{self.major}.{self.minor}.{self.patch}{self.other}{self.rtype}"
|
||||
return f"{self.major}.{self.minor}.{self.patch}{self.other if self.other is not None else ''}{self.rtype if self.rtype is not None else ''}"
|
||||
|
||||
def _compare(self, other: EosVersion) -> float:
|
||||
def _compare(self, other: SemVer) -> float:
|
||||
"""
|
||||
An internal comparison function to compare 2 EosVersion objects
|
||||
An internal comparison function to compare 2 EosVersion objects.
|
||||
|
||||
Do a deep comparison from Major to Release Type
|
||||
The return value is
|
||||
Do a deep comparison from Major to Release Type.
|
||||
The return value is:
|
||||
- negative if ver1 < ver2,
|
||||
- zero if ver1 == ver2
|
||||
- strictly positive if ver1 > ver2
|
||||
- zero if ver1 == ver2,
|
||||
- strictly positive if ver1 > ver2.
|
||||
|
||||
Args:
|
||||
other (EosVersion): An EosVersion to compare with this object
|
||||
Parameters
|
||||
----------
|
||||
other : SemVer
|
||||
An EosVersion to compare with this object.
|
||||
|
||||
Raises:
|
||||
ValueError: Raise ValueError if input is incorrect type
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
Raise ValueError if input is incorrect type.
|
||||
|
||||
Returns:
|
||||
float: -1 if ver1 < ver2, 0 if ver1 == ver2, 1 if ver1 > ver2
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
-1 if ver1 < ver2, 0 if ver1 == ver2, 1 if ver1 > ver2.
|
||||
"""
|
||||
if not isinstance(other, EosVersion):
|
||||
if not isinstance(other, SemVer):
|
||||
raise ValueError(
|
||||
f"could not compare {other} as it is not an EosVersion object"
|
||||
)
|
||||
comparison_flag: float = 0
|
||||
logger.warning(
|
||||
f"current version {self.__str__()} - other {str(other)}" # pylint: disable = unnecessary-dunder-call
|
||||
)
|
||||
for key, _ in self.dict().items():
|
||||
if (
|
||||
comparison_flag == 0
|
||||
and self.dict()[key] is None
|
||||
or other.dict()[key] is None
|
||||
and self.model_dump()[key] is None
|
||||
or other.model_dump()[key] is None
|
||||
):
|
||||
logger.debug(f"{key}: local None - remote None")
|
||||
logger.debug(f"{key}: local {self.dict()} - remote {other.dict()}")
|
||||
return comparison_flag
|
||||
logger.debug(
|
||||
f"{key}: local {self.dict()[key]} - remote {other.dict()[key]}"
|
||||
)
|
||||
if comparison_flag == 0 and self.dict()[key] < other.dict()[key]:
|
||||
if (
|
||||
comparison_flag == 0
|
||||
and self.model_dump()[key] < other.model_dump()[key]
|
||||
):
|
||||
comparison_flag = -1
|
||||
if comparison_flag == 0 and self.dict()[key] > other.dict()[key]:
|
||||
if (
|
||||
comparison_flag == 0
|
||||
and self.model_dump()[key] > other.model_dump()[key]
|
||||
):
|
||||
comparison_flag = 1
|
||||
if comparison_flag != 0:
|
||||
logger.info(f"comparison result is {comparison_flag}")
|
||||
logging.debug(
|
||||
f"Comparison flag {self.model_dump()[key]} with {other.model_dump()[key]}: {comparison_flag}"
|
||||
)
|
||||
return comparison_flag
|
||||
logger.info(f"comparison result is {comparison_flag}")
|
||||
return comparison_flag
|
||||
|
||||
@typing.no_type_check
|
||||
|
@ -214,26 +293,33 @@ class EosVersion(BaseModel):
|
|||
"""
|
||||
Compare self to match a match expression.
|
||||
|
||||
Example:
|
||||
Parameters
|
||||
----------
|
||||
match_expr : str
|
||||
Optional operator and version; valid operators are:
|
||||
``<`` smaller than
|
||||
``>`` greater than
|
||||
``>=`` greater or equal than
|
||||
``<=`` smaller or equal than
|
||||
``==`` equal
|
||||
``!=`` not equal.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If input has no match_expr nor match_ver.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the expression matches the version, otherwise False.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> eos_version.match("<=4.23.3M")
|
||||
True
|
||||
>>> eos_version.match("==4.23.3M")
|
||||
False
|
||||
|
||||
Args:
|
||||
match_expr (str): optional operator and version; valid operators are
|
||||
``<`` smaller than
|
||||
``>`` greater than
|
||||
``>=`` greator or equal than
|
||||
``<=`` smaller or equal than
|
||||
``==`` equal
|
||||
``!=`` not equal
|
||||
|
||||
Raises:
|
||||
ValueError: If input has no match_expr nor match_ver
|
||||
|
||||
Returns:
|
||||
bool: True if the expression matches the version, otherwise False
|
||||
"""
|
||||
prefix = match_expr[:2]
|
||||
if prefix in (">=", "<=", "==", "!="):
|
||||
|
@ -251,7 +337,6 @@ class EosVersion(BaseModel):
|
|||
"['<', '>', '==', '<=', '>=', '!=']. "
|
||||
f"You provided: {match_expr}"
|
||||
)
|
||||
logger.debug(f"work on comparison {prefix} with base release {match_version}")
|
||||
possibilities_dict = {
|
||||
">": (1,),
|
||||
"<": (-1,),
|
||||
|
@ -261,27 +346,133 @@ class EosVersion(BaseModel):
|
|||
"<=": (-1, 0),
|
||||
}
|
||||
possibilities = possibilities_dict[prefix]
|
||||
cmp_res = self._compare(EosVersion.from_str(match_version))
|
||||
cmp_res = self._compare(SemVer.from_str(match_version))
|
||||
|
||||
return cmp_res in possibilities
|
||||
|
||||
def is_in_branch(self, branch_str: str) -> bool:
|
||||
"""
|
||||
Check if current version is part of a branch version
|
||||
Check if current version is part of a branch version.
|
||||
|
||||
Comparison is done across MAJOR and MINOR
|
||||
Comparison is done across MAJOR and MINOR.
|
||||
|
||||
Args:
|
||||
branch_str (str): a string for EOS branch. It supports following formats 4.23 or 4.23.0
|
||||
Parameters
|
||||
----------
|
||||
branch_str : str
|
||||
A string for EOS branch. It supports following formats 4.23 or 4.23.0.
|
||||
|
||||
Returns:
|
||||
bool: True if current version is in provided branch, otherwise False
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if current version is in provided branch, otherwise False.
|
||||
"""
|
||||
logging.info(f"Checking if {self} is in branch {branch_str}")
|
||||
try:
|
||||
logger.debug(f"reading branch str:{branch_str}")
|
||||
branch = EosVersion.from_str(branch_str)
|
||||
branch = SemVer.from_str(branch_str)
|
||||
except Exception as error: # pylint: disable = broad-exception-caught
|
||||
logger.error(exc_to_str(error))
|
||||
else:
|
||||
return self.major == branch.major and self.minor == branch.minor
|
||||
return False
|
||||
|
||||
|
||||
class EosVersion(SemVer):
|
||||
"""EosVersion object to play with version management in code.
|
||||
|
||||
Since EOS is not using strictly semver approach, this class mimics some functions from the semver library for Arista EOS versions.
|
||||
It is based on Pydantic and provides helpers for comparison.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> version = EosVersion(major=4, minor=21, patch=1, rtype="M")
|
||||
>>> print(version)
|
||||
EosVersion(major=4, minor=21, patch=1, rtype='M', other=None)
|
||||
>>> version = EosVersion.from_str('4.32.1F')
|
||||
>>> print(version)
|
||||
EosVersion(major=4, minor=32, patch=1, rtype='F', other=None)
|
||||
|
||||
Attributes
|
||||
----------
|
||||
major : int
|
||||
Major version number, default is 4.
|
||||
minor : int
|
||||
Minor version number, default is 0.
|
||||
patch : int
|
||||
Patch version number, default is 0.
|
||||
rtype : Optional[str]
|
||||
Release type, default is "F".
|
||||
other : Any
|
||||
Any other version information.
|
||||
regex_version : ClassVar[Pattern[str]]
|
||||
Regular expression to extract version information.
|
||||
regex_branch : ClassVar[Pattern[str]]
|
||||
Regular expression to extract branch information.
|
||||
description : str
|
||||
A basic description of this class, default is "A Generic SemVer implementation".
|
||||
"""
|
||||
|
||||
major: int = 4
|
||||
minor: int = 0
|
||||
patch: int = 0
|
||||
rtype: Optional[str] = "F"
|
||||
other: Any = None
|
||||
# Regular Expression to extract version information.
|
||||
regex_version: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>4)\.(?P<minor>\d{1,2})\.(?P<patch>\d{1,2})(?P<other>\.\d*)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
regex_branch: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>4)\.(?P<minor>\d{1,2})(\.?P<patch>\d)*(\.\d)*(?P<rtype>[M,F])*$"
|
||||
)
|
||||
# A Basic description of this class
|
||||
description: str = "A SemVer implementation for EOS"
|
||||
|
||||
|
||||
class CvpVersion(SemVer):
|
||||
"""A CloudVision Portal Version class that inherits from SemVer.
|
||||
|
||||
This class implements version management for CloudVision Portal (CVP) versions
|
||||
following a modified semantic versioning pattern where:
|
||||
- major version represents the year (e.g. 2024)
|
||||
- minor version represents feature releases
|
||||
- patch version represents bug fixes
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> version = CvpVersion(2024, 1, 0)
|
||||
>>> str(version)
|
||||
'2024.1.0'
|
||||
|
||||
Attributes
|
||||
----------
|
||||
major : int
|
||||
The year component of the version (e.g. 2024).
|
||||
minor : int
|
||||
The minor version number.
|
||||
patch : int
|
||||
The patch version number.
|
||||
rtype : Optional[str]
|
||||
Release type if any.
|
||||
other : Any
|
||||
Additional version information if any.
|
||||
regex_version : ClassVar[Pattern[str]]
|
||||
Regular expression to parse version strings.
|
||||
regex_branch : ClassVar[Pattern[str]]
|
||||
Regular expression to parse branch version strings.
|
||||
description : str
|
||||
Brief description of the class purpose.
|
||||
"""
|
||||
|
||||
major: int = 2024
|
||||
minor: int = 0
|
||||
patch: int = 0
|
||||
rtype: Optional[str] = None
|
||||
other: Any = None
|
||||
# Regular Expression to extract version information.
|
||||
regex_version: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>\d{4})\.(?P<minor>\d{1,2})\.(?P<patch>\d{1,2})(?P<other>\.\d*)*$"
|
||||
)
|
||||
regex_branch: ClassVar[Pattern[str]] = re.compile(
|
||||
r"^.*(?P<major>\d{4})\.(?P<minor>\d{1,2})\.(?P<patch>\d{1,2})(?P<other>\.\d*)*$"
|
||||
)
|
||||
# A Basic description of this class
|
||||
description: str = "A SemVer implementation for CloudVision"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue