diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
commit | a453ac31f3428614cceb99027f8efbdb9258a40b (patch) | |
tree | f61f87408f32a8511cbd91799f9cececb53e0374 /test/units/ansible_test | |
parent | Initial commit. (diff) | |
download | ansible-upstream.tar.xz ansible-upstream.zip |
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/units/ansible_test')
-rw-r--r-- | test/units/ansible_test/__init__.py | 0 | ||||
-rw-r--r-- | test/units/ansible_test/ci/__init__.py | 0 | ||||
-rw-r--r-- | test/units/ansible_test/ci/test_azp.py | 31 | ||||
-rw-r--r-- | test/units/ansible_test/ci/test_shippable.py | 31 | ||||
-rw-r--r-- | test/units/ansible_test/ci/util.py | 53 | ||||
-rw-r--r-- | test/units/ansible_test/conftest.py | 14 | ||||
-rw-r--r-- | test/units/ansible_test/test_docker_util.py | 131 |
7 files changed, 260 insertions, 0 deletions
diff --git a/test/units/ansible_test/__init__.py b/test/units/ansible_test/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/units/ansible_test/__init__.py diff --git a/test/units/ansible_test/ci/__init__.py b/test/units/ansible_test/ci/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/units/ansible_test/ci/__init__.py diff --git a/test/units/ansible_test/ci/test_azp.py b/test/units/ansible_test/ci/test_azp.py new file mode 100644 index 00000000..69c4fa49 --- /dev/null +++ b/test/units/ansible_test/ci/test_azp.py @@ -0,0 +1,31 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from .util import common_auth_test + + +def test_auth(): + # noinspection PyProtectedMember + from ansible_test._internal.ci.azp import ( + AzurePipelinesAuthHelper, + ) + + class TestAzurePipelinesAuthHelper(AzurePipelinesAuthHelper): + def __init__(self): + self.public_key_pem = None + self.private_key_pem = None + + def publish_public_key(self, public_key_pem): + # avoid publishing key + self.public_key_pem = public_key_pem + + def initialize_private_key(self): + # cache in memory instead of on disk + if not self.private_key_pem: + self.private_key_pem = self.generate_private_key() + + return self.private_key_pem + + auth = TestAzurePipelinesAuthHelper() + + common_auth_test(auth) diff --git a/test/units/ansible_test/ci/test_shippable.py b/test/units/ansible_test/ci/test_shippable.py new file mode 100644 index 00000000..08b276c7 --- /dev/null +++ b/test/units/ansible_test/ci/test_shippable.py @@ -0,0 +1,31 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from .util import common_auth_test + + +def test_auth(): + # noinspection PyProtectedMember + from ansible_test._internal.ci.shippable import ( + ShippableAuthHelper, + ) + + class TestShippableAuthHelper(ShippableAuthHelper): + def __init__(self): + self.public_key_pem = None + self.private_key_pem = None + + def publish_public_key(self, public_key_pem): + # avoid publishing key + self.public_key_pem = public_key_pem + + def initialize_private_key(self): + # cache in memory instead of on disk + if not self.private_key_pem: + self.private_key_pem = self.generate_private_key() + + return self.private_key_pem + + auth = TestShippableAuthHelper() + + common_auth_test(auth) diff --git a/test/units/ansible_test/ci/util.py b/test/units/ansible_test/ci/util.py new file mode 100644 index 00000000..ba8e358b --- /dev/null +++ b/test/units/ansible_test/ci/util.py @@ -0,0 +1,53 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import base64 +import json +import re + + +def common_auth_test(auth): + private_key_pem = auth.initialize_private_key() + public_key_pem = auth.public_key_pem + + extract_pem_key(private_key_pem, private=True) + extract_pem_key(public_key_pem, private=False) + + request = dict(hello='World') + auth.sign_request(request) + + verify_signature(request, public_key_pem) + + +def extract_pem_key(value, private): + assert isinstance(value, type(u'')) + + key_type = '(EC )?PRIVATE' if private else 'PUBLIC' + pattern = r'^-----BEGIN ' + key_type + r' KEY-----\n(?P<key>.*?)\n-----END ' + key_type + r' KEY-----\n$' + match = re.search(pattern, value, flags=re.DOTALL) + + assert match, 'key "%s" does not match pattern "%s"' % (value, pattern) + + base64.b64decode(match.group('key')) # make sure the key can be decoded + + +def verify_signature(request, public_key_pem): + signature = request.pop('signature') + payload_bytes = json.dumps(request, sort_keys=True).encode() + + assert isinstance(signature, type(u'')) + + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import ec + from cryptography.hazmat.primitives.serialization import load_pem_public_key + + public_key = load_pem_public_key(public_key_pem.encode(), default_backend()) + + verifier = public_key.verifier( + base64.b64decode(signature.encode()), + ec.ECDSA(hashes.SHA256()), + ) + + verifier.update(payload_bytes) + verifier.verify() diff --git a/test/units/ansible_test/conftest.py b/test/units/ansible_test/conftest.py new file mode 100644 index 00000000..9ec9a02f --- /dev/null +++ b/test/units/ansible_test/conftest.py @@ -0,0 +1,14 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +import os +import pytest +import sys + + +@pytest.fixture(autouse=True, scope='session') +def ansible_test(): + """Make ansible_test available on sys.path for unit testing ansible-test.""" + test_lib = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'lib') + sys.path.insert(0, test_lib) diff --git a/test/units/ansible_test/test_docker_util.py b/test/units/ansible_test/test_docker_util.py new file mode 100644 index 00000000..8427f0f2 --- /dev/null +++ b/test/units/ansible_test/test_docker_util.py @@ -0,0 +1,131 @@ +# This file is part of Ansible +# -*- coding: utf-8 -*- +# +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os + +import pytest +from units.compat.mock import call, patch, MagicMock + +# docker images quay.io/ansible/centos7-test-container --format '{{json .}}' +DOCKER_OUTPUT_MULTIPLE = """ +{"Containers":"N/A","CreatedAt":"2020-06-11 17:05:58 -0500 CDT","CreatedSince":"3 months ago","Digest":"\u003cnone\u003e","ID":"b0f914b26cc1","Repository":"quay.io/ansible/centos7-test-container","SharedSize":"N/A","Size":"556MB","Tag":"1.17.0","UniqueSize":"N/A","VirtualSize":"555.6MB"} +{"Containers":"N/A","CreatedAt":"2020-06-11 17:05:58 -0500 CDT","CreatedSince":"3 months ago","Digest":"\u003cnone\u003e","ID":"b0f914b26cc1","Repository":"quay.io/ansible/centos7-test-container","SharedSize":"N/A","Size":"556MB","Tag":"latest","UniqueSize":"N/A","VirtualSize":"555.6MB"} +{"Containers":"N/A","CreatedAt":"2019-04-01 19:59:39 -0500 CDT","CreatedSince":"18 months ago","Digest":"\u003cnone\u003e","ID":"dd3d10e03dd3","Repository":"quay.io/ansible/centos7-test-container","SharedSize":"N/A","Size":"678MB","Tag":"1.8.0","UniqueSize":"N/A","VirtualSize":"678MB"} +""".lstrip() # noqa: E501 + +PODMAN_OUTPUT = """ +[ + { + "id": "dd3d10e03dd3580de865560c3440c812a33fd7a1fca8ed8e4a1219ff3d809e3a", + "names": [ + "quay.io/ansible/centos7-test-container:1.8.0" + ], + "digest": "sha256:6e5d9c99aa558779715a80715e5cf0c227a4b59d95e6803c148290c5d0d9d352", + "created": "2019-04-02T00:59:39.234584184Z", + "size": 702761933 + }, + { + "id": "b0f914b26cc1088ab8705413c2f2cf247306ceeea51260d64c26894190d188bd", + "names": [ + "quay.io/ansible/centos7-test-container:latest" + ], + "digest": "sha256:d8431aa74f60f4ff0f1bd36bc9a227bbb2066330acd8bf25e29d8614ee99e39c", + "created": "2020-06-11T22:05:58.382459136Z", + "size": 578513505 + } +] +""".lstrip() + + +@pytest.fixture +def docker_images(): + from ansible_test._internal.docker_util import docker_images + return docker_images + + +@pytest.fixture +def ansible_test(ansible_test): + import ansible_test + return ansible_test + + +@pytest.fixture +def subprocess_error(): + from ansible_test._internal.util import SubprocessError + return SubprocessError + + +@pytest.mark.parametrize( + ('returned_items_count', 'patched_dc_stdout'), + ( + (3, (DOCKER_OUTPUT_MULTIPLE, '')), + (2, (PODMAN_OUTPUT, '')), + (0, ('', '')), + ), + ids=('docker JSONL', 'podman JSON sequence', 'empty output')) +def test_docker_images(docker_images, mocker, returned_items_count, patched_dc_stdout): + mocker.patch( + 'ansible_test._internal.docker_util.docker_command', + return_value=patched_dc_stdout) + ret = docker_images('', 'quay.io/ansible/centos7-test-container') + assert len(ret) == returned_items_count + + +def test_podman_fallback(ansible_test, docker_images, subprocess_error, mocker): + '''Test podman >2 && <2.2 fallback''' + + cmd = ['docker', 'images', 'quay.io/ansible/centos7-test-container', '--format', '{{json .}}'] + docker_command_results = [ + subprocess_error(cmd, status=1, stderr='function "json" not defined'), + (PODMAN_OUTPUT, ''), + ] + mocker.patch( + 'ansible_test._internal.docker_util.docker_command', + side_effect=docker_command_results) + + ret = docker_images('', 'quay.io/ansible/centos7-test-container') + calls = [ + call( + '', + ['images', 'quay.io/ansible/centos7-test-container', '--format', '{{json .}}'], + capture=True, + always=True), + call( + '', + ['images', 'quay.io/ansible/centos7-test-container', '--format', 'json'], + capture=True, + always=True), + ] + ansible_test._internal.docker_util.docker_command.assert_has_calls(calls) + assert len(ret) == 2 + + +def test_podman_no_such_image(ansible_test, docker_images, subprocess_error, mocker): + '''Test podman "no such image" error''' + + cmd = ['docker', 'images', 'quay.io/ansible/centos7-test-container', '--format', '{{json .}}'] + exc = subprocess_error(cmd, status=1, stderr='no such image'), + mocker.patch( + 'ansible_test._internal.docker_util.docker_command', + side_effect=exc) + ret = docker_images('', 'quay.io/ansible/centos7-test-container') + assert ret == [] |