From b7825c9022f2dc32152b596cec7eb66f8970bd26 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Fri, 20 Sep 2024 04:34:14 -0700 Subject: [PATCH] Add test for ansible-builder (#377) Change the server in container url to 0.0.0.0, which should be safer long-term and resolve some odd errors found with podman related to pasta. Log the container run command for easier troubleshooting locally outside the test suite. Add an execution environment build test Note the failure in this test run: opening file /sys/fs/cgroup/cgroup.subtree_control for writing: Read-only file system https://github.com/ansible/ansible-dev-tools/actions/runs/10930266208/job/30342982168?pr=377 This is why unmask=/sys/fs/cgroup is added after the initial addition of the EE test which works for podman. For docker based on: moby/moby#42275 (comment) --privileged was added (not ideal, but few options) On macOS/intel/podman desktop the following errors were found: Error: crun: mknod /dev/null: Operation not permitted: OCI permission denied the following was added to resolve this error: --cap-add=mknod (docker gets this by default) this allowed all tests to pass on macOS/intel/podman desktop 277.32s call tests/integration/test_container.py::test_builder 6.21s call tests/integration/test_container.py::test_nav_playbook 4.99s call tests/integration/test_container.py::test_nav_collections 3.56s call tests/integration/test_container.py::test_navigator_simple_c_in_c 3.18s call tests/integration/test_container.py::test_nav_collection 2.77s call tests/integration/test_container.py::test_navigator_simple 2.58s call tests/integration/test_container.py::test_podman 1.23s call tests/integration/test_container.py::test_nav_images 1.15s setup tests/integration/test_container.py::test_nav_collections 0.78s setup tests/integration/test_container.py::test_nav_playbook ======================================= 34 passed, 1 warning in 310.65s (0:05:10) ======================================= Additional changes necessary for Windows user include the addition of "--cap-add=NET_ADMIN", to avoid bpf query: Operation failed errors when building an EE --------- Co-authored-by: Brad Thornton --- .config/dictionary.txt | 1 + .devcontainer/devcontainer.json | 9 +-------- .devcontainer/docker/devcontainer.json | 9 +-------- .devcontainer/podman/devcontainer.json | 4 ++++ tests/conftest.py | 17 ++++++++++------ .../test_container/execution-environment.yml | 20 +++++++++++++++++++ tests/integration/test_container.py | 18 +++++++++++++++++ 7 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 tests/fixtures/integration/test_container/execution-environment.yml diff --git a/.config/dictionary.txt b/.config/dictionary.txt index 5441ec4..e128d2f 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -18,6 +18,7 @@ endgroup gunicorn libera microdnf +mknod modifyitems netcommon pkgmgr diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bb9355e..0f980d7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,16 +3,9 @@ "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", "containerUser": "root", "runArgs": [ - "--security-opt", - "seccomp=unconfined", - "--security-opt", - "label=disable", - "--cap-add=SYS_ADMIN", - "--cap-add=SYS_RESOURCE", + "--privileged", "--device", "/dev/fuse", - "--security-opt", - "apparmor=unconfined", "--hostname=ansible-dev-container" ], "updateRemoteUserUID": true, diff --git a/.devcontainer/docker/devcontainer.json b/.devcontainer/docker/devcontainer.json index 60648f1..55c379c 100644 --- a/.devcontainer/docker/devcontainer.json +++ b/.devcontainer/docker/devcontainer.json @@ -3,16 +3,9 @@ "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", "containerUser": "root", "runArgs": [ - "--security-opt", - "seccomp=unconfined", - "--security-opt", - "label=disable", - "--cap-add=SYS_ADMIN", - "--cap-add=SYS_RESOURCE", + "--privileged", "--device", "/dev/fuse", - "--security-opt", - "apparmor=unconfined", "--hostname=ansible-dev-container" ], "updateRemoteUserUID": true, diff --git a/.devcontainer/podman/devcontainer.json b/.devcontainer/podman/devcontainer.json index 8b198f0..7d1ef36 100644 --- a/.devcontainer/podman/devcontainer.json +++ b/.devcontainer/podman/devcontainer.json @@ -3,6 +3,8 @@ "image": "ghcr.io/ansible/community-ansible-dev-tools:latest", "containerUser": "root", "runArgs": [ + "--cap-add=CAP_MKNOD", + "--cap-add=NET_ADMIN", "--cap-add=SYS_ADMIN", "--cap-add=SYS_RESOURCE", "--device", @@ -13,6 +15,8 @@ "label=disable", "--security-opt", "apparmor=unconfined", + "--security-opt", + "unmask=/sys/fs/cgroup", "--userns=host", "--hostname=ansible-dev-container" ], diff --git a/tests/conftest.py b/tests/conftest.py index 48335dc..a47e7e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -202,7 +202,7 @@ def server_in_container_url() -> str: Returns: str: The server URL. """ - return "http://localhost:8001" + return "http://0.0.0.0:8001" def pytest_sessionstart(session: pytest.Session) -> None: @@ -245,24 +245,28 @@ def pytest_sessionfinish(session: pytest.Session) -> None: BASE_CMD = """{container_engine} run -d --rm - --cap-add=SYS_ADMIN - --cap-add=SYS_RESOURCE --device "/dev/fuse" -e NO_COLOR=1 --hostname=ansible-dev-container --name={container_name} -p 8001:8001 - --security-opt "apparmor=unconfined" - --security-opt "label=disable" - --security-opt "seccomp=unconfined" -v $PWD:/workdir """ PODMAN_CMD = """ --user=root + --cap-add=CAP_MKNOD + --cap-add=NET_ADMIN + --cap-add=SYS_ADMIN + --cap-add=SYS_RESOURCE + --security-opt "apparmor=unconfined" + --security-opt "label=disable" + --security-opt "seccomp=unconfined" + --security-opt=unmask=/sys/fs/cgroup --userns=host """ DOCKER_CMD = """ --user=root +--privileged """ END = """ {image_name} @@ -307,6 +311,7 @@ def _start_container() -> None: container_name=INFRASTRUCTURE.container_name, image_name=INFRASTRUCTURE.image_name, ) + warnings.warn("Running: " + cmd, stacklevel=0) try: subprocess.run(cmd, check=True, capture_output=True, shell=True, text=True) except subprocess.CalledProcessError as exc: diff --git a/tests/fixtures/integration/test_container/execution-environment.yml b/tests/fixtures/integration/test_container/execution-environment.yml new file mode 100644 index 0000000..34082b2 --- /dev/null +++ b/tests/fixtures/integration/test_container/execution-environment.yml @@ -0,0 +1,20 @@ +--- +version: 3 + +images: + base_image: + name: quay.io/fedora/fedora-minimal:40 + +dependencies: + ansible_runner: + package_pip: ansible-runner + + ansible_core: + package_pip: ansible-core + +options: + package_manager_path: /usr/bin/microdnf + +additional_build_steps: + prepend_base: + - RUN $PKGMGR -y install python3-devel diff --git a/tests/integration/test_container.py b/tests/integration/test_container.py index 22cf9e0..6e52b8d 100644 --- a/tests/integration/test_container.py +++ b/tests/integration/test_container.py @@ -279,3 +279,21 @@ def test_nav_collection(container_tmux: ContainerTmux, tmp_path: Path) -> None: ) stdout = container_tmux.send_and_wait(cmd=cmd, wait_for=":help help", timeout=10) assert any(f"{namespace}.{name}" in line for line in stdout) + + +@pytest.mark.container() +def test_builder( + exec_container: Callable[[str], subprocess.CompletedProcess[str]], + test_fixture_dir_container: Path, + tmp_path: Path, +) -> None: + """Test building an execution environment with ansible-builder. + + Args: + exec_container: The container executor. + test_fixture_dir_container: The test fixture directory. + tmp_path: The temporary directory. + """ + ee_file = test_fixture_dir_container / "execution-environment.yml" + result = exec_container(f"ansible-builder build -f {ee_file} -c {tmp_path}") + assert "Complete!" in result.stdout