Skip to content

Commit

Permalink
fixes + add DockerHubApi unit tests (close #218)
Browse files Browse the repository at this point in the history
  • Loading branch information
tcaiazzi committed Jun 15, 2023
1 parent 430666a commit 3fe328f
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 13 deletions.
36 changes: 23 additions & 13 deletions src/Kathara/webhooks/DockerHubApi.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ def get_images() -> filter:
Raises:
HTTPConnectionError: If there is a connection error with the Docker Hub.
"""
try:
result = requests.get(DOCKER_HUB_KATHARA_URL)
logging.debug("Getting Kathara images from Docker Hub...")
response = requests.get(DOCKER_HUB_KATHARA_URL)
except requests.exceptions.ConnectionError as e:
raise HTTPConnectionError(str(e))

if result.status_code != 200:
logging.debug("Docker Hub replied with status code %s.", result.status_code)
raise HTTPConnectionError("Docker Hub replied with status code %s." % result.status_code)
if response.status_code != 200:
logging.debug("Docker Hub replied with status code %s.", response.status_code)
raise HTTPConnectionError("Docker Hub replied with status code %s." % response.status_code)

return filter(
lambda x: not x['is_private'] and x['repository_type'] == 'image' and x['name'] not in EXCLUDED_IMAGES,
result.json()['results']
response.json()['results']
)

@staticmethod
Expand All @@ -53,17 +53,27 @@ def get_tagged_images() -> list[str]:
HTTPConnectionError: If there is a connection error with the Docker Hub.
"""
images = list(DockerHubApi.get_images())

tagged_images = []

def get_image_tag(tags, image):
image_name = f"{image['namespace']}/{image['name']}"
res = requests.get(f"https://hub.docker.com/v2/repositories/{image_name}/tags/?page_size=-1&ordering")
tags.extend(list(dict(map(lambda x:
(x['digest'],
f"{image_name}:{x['name']}" if x['name'] != "latest" else image_name),
filter(lambda x: x['tag_status'] == 'active',
res.json()['results']))).values()))
try:
logging.debug(f"Getting Kathara tags for image '{image_name}' from Docker Hub...")
response = requests.get(
f"https://hub.docker.com/v2/repositories/{image_name}/tags/?page_size=-1&ordering"
)
except requests.exceptions.ConnectionError as e:
raise HTTPConnectionError(str(e))

if response.status_code != 200:
logging.debug(f"Docker Hub replied with status code %s for image '{image_name}'.", response.status_code)
raise HTTPConnectionError(
f"Docker Hub replied with status code %s for image '{image_name}'." % response.status_code)

tags.extend(list(map(
lambda x: f"{image_name}:{x['name']}" if x['name'] != "latest" else image_name,
filter(lambda x: x['tag_status'] == 'active', response.json()['results'])
)))

pool_size = get_pool_size()
machines_pool = Pool(pool_size)
Expand Down
117 changes: 117 additions & 0 deletions tests/webhooks/docker_hub_api_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import sys
from unittest import mock

import pytest
import requests.exceptions

sys.path.insert(0, './')

from src.Kathara.webhooks.DockerHubApi import DockerHubApi, EXCLUDED_IMAGES
from src.Kathara.exceptions import HTTPConnectionError

EXCLUDED_IMAGES.append("excluded")


@pytest.fixture()
@mock.patch("requests.Response")
def docker_hub_get_images_response(mock_response):
mock_response.status_code = 200
mock_response.json.return_value = {
'results': [
{'name': 'test', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'},
{'name': 'test-2', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'},
{'name': 'test-3', 'namespace': 'kathara', 'is_private': True, 'repository_type': 'image'},
{'name': 'excluded', 'namespace': 'kathara', 'is_private': True, 'repository_type': 'image'}
]
}
return mock_response


@pytest.fixture()
@mock.patch("requests.Response")
def docker_hub_get_tags_response(mock_response):
mock_response.status_code = 200
mock_response.json.return_value = {
'results': [
{'name': 'latest', 'digest': '11111', 'tag_status': 'active', 'repository_type': 'image'},
{'name': 'tag-latest', 'digest': '11111', 'tag_status': 'active', 'repository_type': 'image'},
{'name': 'tag-1', 'digest': '22222', 'tag_status': 'active', 'repository_type': 'image'},
{'name': 'tag-2', 'digest': '22222', 'tag_status': 'active', 'repository_type': 'image'},
{'name': 'tag-1', 'digest': '33333', 'tag_status': 'inactive', 'repository_type': 'image'},
]
}
return mock_response


#
# TEST: get_images()
#
@mock.patch("requests.get")
def test_get_images(mock_requests_get, docker_hub_get_images_response):
mock_requests_get.return_value = docker_hub_get_images_response
images = list(DockerHubApi.get_images())
assert len(images) == 2
assert images[0]['name'] == 'test'
assert images[1]['name'] == 'test-2'


@mock.patch("requests.get")
def test_get_images_connection_error(mock_requests_get):
mock_requests_get.side_effect = requests.exceptions.ConnectionError
with pytest.raises(HTTPConnectionError):
DockerHubApi.get_images()


@mock.patch("requests.get")
def test_get_images_status_code_error(mock_requests_get):
mock_requests_get.status_code = 404
with pytest.raises(HTTPConnectionError):
DockerHubApi.get_images()


#
# TEST: get_tagged_images()
#
@mock.patch("requests.get")
@mock.patch("src.Kathara.webhooks.DockerHubApi.DockerHubApi.get_images")
def test_get_tagged_images(mock_get_images, mock_request_get, docker_hub_get_tags_response):
mock_get_images.return_value = [
{'name': 'test-0', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'},
{'name': 'test-1', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'}
]
mock_request_get.return_value = docker_hub_get_tags_response
tagged_images = DockerHubApi.get_tagged_images()
print(tagged_images)
assert len(tagged_images) == 8
assert 'kathara/test-0' in tagged_images
assert 'kathara/test-0:tag-latest' in tagged_images
assert 'kathara/test-0:tag-1' in tagged_images
assert 'kathara/test-0:tag-2' in tagged_images
assert 'kathara/test-1' in tagged_images
assert 'kathara/test-1:tag-latest' in tagged_images
assert 'kathara/test-1:tag-1' in tagged_images
assert 'kathara/test-1:tag-2' in tagged_images


@mock.patch("requests.get")
@mock.patch("src.Kathara.webhooks.DockerHubApi.DockerHubApi.get_images")
def test_get_tagged_images_connection_error(mock_get_images, mock_requests_get):
mock_get_images.return_value = [
{'name': 'test-0', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'},
{'name': 'test-1', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'}
]
mock_requests_get.side_effect = requests.exceptions.ConnectionError
with pytest.raises(HTTPConnectionError):
DockerHubApi.get_tagged_images()


@mock.patch("requests.get")
@mock.patch("src.Kathara.webhooks.DockerHubApi.DockerHubApi.get_images")
def test_get_tagged_images_status_code_error(mock_get_images, mock_requests_get):
mock_get_images.return_value = [
{'name': 'test-0', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'},
{'name': 'test-1', 'namespace': 'kathara', 'is_private': False, 'repository_type': 'image'}
]
mock_requests_get.status_code = 404
with pytest.raises(HTTPConnectionError):
DockerHubApi.get_tagged_images()

0 comments on commit 3fe328f

Please sign in to comment.