From a11772fe06727ce4a47ff774c83ad89389122302 Mon Sep 17 00:00:00 2001 From: "David H. Irving" Date: Wed, 15 Nov 2023 13:22:39 -0700 Subject: [PATCH] Add butler server docker smoke test --- .github/workflows/docker.yaml | 24 +++++++- pyproject.toml | 3 + tests_integration/test_docker_container.py | 67 ++++++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests_integration/test_docker_container.py diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 81c019fae1..5677c4fe2c 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -47,11 +47,29 @@ jobs: # figure out version number fetch-depth: 0 - - - uses: lsst-sqre/build-and-push-to-ghcr@v1 + - uses: lsst-sqre/build-and-push-to-ghcr@tickets/DM-41568 id: build with: image: ${{ github.repository }} github_token: ${{ secrets.GITHUB_TOKEN }} - - run: echo Pushed ghcr.io/${{ github.repository }}:${{ steps.build.outputs.tag }} + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade setuptools wheel build + pip install -r requirements.txt + pip install testcontainers + + - name: Install Butler client + run: | + pip install -v --no-deps -e . + + - name: Run smoke test + run: | + export BUTLER_SERVER_DOCKER_IMAGE=${{ steps.build.outputs.fully_qualified_image_digest }} + python tests_integration/test_docker_container.py diff --git a/pyproject.toml b/pyproject.toml index 3a1e9417b3..11c075bd79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -132,6 +132,9 @@ write_to = "python/lsst/daf/butler/version.py" # The matplotlib test may not release font files. # Some unit tests open registry database in setUpClass. open_files_ignore = ["*.ttf", "gen3.sqlite3"] +# These require additional environment setup that isn't available during +# normal unit test runs +addopts = "--ignore=tests_integration" [tool.pydocstyle] convention = "numpy" diff --git a/tests_integration/test_docker_container.py b/tests_integration/test_docker_container.py new file mode 100644 index 0000000000..cf5804aa69 --- /dev/null +++ b/tests_integration/test_docker_container.py @@ -0,0 +1,67 @@ +import contextlib +import os +import tempfile +import unittest + +from lsst.daf.butler import Butler +from lsst.daf.butler.tests.utils import MetricTestRepo +from testcontainers.core.container import DockerContainer + +TESTDIR = os.path.abspath(os.path.dirname(__file__)) + + +@contextlib.contextmanager +def _run_server_docker(): + with tempfile.TemporaryDirectory() as temp_dir: + # Ensure the repository directory will be readable inside the container + os.chmod(temp_dir, 0o755) + + MetricTestRepo( + root=temp_dir, configFile=os.path.join(TESTDIR, "../tests", "config/basic/butler.yaml") + ) + + port = 8080 + butler_root = "/butler_root" + docker_image = os.getenv("BUTLER_SERVER_DOCKER_IMAGE") + if not docker_image: + raise Exception("BUTLER_SERVER_DOCKER_IMAGE must be set") + container = ( + DockerContainer(docker_image) + .with_exposed_ports(port) + .with_env("BUTLER_SERVER_CONFIG_URI", butler_root) + .with_volume_mapping(temp_dir, butler_root, "rw") + ) + + with container: + server_host = container.get_container_host_ip() + server_port = container.get_exposed_port(port) + server_url = f"http://{server_host}:{server_port}/api/butler" + try: + yield server_url + finally: + (stdout, stderr) = container.get_logs() + if stdout: + print("STDOUT:") + print(stdout.decode()) + if stderr: + print("STDERR:") + print(stderr.decode()) + + +class ButlerDockerTestCase(unittest.TestCase): + """Simple smoke test to ensure the server can start up and respond to + requests + """ + + @classmethod + def setUpClass(cls): + cls.server_uri = cls.enterClassContext(_run_server_docker()) + + def test_get_dataset_type(self): + butler = Butler(self.server_uri) + dataset_type = butler.get_dataset_type("test_metric_comp") + self.assertEqual(dataset_type.name, "test_metric_comp") + + +if __name__ == "__main__": + unittest.main()