-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [graph objects] - add supported native images property * update native image obj * enhance docker-image class * add encoding to structured file * fix cache issues * revert docker_images_metadata * fix tests and revert linter and native-image * revert file * comments * fix test_DockerImageExistValidator_is_valid test * revert config
- Loading branch information
Showing
13 changed files
with
288 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import re | ||
from datetime import datetime | ||
from typing import Optional | ||
|
||
from packaging.version import Version | ||
|
||
from demisto_sdk.commands.common.constants import ( | ||
NATIVE_IMAGE_DOCKER_NAME, | ||
) | ||
from demisto_sdk.commands.common.docker.dockerhub_client import DockerHubClient | ||
from demisto_sdk.commands.common.logger import logger | ||
|
||
|
||
class DockerImage: | ||
|
||
DOCKER_IMAGE_REGX = ( | ||
r"^([^/]+)/(.*?)(?::(.*))?$" # regex to extract parts of a docker-image | ||
) | ||
DEMISTO_PYTHON_BASE_IMAGE_REGEX = re.compile( | ||
r"[\d\w]+/python3?:(?P<python_version>[23]\.\d+(\.\d+)?)" # regex to extract python version for image name | ||
) | ||
|
||
def __init__( | ||
self, | ||
dockerhub_client: DockerHubClient, | ||
repository: str = "", | ||
image_name: str = "", | ||
tag: str = "", | ||
): | ||
self._dockerhub_client = dockerhub_client | ||
self.repository = repository # the repository e.g.: demisto | ||
self.image_name = image_name # the image name e.g.: python3, pan-os-python | ||
self.tag = tag # the tag | ||
|
||
@classmethod | ||
def parse( | ||
cls, | ||
docker_image: str, | ||
dockerhub_client: Optional[DockerHubClient] = None, | ||
raise_if_not_valid: bool = False, | ||
) -> "DockerImage": | ||
""" | ||
Parses a docker-image into repository, image name and its tag | ||
Args: | ||
docker_image: the docker image to parse | ||
dockerhub_client: client to interact with dockerhub client | ||
raise_if_not_valid: raise ValueError if the docker-image structure is not valid | ||
""" | ||
_dockerhub_client = dockerhub_client or DockerHubClient() | ||
pattern = re.compile(cls.DOCKER_IMAGE_REGX) | ||
if matches := pattern.match(docker_image): | ||
docker_image_object = cls( | ||
_dockerhub_client, | ||
repository=matches.group(1), | ||
image_name=matches.group(2), | ||
tag=matches.group(3), | ||
) | ||
else: | ||
docker_image_object = cls(_dockerhub_client) | ||
|
||
if raise_if_not_valid and not docker_image_object.is_valid: | ||
raise ValueError( | ||
f"Docker image {docker_image} is not valid, should be in the form of repository/image-name:tag" | ||
) | ||
|
||
return docker_image_object | ||
|
||
def __str__(self): | ||
return f"{self.repository}/{self.image_name}:{self.tag}" | ||
|
||
@property | ||
def name(self): | ||
""" | ||
Returns the repository + image name. .e.g: demisto/python3, demisto/pan-os-python | ||
""" | ||
return f"{self.repository}/{self.image_name}" | ||
|
||
@property | ||
def is_valid(self) -> bool: | ||
""" | ||
Validates that the structure of the docker-image is valid. | ||
Returns: | ||
bool: True if the structure is valid, False if not. | ||
""" | ||
if not self.repository or not self.image_name or not self.tag: | ||
logger.warning( | ||
f"Docker image {self} is not valid, should be in the form of repository/image-name:tag" | ||
) | ||
return False | ||
return True | ||
|
||
@property | ||
def is_tag_latest(self) -> bool: | ||
return self.tag == "latest" | ||
|
||
@property | ||
def is_demisto_repository(self) -> bool: | ||
return self.repository == "demisto" | ||
|
||
@property | ||
def is_native_image(self) -> bool: | ||
return self.name == NATIVE_IMAGE_DOCKER_NAME | ||
|
||
@property | ||
def creation_date(self) -> datetime: | ||
return self._dockerhub_client.get_docker_image_tag_creation_date( | ||
self.name, tag=self.tag | ||
) | ||
|
||
@property | ||
def python_version(self) -> Optional[Version]: | ||
if self.is_valid: | ||
if "pwsh" == self.image_name or "powershell" == self.image_name: | ||
logger.debug( | ||
f"The {self} is a powershell image, does not have python version" | ||
) | ||
return None | ||
|
||
if match := self.DEMISTO_PYTHON_BASE_IMAGE_REGEX.match(str(self)): | ||
return Version(match.group("python_version")) | ||
|
||
logger.debug(f"Could not get python version for image {self} from regex") | ||
image_env = self._dockerhub_client.get_image_env(self.name, tag=self.tag) | ||
|
||
if python_version := next( | ||
( | ||
var.split("=")[1] | ||
for var in image_env | ||
if var.startswith("PYTHON_VERSION=") | ||
), | ||
None, | ||
): | ||
return Version(python_version) | ||
|
||
logger.error(f"Could not find python-version of docker-image {self}") | ||
return None | ||
|
||
logger.debug( | ||
f"docker-image {self} is not valid, could not get its python-version" | ||
) | ||
return None | ||
|
||
@property | ||
def is_image_exist(self) -> bool: | ||
""" | ||
Returns True if the docker-image exist in dockerhub | ||
""" | ||
return self._dockerhub_client.is_docker_image_exist(self.name, tag=self.tag) | ||
|
||
@property | ||
def latest_tag(self) -> Version: | ||
return self._dockerhub_client.get_latest_docker_image_tag(self.name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
demisto_sdk/commands/common/docker/tests/docker_image_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import pytest | ||
|
||
from demisto_sdk.commands.common.docker.docker_image import DockerImage | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"docker_image, expected_repo, expected_image_name, expected_tag", | ||
[ | ||
( | ||
"demisto/pan-os-python:1.0.0.83880", | ||
"demisto", | ||
"pan-os-python", | ||
"1.0.0.83880", | ||
), | ||
("demisto/py3-tools:0.0.1.25751", "demisto", "py3-tools", "0.0.1.25751"), | ||
("demisto/boto3py3:1.0.0.52713", "demisto", "boto3py3", "1.0.0.52713"), | ||
( | ||
"demisto/googleapi-python3:1.0.0.12698", | ||
"demisto", | ||
"googleapi-python3", | ||
"1.0.0.12698", | ||
), | ||
("demisto/ml:1.0.0.84027", "demisto", "ml", "1.0.0.84027"), | ||
("demisto/fetch-data:1.0.0.22177", "demisto", "fetch-data", "1.0.0.22177"), | ||
("demisto/python3:3.10.13.78960", "demisto", "python3", "3.10.13.78960"), | ||
("custom-repo/test-image:7.8.9", "custom-repo", "test-image", "7.8.9"), | ||
("some-repo/test-image-2:1.1.1.1", "some-repo", "test-image-2", "1.1.1.1"), | ||
], | ||
) | ||
def test_docker_image_parse_valid_docker_images( | ||
docker_image: str, expected_repo: str, expected_image_name: str, expected_tag: str | ||
): | ||
""" | ||
Given: | ||
- valid docker images | ||
When: | ||
- trying to parse docker-images parts (repository, image-name and tag) | ||
Then: | ||
- make sure images are parsed correctly | ||
""" | ||
docker_image_object = DockerImage.parse(docker_image) | ||
assert docker_image_object.repository == expected_repo | ||
assert docker_image_object.image_name == expected_image_name | ||
assert docker_image_object.tag == expected_tag | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"docker_image", | ||
[ | ||
"demisto/pan-os-python", | ||
"demisto", | ||
"1.0.0.52713", | ||
"test-image:7.8.9", | ||
"some-repo", | ||
], | ||
) | ||
def test_docker_image_parse_invalid_docker_images(docker_image: str): | ||
""" | ||
Given: | ||
- invalid docker images | ||
When: | ||
- trying to parse docker-images parts (repository, image-name and tag) | ||
Then: | ||
- make sure ValueError is raised | ||
""" | ||
with pytest.raises(ValueError): | ||
DockerImage.parse(docker_image, raise_if_not_valid=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.