dangerzone/tests/isolation_provider/test_container.py
Alex Pyrgiotis a1402d5b6b
Fix a Podman regression regarding Buildkit images
Loading an image built with Buildkit in Podman 3.4 messes up its name.
The tag somehow becomes the name of the loaded image.

We know that older Podman versions are not generally affected, since
Podman v3.0.1 on Debian Bullseye works properly. Also, Podman v4.0 is
not affected, so it makes sense to target only Podman v3.4 for a fix.

The fix is simple, tag the image properly based on the expected tag from
`share/image-id.txt` and delete the incorrect tag.

Refs containers/podman#16490
2025-03-20 17:17:40 +02:00

210 lines
6.4 KiB
Python

import os
import platform
import pytest
from pytest_mock import MockerFixture
from pytest_subprocess import FakeProcess
from dangerzone import container_utils, errors
from dangerzone.isolation_provider.container import Container
from dangerzone.isolation_provider.qubes import is_qubes_native_conversion
from dangerzone.util import get_resource_path
from .base import IsolationProviderTermination, IsolationProviderTest
# Run the tests in this module only if we can spawn containers.
if is_qubes_native_conversion():
pytest.skip("Qubes native conversion is enabled", allow_module_level=True)
elif os.environ.get("DUMMY_CONVERSION", False):
pytest.skip("Dummy conversion is enabled", allow_module_level=True)
@pytest.fixture
def provider() -> Container:
return Container()
class TestContainer(IsolationProviderTest):
def test_is_available_raises(self, provider: Container, fp: FakeProcess) -> None:
"""
NotAvailableContainerTechException should be raised when
the "podman image ls" command fails.
"""
fp.register_subprocess(
[container_utils.get_runtime(), "image", "ls"],
returncode=-1,
stderr="podman image ls logs",
)
with pytest.raises(errors.NotAvailableContainerTechException):
provider.is_available()
def test_is_available_works(self, provider: Container, fp: FakeProcess) -> None:
"""
No exception should be raised when the "podman image ls" can return properly.
"""
fp.register_subprocess(
[container_utils.get_runtime(), "image", "ls"],
)
provider.is_available()
def test_install_raise_if_image_cant_be_installed(
self, provider: Container, fp: FakeProcess
) -> None:
"""When an image installation fails, an exception should be raised"""
fp.register_subprocess(
[container_utils.get_runtime(), "image", "ls"],
)
# First check should return nothing.
fp.register_subprocess(
[
container_utils.get_runtime(),
"image",
"list",
"--format",
"{{ .Tag }}",
"dangerzone.rocks/dangerzone",
],
occurrences=2,
)
fp.register_subprocess(
[
container_utils.get_runtime(),
"load",
"-i",
get_resource_path("container.tar"),
],
returncode=-1,
)
with pytest.raises(errors.ImageInstallationException):
provider.install()
def test_install_raises_if_still_not_installed(
self, provider: Container, fp: FakeProcess
) -> None:
"""When an image keep being not installed, it should return False"""
fp.register_subprocess(
["podman", "version", "-f", "{{.Client.Version}}"],
stdout="4.0.0",
)
fp.register_subprocess(
[container_utils.get_runtime(), "image", "ls"],
)
# First check should return nothing.
fp.register_subprocess(
[
container_utils.get_runtime(),
"image",
"list",
"--format",
"{{ .Tag }}",
"dangerzone.rocks/dangerzone",
],
occurrences=2,
)
fp.register_subprocess(
[
container_utils.get_runtime(),
"load",
"-i",
get_resource_path("container.tar"),
],
)
with pytest.raises(errors.ImageNotPresentException):
provider.install()
@pytest.mark.skipif(
platform.system() not in ("Windows", "Darwin"),
reason="macOS and Windows specific",
)
def test_old_docker_desktop_version_is_detected(
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
) -> None:
fp.register_subprocess(
[
"docker",
"version",
"--format",
"{{.Server.Platform.Name}}",
],
stdout="Docker Desktop 1.0.0 (173100)",
)
mocker.patch(
"dangerzone.isolation_provider.container.MINIMUM_DOCKER_DESKTOP",
{"Darwin": "1.0.1", "Windows": "1.0.1"},
)
assert (False, "1.0.0") == provider.check_docker_desktop_version()
@pytest.mark.skipif(
platform.system() not in ("Windows", "Darwin"),
reason="macOS and Windows specific",
)
def test_up_to_date_docker_desktop_version_is_detected(
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
) -> None:
fp.register_subprocess(
[
"docker",
"version",
"--format",
"{{.Server.Platform.Name}}",
],
stdout="Docker Desktop 1.0.1 (173100)",
)
# Require version 1.0.1
mocker.patch(
"dangerzone.isolation_provider.container.MINIMUM_DOCKER_DESKTOP",
{"Darwin": "1.0.1", "Windows": "1.0.1"},
)
assert (True, "1.0.1") == provider.check_docker_desktop_version()
fp.register_subprocess(
[
"docker",
"version",
"--format",
"{{.Server.Platform.Name}}",
],
stdout="Docker Desktop 2.0.0 (173100)",
)
assert (True, "2.0.0") == provider.check_docker_desktop_version()
@pytest.mark.skipif(
platform.system() not in ("Windows", "Darwin"),
reason="macOS and Windows specific",
)
def test_docker_desktop_version_failure_returns_true(
self, mocker: MockerFixture, provider: Container, fp: FakeProcess
) -> None:
fp.register_subprocess(
[
"docker",
"version",
"--format",
"{{.Server.Platform.Name}}",
],
stderr="Oopsie",
returncode=1,
)
assert provider.check_docker_desktop_version() == (True, "")
@pytest.mark.skipif(
platform.system() != "Linux",
reason="Linux specific",
)
def test_linux_skips_desktop_version_check_returns_true(
self, provider: Container
) -> None:
assert (True, "") == provider.check_docker_desktop_version()
class TestContainerTermination(IsolationProviderTermination):
pass