Skip to content

Commit

Permalink
tests: pull containers into local storage
Browse files Browse the repository at this point in the history
Ensure that the containers have been copied into local
storage for all test cases.

We need to explicitly pull the container into local containers
storage with the correct arch otherwise cross-arch building
fails. The helper function uses the host-arch as a fallback
when no target arch is provided.
  • Loading branch information
kingsleyzissou committed Sep 11, 2024
1 parent 4ce0ff2 commit b27789d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 26 deletions.
24 changes: 4 additions & 20 deletions test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
import os
import pathlib
import platform
import random
import re
import shutil
import string
import subprocess
import tempfile
import uuid
Expand Down Expand Up @@ -60,20 +58,7 @@ def image_type_fixture(shared_tmpdir, build_container, request, force_aws_upload
In the case an image is being built from a local container, the
function will build the required local container for the test.
"""
container_ref = request.param.container_ref

if request.param.local:
cont_tag = "localhost/cont-base-" + "".join(random.choices(string.digits, k=12))

# we are not cross-building local images (for now)
request.param.target_arch = ""

# copy the container into containers-storage
subprocess.check_call([
"skopeo", "copy",
f"docker://{container_ref}",
f"containers-storage:[overlay@/var/lib/containers/storage+/run/containers/storage]{cont_tag}"
])
testutil.pull_container(request.param.container_ref, request.param.target_arch)

with build_images(shared_tmpdir, build_container, request, force_aws_upload) as build_results:
yield build_results[0]
Expand All @@ -85,6 +70,8 @@ def images_fixture(shared_tmpdir, build_container, request, force_aws_upload):
Build one or more images inside the passed build_container and return an
ImageBuildResult array with the resulting image path and user/password
"""
testutil.pull_container(request.param.container_ref, request.param.target_arch)

with build_images(shared_tmpdir, build_container, request, force_aws_upload) as build_results:
yield build_results

Expand Down Expand Up @@ -249,12 +236,9 @@ def build_images(shared_tmpdir, build_container, request, force_aws_upload):
"-v", f"{config_json_path}:/config.json:ro",
"-v", f"{output_path}:/output",
"-v", "/var/tmp/osbuild-test-store:/store", # share the cache between builds
"-v", "/var/lib/containers/storage:/var/lib/containers/storage", # mount the host's containers storage
]

# we need to mount the host's container store
if tc.local:
cmd.extend(["-v", "/var/lib/containers/storage:/var/lib/containers/storage"])

cmd.extend([
*creds_args,
build_container,
Expand Down
18 changes: 17 additions & 1 deletion test/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def find_image_size_from(manifest_str):

@pytest.mark.parametrize("tc", gen_testcases("manifest"))
def test_manifest_smoke(build_container, tc):
testutil.pull_container(tc.container_ref, tc.target_arch)

output = subprocess.check_output([
*testutil.podman_run_common,
build_container,
Expand All @@ -50,6 +52,8 @@ def test_manifest_smoke(build_container, tc):

@pytest.mark.parametrize("tc", gen_testcases("anaconda-iso"))
def test_iso_manifest_smoke(build_container, tc):
testutil.pull_container(tc.container_ref, tc.target_arch)

output = subprocess.check_output([
*testutil.podman_run_common,
build_container,
Expand Down Expand Up @@ -158,6 +162,7 @@ def find_rootfs_type_from(manifest_str):
@pytest.mark.parametrize("tc", gen_testcases("default-rootfs"))
def test_manifest_rootfs_respected(build_container, tc):
# TODO: derive container and fake "bootc install print-configuration"?
testutil.pull_container(tc.container_ref)
output = subprocess.check_output([
*testutil.podman_run_common,
build_container,
Expand Down Expand Up @@ -197,6 +202,7 @@ def find_user_stage_from(manifest_str):
def test_manifest_user_customizations_toml(tmp_path, build_container):
# no need to parameterize this test, toml is the same for all containers
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

config_toml_path = tmp_path / "config.toml"
config_toml_path.write_text(textwrap.dedent("""\
Expand Down Expand Up @@ -224,6 +230,7 @@ def test_manifest_user_customizations_toml(tmp_path, build_container):

def test_manifest_installer_customizations(tmp_path, build_container):
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

config_toml_path = tmp_path / "config.toml"
config_toml_path.write_text(textwrap.dedent("""\
Expand Down Expand Up @@ -257,6 +264,7 @@ def test_manifest_installer_customizations(tmp_path, build_container):
def test_mount_ostree_error(tmpdir_factory, build_container):
# no need to parameterize this test, toml is the same for all containers
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

cfg = {
"blueprint": {
Expand Down Expand Up @@ -305,6 +313,7 @@ def test_mount_ostree_error(tmpdir_factory, build_container):
)
def test_manifest_checks_build_container_is_bootc(build_container, container_ref, should_error, expected_error):
def check_image_ref():
testutil.pull_container(container_ref)
subprocess.check_output([
*testutil.podman_run_common,
build_container,
Expand All @@ -321,6 +330,8 @@ def check_image_ref():

@pytest.mark.parametrize("tc", gen_testcases("target-arch-smoke"))
def test_manifest_target_arch_smoke(build_container, tc):
testutil.pull_container(tc.container_ref, tc.target_arch)

# TODO: actually build an image too
output = subprocess.check_output([
*testutil.podman_run_common,
Expand Down Expand Up @@ -373,6 +384,8 @@ def test_manifest_anaconda_module_customizations(tmpdir_factory, build_container
config_json_path = output_path / "config.json"
config_json_path.write_text(json.dumps(cfg), encoding="utf-8")

testutil.pull_container(tc.container_ref, tc.target_arch)

output = subprocess.check_output([
*testutil.podman_run_common,
"-v", f"{output_path}:/output",
Expand Down Expand Up @@ -411,6 +424,7 @@ def find_fstab_stage_from(manifest_str):
])
def test_manifest_fs_customizations(tmp_path, build_container, fscustomizations, rootfs):
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

config = {
"customizations": {
Expand Down Expand Up @@ -467,7 +481,9 @@ def assert_fs_customizations(customizations, fstype, manifest):
({}, "btrfs"),
])
def test_manifest_fs_customizations_xarch(tmp_path, build_container, fscustomizations, rootfs):
target_arch = "aarch64"
container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref, target_arch)

config = {
"customizations": {
Expand All @@ -483,7 +499,7 @@ def test_manifest_fs_customizations_xarch(tmp_path, build_container, fscustomiza
"--entrypoint=/usr/bin/bootc-image-builder",
build_container,
f"--rootfs={rootfs}",
"--target-arch=aarch64",
f"--target-arch={target_arch}",
"manifest", f"{container_ref}",
])

Expand Down
26 changes: 21 additions & 5 deletions test/test_opts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import subprocess

import pytest
import testutil
# pylint: disable=unused-import
from containerbuild import build_container_fixture, build_fake_container_fixture

Expand All @@ -25,14 +26,17 @@ def test_bib_chown_opts(tmp_path, container_storage, build_fake_container, chown
output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)

container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

subprocess.check_call([
"podman", "run", "--rm",
"--privileged",
"--security-opt", "label=type:unconfined_t",
"-v", f"{container_storage}:/var/lib/containers/storage",
"-v", f"{output_path}:/output",
build_fake_container,
"quay.io/centos-bootc/centos-bootc:stream9",
container_ref,
] + chown_opt)
expected_output_disk = output_path / "qcow2/disk.qcow2"
for p in output_path, expected_output_disk:
Expand All @@ -52,6 +56,9 @@ def test_opts_arch_is_same_arch_is_fine(tmp_path, build_fake_container, target_a
output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)

container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

res = subprocess.run([
"podman", "run", "--rm",
"--privileged",
Expand All @@ -60,7 +67,7 @@ def test_opts_arch_is_same_arch_is_fine(tmp_path, build_fake_container, target_a
"-v", f"{output_path}:/output",
build_fake_container,
"--type=iso",
"quay.io/centos-bootc/centos-bootc:stream9",
container_ref,
] + target_arch_opt, check=False, capture_output=True, text=True)
if expected_err == "":
assert res.returncode == 0
Expand All @@ -80,14 +87,17 @@ def test_bib_tls_opts(tmp_path, container_storage, build_fake_container, tls_opt
output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)

container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

subprocess.check_call([
"podman", "run", "--rm",
"--privileged",
"--security-opt", "label=type:unconfined_t",
"-v", f"{container_storage}:/var/lib/containers/storage",
"-v", f"{output_path}:/output",
build_fake_container,
"quay.io/centos-bootc/centos-bootc:stream9"
container_ref,
] + tls_opt)
podman_log = output_path / "podman.log"
assert expected_cmdline in podman_log.read_text()
Expand All @@ -98,6 +108,9 @@ def test_bib_log_level_smoke(tmp_path, container_storage, build_fake_container,
output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)

container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

log_debug = ["--log-level", "debug"] if with_debug else []
res = subprocess.run([
"podman", "run", "--rm",
Expand All @@ -107,7 +120,7 @@ def test_bib_log_level_smoke(tmp_path, container_storage, build_fake_container,
"-v", f"{output_path}:/output",
build_fake_container,
*log_debug,
"quay.io/centos-bootc/centos-bootc:stream9"
container_ref,
], check=True, capture_output=True, text=True)
assert ('level=debug' in res.stderr) == with_debug

Expand Down Expand Up @@ -176,13 +189,16 @@ def test_bib_no_outside_container_warning_in_container(tmp_path, container_stora
output_path = tmp_path / "output"
output_path.mkdir(exist_ok=True)

container_ref = "quay.io/centos-bootc/centos-bootc:stream9"
testutil.pull_container(container_ref)

res = subprocess.run([
"podman", "run", "--rm",
"--privileged",
"--security-opt", "label=type:unconfined_t",
"-v", f"{container_storage}:/var/lib/containers/storage",
"-v", f"{output_path}:/output",
build_fake_container,
"quay.io/centos-bootc/centos-bootc:stream9"
container_ref,
], check=True, capture_output=True, text=True)
assert "running outside a container" not in res.stderr
14 changes: 14 additions & 0 deletions test/testutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ def create_filesystem_customizations(rootfs: str):
]


def pull_container(container_ref, target_arch=""):
if target_arch == "":
target_arch = platform.machine()

if target_arch not in ["x86_64", "amd64", "aarch64", "arm64", "s390x", "ppc64le"]:
raise RuntimeError(f"unknown host arch: {target_arch}")

subprocess.run([
"podman", "pull",
"--arch", target_arch,
container_ref,
], check=True)


# podman_run_common has the common prefix for the podman run invocations
podman_run_common = [
"podman", "run", "--rm",
Expand Down

0 comments on commit b27789d

Please sign in to comment.