Skip to content

fix: Podman compatibility and testing #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
79bd559
Handle empty strings and repo urls in assertions
angela-ko Apr 29, 2025
4ab50b3
Handle more strings
heitorPB Apr 30, 2025
6e0eb83
refactor logic to get an image
heitorPB Apr 30, 2025
265ed01
Handle image_name with URL
heitorPB Apr 30, 2025
cbf1484
Change to any
angela-ko Apr 30, 2025
e43a573
Change image exists
angela-ko Apr 30, 2025
eec02a7
test: skip tesseract_serve_ports with range on Podman
heitorPB Apr 30, 2025
18adba4
ci: run all E2E tests with Podman
heitorPB Apr 30, 2025
ee16afe
Add proper substring matching for image names
angela-ko Apr 30, 2025
04fa690
Podman typeguard
angela-ko Apr 30, 2025
479d9e1
ci: display status of podman socket for debugging
heitorPB May 2, 2025
507f6ec
Docker-py does not support partial string matching
heitorPB Apr 30, 2025
5648db6
ci(tests): test podman setup
heitorPB May 5, 2025
6136e43
Runs on multiple Ubuntus
heitorPB May 5, 2025
4bd8249
ci(test-podman): fix command to run `tesseract`
heitorPB May 5, 2025
73910ba
Fix the fixed command to build the images
heitorPB May 5, 2025
fc03af6
ci(tests): use Ubuntu24 for Podman tests
heitorPB May 5, 2025
a9eabc3
ci(tests): refactor to use a matrix for Podman
heitorPB May 6, 2025
3d4024d
use curly braces?
heitorPB May 6, 2025
b497733
Add spaces?
heitorPB May 6, 2025
dc0496c
- -> _
heitorPB May 6, 2025
dd43c07
Merge branch 'main' into ako/podman_url
heitorPB May 6, 2025
605d82e
No more braces; use single quotes
heitorPB May 6, 2025
28697f1
Try running Podman tests on all tessies
heitorPB May 6, 2025
d002512
Test all unit tessies with Podman
heitorPB May 6, 2025
f5d4000
Run base E2E + vectoradd_jax tests with Podman
heitorPB May 6, 2025
5564ef5
Add ubuntu 24 to runs on
angela-ko May 6, 2025
a449c25
Clear up some disk space
heitorPB May 6, 2025
d899c23
ci(tests): replace docker_engine -> docker-engine
heitorPB May 7, 2025
3fdd90e
ci(tests): use Ubuntu 24.04 to run E2E tests
heitorPB May 7, 2025
365cba6
refactor(sdk): better type hint for DockerException
heitorPB May 7, 2025
451e705
Make method private
heitorPB May 7, 2025
c822fba
Readd check for image name in image tags
heitorPB May 7, 2025
a6cf5f4
Revert "Readd check for image name in image tags"
heitorPB May 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,24 +164,37 @@ jobs:

strategy:
matrix:
os: [ubuntu-22.04]
os: [ubuntu-24.04]
python-version: ["3.12"]

arch: ["x64"]
docker-engine: ["docker"]

unit-tesseract: ${{ fromJson(needs.get-e2e-matrix.outputs.matrix) }}

include:
# Test on arm to ensure compatibility with Apple M1 chips
# (OSX runners don't have access to Docker so we use Linux ARM runners instead)
- os: "ubuntu-22.04"
- os: "ubuntu-24.04"
python-version: "3.12"
arch: "arm"
docker-engine: "docker"
unit-tesseract: "base"
# Run tests using Podman
- os: "ubuntu-24.04"
python-version: "3.12"
arch: "x64"
docker-engine: "podman"
unit-tesseract: "base"
- os: "ubuntu-24.04"
python-version: "3.12"
arch: "x64"
docker-engine: "podman"
unit-tesseract: "vectoradd_jax"

fail-fast: false

runs-on: ${{ matrix.arch == 'x64' && matrix.os == 'ubuntu-22.04' && 'ubuntu-22.04' || matrix.arch == 'arm' && matrix.os == 'ubuntu-22.04' && 'linux-arm64-ubuntu2204' }}
runs-on: ${{ matrix.arch == 'x64' && matrix.os == 'ubuntu-24.04' && 'ubuntu-24.04' || matrix.arch == 'arm' && matrix.os == 'ubuntu-24.04' && 'linux-arm64-ubuntu2404' || matrix.arch == 'x64' && matrix.os == 'ubuntu-24.04' && 'ubuntu-24.04'}}

defaults:
run:
Expand Down Expand Up @@ -209,8 +222,27 @@ jobs:
run: |
uv sync --extra dev --frozen

- name: Set up Podman
if: matrix.docker-engine == 'podman'
run: |
systemctl start --user podman.socket
systemctl status --user podman.socket

podman --version

export DOCKER_HOST=unix:///run/user/1001/podman/podman.sock
echo "DOCKER_HOST=${DOCKER_HOST}" >> $GITHUB_ENV

- name: Free some disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \
/usr/local/share/powershell \
/usr/share/swift /usr/local/.ghcup /usr/lib/jvm
Comment on lines +236 to +240
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels icky to me (but ok if we have no better solution).

Are we sure that cleanup works as expected? Why do we suddenly run out of disk space?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels icky to me

Why?

Are we sure that cleanup works as expected?

It does. I didn't check how much space it clears, but it is a few GB. This solves the issue of one of the tests erroring with "no space left on device" when unpacking an image.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the Docker cleanup we run after each test.

Feels icky because we'll have the same situation again after we add 5 more tests :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the Docker cleanup we run after each test.

Mostly. I just noticed I have a unit_vectoradd:latest after running the E2E tests locally, so maybe there's some cleanup missing?


- name: Run test suite
run: |
env | grep DOCKER_HOST || true

Comment on lines +244 to +245
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug artifact

if [ "${{ matrix.unit-tesseract }}" == "base" ]; then
uv run --no-sync pytest \
--always-run-endtoend \
Expand Down
46 changes: 40 additions & 6 deletions tesseract_core/sdk/docker_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,48 @@ def from_dict(cls, json_dict: dict) -> "Image":
class Images:
"""Namespace for functions to interface with Tesseract docker images."""

@staticmethod
def _tag_exists(image_name: str, tags: list_) -> bool:
"""Helper function to check if image name exists in the list of tags.

Specially handling has to be done to achieve unfuzzy substring matching, i.e.
if image tag is foo/bar/image, we need to return true for foo/bar/image, bar/image,
and image, but not ar/image.

There is no equivalent in docker-py.

Params:
image_name: The image name to check.
tags: The list of tags to check against.

Returns:
True if the image name exists in the list of tags, False otherwise.
"""
if ":" not in image_name:
image_name += ":latest"

image_name_parts = image_name.strip("/").split("/")
for tag in tags:
tag_parts = tag.strip("/").split("/")
# Check if the last parts of the tag matches the subportion that image name specifies
if tag_parts[-len(image_name_parts) :] == image_name_parts:
return True
return False

@staticmethod
def get(image_id_or_name: str | bytes, tesseract_only: bool = True) -> Image:
"""Returns the metadata for a specific image.

In docker-py, there is no substring matching and the image name is the
last tag in the list of tags, so if an image has multiple tags, only
one of the tags would be able to find the image.

However, in podman, this is not the case. Podman has substring matching
by "/" segments to handle repository urls and returns images even if
partial name is specified, or if image has multiple tags.

We chose to support podman's largest string matching functionality here.

Params:
image_id_or_name: The image name or id to get.
tesseract_only: If True, only retrieves Tesseract images.
Expand Down Expand Up @@ -77,11 +115,7 @@ def is_image_id(s: str) -> bool:
image_obj.id == image_id_or_name
or image_obj.short_id == image_id_or_name
or image_id_or_name in image_obj.tags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove? (should be covered by tag_exists)

or (
any(
tag.split("/")[-1] == image_id_or_name for tag in image_obj.tags
)
)
or Images._tag_exists(image_id_or_name, image_obj.tags)
):
return image_obj

Expand Down Expand Up @@ -711,7 +745,7 @@ class DockerException(Exception):
class BuildError(DockerException):
"""Raised when a build fails."""

def __init__(self, build_log: str) -> None:
def __init__(self, build_log: list_[str]) -> None:
self.build_log = build_log


Expand Down
5 changes: 3 additions & 2 deletions tests/endtoend_tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def print_debug_info(result):


def build_tesseract(
sourcedir, image_name, config_override=None, tag=None, build_retries=3
client, sourcedir, image_name, config_override=None, tag=None, build_retries=3
):
cli_runner = CliRunner(mix_stderr=False)

Expand Down Expand Up @@ -87,6 +87,7 @@ def build_tesseract(
assert result.exit_code == 0, result.exception

image_tags = json.loads(result.stdout.strip())
assert image_name in image_tags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was replaced by tag_exists(image_name, image_tags) that parses it correctly: foo/bar in repo/foo/bar should be true, but foo/bar in blafoo/bar should not.


assert client.images._tag_exists(image_name, image_tags)

return image_tags[0]
36 changes: 29 additions & 7 deletions tests/endtoend_tests/test_docker_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

"""End to end tests for docker cli wrapper."""

import os
import subprocess
import textwrap
from contextlib import closing
Expand Down Expand Up @@ -52,7 +53,7 @@ def test_get_image(docker_client, docker_client_built_image_name, docker_py_clie
# Get the image
image = docker_client.images.get(docker_client_built_image_name)
assert image is not None
assert docker_client_built_image_name in image.tags
assert docker_client.images._tag_exists(docker_client_built_image_name, image.tags)

docker_py_image = docker_py_client.images.get(docker_client_built_image_name)
assert docker_py_image is not None
Expand Down Expand Up @@ -100,7 +101,7 @@ def test_get_image(docker_client, docker_client_built_image_name, docker_py_clie
assert docker_py_image_list is not None
# Check that every image in image_list is also in docker_py_image_list
for image in image_list:
assert image.id in [img.id for img in docker_py_image_list]
assert image.id in [img.id for img in docker_py_image_list if img]


def test_create_image(
Expand All @@ -120,7 +121,9 @@ def test_create_image(
try:
image = docker_client.images.get(docker_client_built_image_name)
assert image is not None
assert docker_client_built_image_name in image.tags
assert docker_client.images._tag_exists(
docker_client_built_image_name, image.tags
)

image_id_obj = docker_client.images.get(image.id)
image_short_id_obj = docker_client.images.get(image.short_id)
Expand All @@ -138,7 +141,7 @@ def test_create_image(
image1 = docker_client.images.get(image1_name)
image1_name = image1_name + ":latest"
assert image1 is not None
assert image1_name in image1.tags
assert docker_client.images._tag_exists(image1_name, image1.tags)
assert image_exists(docker_client, image1_name)
assert image_exists(docker_py_client, image1_name)

Expand All @@ -155,14 +158,33 @@ def test_create_image(
# Our docker client should be able to retrieve images with just the name
image2 = docker_client.images.get(repo_url + image2_name)
image2_no_url = docker_client.images.get(image2_name)
assert docker_client.images._tag_exists(image2_name, image2.tags)

assert image2 is not None
assert image2_no_url is not None
assert image2.id == image2_py.id
assert image2_no_url.id == image2_py.id

assert image_exists(docker_client, image2_name)
assert image_exists(docker_client, repo_url + image2_name)
assert image_exists(docker_py_client, repo_url + image2_name)
# Check we are not overmatching but we are getting all possible cases
docker_host = os.environ.get("DOCKER_HOST", "")

podman = False
if "podman" in docker_host:
podman = True

for client in [docker_client, docker_py_client]:
assert not image_exists(client, "create_image")

if podman and client == docker_py_client:
# Docker-py does not support partial string matching
assert image_exists(client, image2_name)
assert image_exists(client, f"/{image2_name}")
assert image_exists(client, f"bar/{image2_name}")
assert image_exists(client, f"bar/{image2_name}:latest")
assert not image_exists(client, f"ar/{image2_name}")
assert image_exists(client, f"foo/bar/{image2_name}")
Comment on lines +178 to +185
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get what's going on here. Why are we testing docker-py?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just to test if we have the same behavior as docker-py, aka images that docker-py marks as existing vs images we mark as existing vs images docker-py marks as not existing are all the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was acutally something I had to do manually a lot as well to validate the behavior of what docker-py marks as existing and what it doesn't and actually docker-py/podman have slightly different behavior which is why we check if podman is in the docker_host.

docker-py marks less images as existing than podman and we match podman's behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also like some documentation as to what counts as existing and what doesn't for all systems.


assert image_exists(client, repo_url + image2_name)

finally:
# Clean up the images
Expand Down
19 changes: 17 additions & 2 deletions tests/endtoend_tests/test_endtoend.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""End-to-end tests for Tesseract workflows."""

import json
import os
from pathlib import Path

import pytest
Expand All @@ -20,7 +21,9 @@ def built_image_name(
docker_client, docker_cleanup, shared_dummy_image_name, dummy_tesseract_location
):
"""Build the dummy Tesseract image for the tests."""
image_name = build_tesseract(dummy_tesseract_location, shared_dummy_image_name)
image_name = build_tesseract(
docker_client, dummy_tesseract_location, shared_dummy_image_name
)
assert image_exists(docker_client, image_name)
docker_cleanup["images"].append(image_name)
yield image_name
Expand Down Expand Up @@ -59,7 +62,11 @@ def test_build_from_init_endtoend(
config_override["build_config.base_image"] = base_image

image_name = build_tesseract(
tmp_path, dummy_image_name, config_override=config_override, tag=img_tag
docker_client,
tmp_path,
dummy_image_name,
config_override=config_override,
tag=img_tag,
)
assert image_exists(docker_client, image_name)
docker_cleanup["images"].append(image_name)
Expand Down Expand Up @@ -318,6 +325,14 @@ def test_tesseract_serve_ports(built_image_name, port, docker_cleanup):
cli_runner = CliRunner(mix_stderr=False)
project_id = None

docker_host = os.environ.get("DOCKER_HOST", "")

if "-" in port and "podman" in docker_host:
pytest.skip(
"Podman does not support port ranges in compose."
"See https://github.com/containers/podman/issues/15111"
)
Comment on lines +328 to +334
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will this manifest when actual users try to use this feature? Big scary error I presume?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with a big scary error :(
$ tesseract serve -p 8080-8090 vectoradd
 [i] Waiting for Tesseract containers to start ...
 [-] Command '['docker', 'compose', '-f', '/tmp/docker-compose-5q6c6fow2334.yml067irwdg', '-p', 'tesseract-oztyf31595ji', 'up', '-d', '--wait']' returned non-zero exit status 1.
 [-] time="2025-05-07T11:32:50-03:00" level=warning msg="a network with name multi-tesseract-network exists but was not created for project \"tesseract-oztyf31595ji\".\nSet `external: true` to use an existing network"
 Container tesseract-oztyf31595ji-sha256-1u8fa9j3tlsb-1  Creating
Error response from daemon: make cli opts(): strconv.Atoi: parsing "8080-8090": invalid syntax

 [x] Uncaught error: ('Failed to start Tesseract containers.', b'time="2025-05-07T11:32:50-03:00" level=warning msg="a network with name multi-tesseract-network exists but was not created for project \\"tesseract-oztyf31595ji\\".\\nSet `external: true` to use an existing network"\n Container tesseract-oztyf31595ji-sha256-1u8fa9j3tlsb-1  Creating\nError response from daemon: make cli opts(): strconv.Atoi: parsing "8080-8090": invalid syntax\n')
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/h/projects/pasteur/tesseract-core/tesseract_core/sdk/docker_client.py:653 in up            │
│                                                                                                  │
│   650 │   │   """                                                                                │
│   651 │   │   logger.info("Waiting for Tesseract containers to start ...")                       │
│   652 │   │   try:                                                                               │
│ ❱ 653 │   │   │   _ = subprocess.run(                                                            │
│   654 │   │   │   │   [                                                                          │
│   655 │   │   │   │   │   "docker",                                                              │
│   656 │   │   │   │   │   "compose",                                                             │
│                                                                                                  │
│ /home/h/.local/share/uv/python/cpython-3.13.3-linux-x86_64-gnu/lib/python3.13/subprocess.py:577  │
│ in run                                                                                           │
│                                                                                                  │
│    574 │   │   │   raise                                                                         │
│    575 │   │   retcode = process.poll()                                                          │
│    576 │   │   if check and retcode:                                                             │
│ ❱  577 │   │   │   raise CalledProcessError(retcode, process.args,                               │
│    578 │   │   │   │   │   │   │   │   │    output=stdout, stderr=stderr)                        │
│    579 │   return CompletedProcess(process.args, retcode, stdout, stderr)                        │
│    580                                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
CalledProcessError: Command '['docker', 'compose', '-f',
'/tmp/docker-compose-5q6c6fow2334.yml067irwdg', '-p', 'tesseract-oztyf31595ji', 'up', '-d', '--wait']'
returned non-zero exit status 1.

The above exception was the direct cause of the following exception:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/h/projects/pasteur/tesseract-core/tesseract_core/sdk/engine.py:114 in wrapper_needs_docker │
│                                                                                                  │
│   111 │   │   │   raise UserError(                                                               │
│   112 │   │   │   │   "Could not reach Docker daemon, check if it is running."                   │
│   113 │   │   │   ) from ex                                                                      │
│ ❱ 114 │   │   return func(*args, **kwargs)                                                       │
│   115 │                                                                                          │
│   116 │   return wrapper_needs_docker                                                            │
│   117                                                                                            │
│                                                                                                  │
│ /home/h/projects/pasteur/tesseract-core/tesseract_core/sdk/cli.py:453 in serve                   │
│                                                                                                  │
│   450 │   │   ports = None                                                                       │
│   451 │                                                                                          │
│   452 │   try:                                                                                   │
│ ❱ 453 │   │   project_id = engine.serve(image_names, ports, volume, gpus)                        │
│   454 │   │   container_ports = _display_project_meta(project_id)                                │
│   455 │   │   logger.info(                                                                       │
│   456 │   │   │   f"Docker Compose Project ID, use it with 'tesseract teardown' command: {proj   │
│                                                                                                  │
│ /home/h/projects/pasteur/tesseract-core/tesseract_core/sdk/engine.py:545 in serve                │
│                                                                                                  │
│   542 │   │   compose_file.flush()                                                               │
│   543 │   │                                                                                      │
│   544 │   │   project_name = _create_compose_proj_id()                                           │
│ ❱ 545 │   │   if not docker_client.compose.up(compose_file.name, project_name):                  │
│   546 │   │   │   raise RuntimeError("Cannot serve Tesseracts")                                  │
│   547 │   │   return project_name                                                                │
│   548                                                                                            │
│                                                                                                  │
│ /home/h/projects/pasteur/tesseract-core/tesseract_core/sdk/docker_client.py:683 in up            │
│                                                                                                  │
│   680 │   │   │   │   ) from ex                                                                  │
│   681 │   │   │   logger.error(str(ex))                                                          │
│   682 │   │   │   logger.error(ex.stderr.decode())                                               │
│ ❱ 683 │   │   │   raise ContainerError(                                                          │
│   684 │   │   │   │   "Failed to start Tesseract containers.", ex.stderr                         │
│   685 │   │   │   ) from ex                                                                      │
│   686                                                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ContainerError: ('Failed to start Tesseract containers.', b'time="2025-05-07T11:32:50-03:00"
level=warning msg="a network with name multi-tesseract-network exists but was not created for project
\\"tesseract-oztyf31595ji\\".\\nSet `external: true` to use an existing network"\n Container
tesseract-oztyf31595ji-sha256-1u8fa9j3tlsb-1  Creating\nError response from daemon: make cli opts():
strconv.Atoi: parsing "8080-8090": invalid syntax\n')
 [x] Aborting

Should we handle this here or on a separate PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can detect Podman reliably ahead of time (ideally not by parsing DOCKER_HOST but via docker --version or something like that) let's do it. Otherwise this should be acceptable for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docker communicates with the Docker daemon via a socket, so we can "point" docker to a Podman daemon instead by overwriting DOCKER_HOST. But docker itself doesn't know which daemon it communicates with, as long as it is API compatible. docker info and docker --version don't show anything that indicates which daemon it is communicating with.

The only way I'm aware of to check if docker is communicating with Podman is to check the environment variable DOCKER_HOST.


# Serve tesseract on specified ports.
run_res = cli_runner.invoke(
app,
Expand Down
12 changes: 2 additions & 10 deletions tests/endtoend_tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import numpy.typing as npt
import pytest
import requests
from common import build_tesseract
from common import build_tesseract, image_exists
from typer.testing import CliRunner


Expand Down Expand Up @@ -739,15 +739,6 @@ def unit_tesseract_config(unit_tesseract_names, unit_tesseract_path):
return TEST_CASES[unit_tesseract_path.name]


def image_exists(client, image_name):
# Docker images may be prefixed with the registry URL
return any(
tag.split("/")[-1] == image_name
for img in client.images.list()
for tag in img.tags
)


def print_debug_info(result):
"""Print debug info from result of a CLI command if it failed."""
if result.exit_code == 0:
Expand Down Expand Up @@ -816,6 +807,7 @@ def test_unit_tesseract_endtoend(

# Stage 1: Build
img_name = build_tesseract(
docker_client,
unit_tesseract_path,
dummy_image_name,
tag="sometag",
Expand Down
4 changes: 3 additions & 1 deletion tests/endtoend_tests/test_tesseract_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ def built_image_name(
docker_client, shared_dummy_image_name, dummy_tesseract_location, docker_cleanup
):
"""Build the dummy Tesseract image for the tests."""
image_name = build_tesseract(dummy_tesseract_location, shared_dummy_image_name)
image_name = build_tesseract(
docker_client, dummy_tesseract_location, shared_dummy_image_name
)
assert image_exists(docker_client, image_name)
docker_cleanup["images"].append(image_name)
yield image_name
Expand Down
Loading