Skip to content

Commit

Permalink
stages(container-deploy): add new exclude option
Browse files Browse the repository at this point in the history
This commit adds a new `exclude` option to the container-deploy
stage. This is needed when we deploy `bootc` containers that are
used for the buildroot. Here the  `/sysroot` dir needs to be
excluded because it has conflicting selinux definitions for
files there and in the normal "root" dir.

See also osbuild/bootc-image-builder#138
  • Loading branch information
mvo5 committed Jan 24, 2024
1 parent d883515 commit c53c6ee
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 6 deletions.
22 changes: 17 additions & 5 deletions stages/org.osbuild.container-deploy
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ SCHEMA_2 = r"""
}
},
"options": {
"additionalProperties": false
"additionalProperties": false,
"properties": {
"exclude": {
"type": "array",
"description": "Exclude paths from the deployment",
"minItems": 1,
"items": {
"type": "string"
}
}
}
}
"""

Expand All @@ -50,7 +60,7 @@ def mount_container(image_tag):
)


def main(inputs, output):
def main(inputs, tree, options):
images = containers.parse_containers_input(inputs)
assert len(images) == 1
image = list(images.values())[0]
Expand All @@ -71,10 +81,12 @@ def main(inputs, output):
check=True,
)
with mount_container(image_tag) as img:
subprocess.run(["cp", "-a", f"{img}/.", f"{output}/"], check=True)

subprocess.run(["cp", "-a", f"{img}/.", f"{tree}/"], check=True)
# postprocess the tree, would be nicer to filter before already
for exclude in options.get("exclude", []):
subprocess.run(["rm", "-rf", f"{tree}/{exclude}"], check=True)

if __name__ == "__main__":
args = osbuild.api.arguments()
r = main(args["inputs"], args["tree"])
r = main(args["inputs"], args["tree"], args["options"])
sys.exit(r)
58 changes: 57 additions & 1 deletion stages/test/test_container_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,67 @@ def test_container_deploy_integration(tmp_path):
},
}
output_dir = tmp_path / "output"
options = {}

with patch("os.makedirs", wraps=os.makedirs) as mocked_makedirs:
stage.main(inputs, output_dir)
stage.main(inputs, output_dir, options)

assert output_dir.exists()
assert (output_dir / "file1").read_bytes() == b"file1 from final layer"

assert mocked_makedirs.call_args_list == [call("/var/tmp", mode=0o1777, exist_ok=True)]


@pytest.mark.skipif(os.getuid() != 0, reason="needs root")
@pytest.mark.skipif(not has_executable("podman"), reason="no podman executable")
def test_container_deploy_exclude(tmp_path):
stage_path = os.path.join(os.path.dirname(__file__), "../org.osbuild.container-deploy")
stage = import_module_from_path("stage", stage_path)

base_tag = "cont-base-" + "".join(random.choices(string.digits, k=12))
make_container(tmp_path, base_tag, {
"file1": "file1 content",
"file2": "file2 content",
"dir1/file3": "dir1/file3 content",
"dir2/file4": "dir2/file4 content",
})
# export for the container-deploy stage
fake_container_dst = tmp_path / "fake-container"
subprocess.check_call([
"podman", "save",
"--format=oci-archive",
f"--output={fake_container_dst}",
base_tag,
])
# and remove from podman
subprocess.check_call(["podman", "rmi", base_tag])

inputs = {
"images": {
# seems to be unused with fake_container_path?
"path": fake_container_dst,
"data": {
"archives": {
fake_container_dst: {
"format": "oci-archive",
"name": base_tag,
},
},
},
},
}
options = {
"exclude": [
"file2",
"dir2/",
],
}
output_dir = tmp_path / "output"

stage.main(inputs, output_dir, options)
assert output_dir.exists()
assert (output_dir / "file1").read_bytes() == b"file1 content"
assert not (output_dir / "file2").exists()
assert (output_dir / "dir1/file3").read_bytes() == b"dir1/file3 content"
assert not (output_dir / "dir2/file4").exists()
assert not (output_dir / "dir2").exists()

0 comments on commit c53c6ee

Please sign in to comment.