]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
integration: bind mounting repository and the test
authorVasek Sraier <git@vakabus.cz>
Tue, 9 Mar 2021 10:03:07 +0000 (11:03 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 8 Apr 2022 14:17:51 +0000 (16:17 +0200)
manager/integration/README.md
manager/integration/runner.py
manager/integration/tests/dummy/Dockerfile
manager/integration/tests/dummy/run [moved from manager/integration/tests/dummy/test with 100% similarity]

index eb482434c82371592ebb01dd9beef21b00b916be..d1f81bcaf971c29ef38f23b814affcc237ed48e1 100644 (file)
@@ -12,15 +12,17 @@ Install Podman and configure it so that it can run in a rootless mode. The tool
 
 ## What is a test?
 
-A single test is a directory in `tests`. It has to contain `Dockerfile`. The container created by the `Dockerfile` has to have an executable called `/test` in its file system. The `Dockerfile` must be configured to execute systemd on container startup. The `/test` executable is then called manually by the testing tool.
+A single test is a directory in `tests`. It has to contain `Dockerfile`, which defines the used system. The `Dockerfile` must be configured to execute systemd on container startup.
 
-Exit code of the `/test` script determines the result of a test. 0 means test successfull, non-zero unsuccessful.
+The test directory is mounted to `/test`, the root of the git repository is mounted to `/repo`. Both are read-only mounts.
+
+The test starts with the execution of `/test/run` executable. Its exit code determines the result of a test. 0 means test successfull, non-zero unsuccessful.
 
 ## How does the integration tool work?
 
 The tool launches a Podman subprocess which exposes a HTTP API. This API is then used to control the containers.
 
-For each directory in `tests/`, the testing tool builds the container, starts it, exec's `/test` and observes its result. After that, it issues `systemctl poweroff` and waits until the container turns itself off.
+For each directory in `tests/`, the testing tool builds the container, starts it, exec's `/test/run` and observes its result. After that, it issues `systemctl poweroff` and waits until the container turns itself off.
 
 Because building the container is slow (even with Podman's caching), we skip it if it's not needed. The testing tool creates a `.contentshash` file within each test directory, which contains a hash of all content. The container is rebuilt only when the hash changes (or the file is missing).
 
index 3115f96fe82b3a293a6d71c43057213ed6d09023..87020206e38fc6f585721e0d352c52c39269d82a 100644 (file)
@@ -1,7 +1,7 @@
 import subprocess
 import signal
 import uuid
-from typing import Optional, List, BinaryIO
+from typing import Optional, List, BinaryIO, Dict
 import shutil
 import tarfile
 import os
@@ -11,7 +11,7 @@ import requests
 import hashlib
 
 from _hashlib import HASH as Hash
-from pathlib import Path
+from pathlib import Path, PurePath
 from typing import Union
 
 
@@ -143,10 +143,25 @@ class PodmanServiceManager:
         # create hashfile for future caching
         self._create_hashfile(context_dir, current_hash)
 
-    def _api_create_container(self, image: str) -> str:
+    def _api_create_container(
+        self, image: str, bind_mount_ro: Dict[PurePath, PurePath] = {}
+    ) -> str:
         response = requests.post(
             self._create_url("libpod/containers/create"),
-            json={"image": image, "remove": True, "systemd": "true"},
+            json={
+                "image": image,
+                "remove": True,
+                "systemd": "true",
+                "mounts": [
+                    {
+                        "destination": str(destination),
+                        "options": ["ro"],
+                        "source": str(source),
+                        "type": "bind",
+                    }
+                    for source, destination in bind_mount_ro.items()
+                ],
+            },
         )
         response.raise_for_status()
         return response.json()["Id"]
@@ -192,9 +207,11 @@ class PodmanServiceManager:
         )
         response.raise_for_status()
 
-    def start_temporary_and_wait(self, image: str, command: List[str]) -> int:
+    def start_temporary_and_wait(
+        self, image: str, command: List[str], bind_mount_ro: Dict[PurePath, PurePath] = {}
+    ) -> int:
         # start the container
-        container_id = self._api_create_container(image)
+        container_id = self._api_create_container(image, bind_mount_ro)
         self._api_start_container(container_id)
 
         # the container is booting, let's give it some time
@@ -222,9 +239,13 @@ class Colors:
     RESET = "\033[0m"
 
 
+def _get_git_root() -> PurePath:
+    result = subprocess.run("git rev-parse --show-toplevel", shell=True, capture_output=True)
+    return PurePath(str(result.stdout, encoding='utf8').strip())
+
 class TestRunner:
     _TEST_DIRECTORY = "tests"
-    _TEST_ENTRYPOINT = ["/test"]
+    _TEST_ENTRYPOINT = ["/test/run"]
 
     @staticmethod
     def _list_tests() -> List[Path]:
@@ -248,7 +269,12 @@ class TestRunner:
                 manager.build_image(test_path, image)
                 print("\tRunning...")
                 exit_code = manager.start_temporary_and_wait(
-                    image, TestRunner._TEST_ENTRYPOINT
+                    image,
+                    TestRunner._TEST_ENTRYPOINT,
+                    bind_mount_ro={
+                        _get_git_root(): PurePath('/repo'),
+                        test_path.absolute(): '/test'
+                    }
                 )
                 if exit_code == 0:
                     print(f"\t{Colors.GREEN}Test succeeded{Colors.RESET}")
index 6f6c583012409f22558057f3747fc9346afe0adc..05b0078389041a174df4ae6afe7764ed6ee3993e 100644 (file)
@@ -6,6 +6,4 @@ RUN useradd -m -s /bin/bash dev
 RUN echo "dev:password" | chpasswd
 RUN usermod -a -G sudo dev
 
-COPY test /test
-
 CMD ["/sbin/init"]