Skip to content

Commit e3d2a55

Browse files
test: run object-storage tests against SeaweedFS instead of MinIO
MinIO withdrew its public images and archived its source. SeaweedFS 4.48 matches MinIO on s3fs directory emulation, which GC relies on, and passes the object-storage suites from a cold pull. The image is overridable through DJ_TEST_S3_IMAGE. Refs #1560
1 parent 15610e5 commit e3d2a55

1 file changed

Lines changed: 37 additions & 23 deletions

File tree

‎tests/conftest.py‎

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def pytest_collection_modifyitems(config, items):
9595

9696

9797
# =============================================================================
98-
# Container Fixtures - Auto-start MySQL and MinIO via testcontainers
98+
# Container Fixtures - Auto-start MySQL, PostgreSQL, and S3 via testcontainers
9999
# =============================================================================
100100

101101
# Check if we should use external containers (for CI or manual docker-compose)
@@ -164,36 +164,50 @@ def postgres_container():
164164

165165

166166
@pytest.fixture(scope="session")
167-
def minio_container():
168-
"""Start MinIO container for the test session (or use external)."""
167+
def s3_container():
168+
"""Start an S3-compatible object store for the test session (or use external)."""
169169
if USE_EXTERNAL_CONTAINERS:
170170
# Use external container - return None, credentials come from env
171-
logger.info("Using external MinIO container")
171+
logger.info("Using external S3 container")
172172
yield None
173173
return
174174

175-
from testcontainers.minio import MinioContainer
176-
177-
# MinIO withdrew its public images: `minio/minio` on Docker Hub is gone
178-
# entirely (any tag, not just `latest`) and `quay.io/minio/minio` now
179-
# requires authentication. Chainguard publishes a maintained build that
180-
# needs no credentials and is drop-in for this fixture. Overridable so a
181-
# deployment can point at its own mirror without editing tests.
182-
container = MinioContainer(
183-
image=os.environ.get("DJ_TEST_MINIO_IMAGE", "cgr.dev/chainguard/minio:latest"),
184-
access_key="datajoint",
185-
secret_key="datajoint",
175+
import time
176+
177+
from testcontainers.core.container import DockerContainer
178+
179+
# SeaweedFS replaces MinIO, which withdrew its public images and archived
180+
# its source (#1560). It matched MinIO on s3fs directory emulation
181+
# (isdir/walk/find over prefixes and zero-byte markers), which GC depends
182+
# on. Overridable so a deployment can point at its own mirror.
183+
container = (
184+
DockerContainer(os.environ.get("DJ_TEST_S3_IMAGE", "chrislusf/seaweedfs:4.48"))
185+
.with_command("server -s3 -ip.bind=0.0.0.0")
186+
.with_env("AWS_ACCESS_KEY_ID", "datajoint")
187+
.with_env("AWS_SECRET_ACCESS_KEY", "datajoint")
188+
.with_exposed_ports(8333)
186189
)
187190
container.start()
188191

189192
host = container.get_container_host_ip()
190-
port = container.get_exposed_port(9000)
191-
logger.info(f"MinIO container started at {host}:{port}")
193+
port = container.get_exposed_port(8333)
194+
# The S3 gateway starts after the master, volume, and filer servers
195+
deadline = time.monotonic() + 60
196+
while True:
197+
try:
198+
urllib3.PoolManager().request("GET", f"http://{host}:{port}/", retries=False, timeout=1)
199+
break
200+
except urllib3.exceptions.HTTPError:
201+
if time.monotonic() > deadline:
202+
container.stop()
203+
raise
204+
time.sleep(0.5)
205+
logger.info(f"S3 container started at {host}:{port}")
192206

193207
yield container
194208

195209
container.stop()
196-
logger.info("MinIO container stopped")
210+
logger.info("S3 container stopped")
197211

198212

199213
# =============================================================================
@@ -253,12 +267,12 @@ def db_creds_test(mysql_container) -> Dict:
253267

254268

255269
@pytest.fixture(scope="session")
256-
def s3_creds(minio_container) -> Dict:
257-
"""S3/MinIO credentials from container or environment."""
258-
if minio_container is not None:
270+
def s3_creds(s3_container) -> Dict:
271+
"""S3 credentials from container or environment."""
272+
if s3_container is not None:
259273
# From testcontainer
260-
host = minio_container.get_container_host_ip()
261-
port = minio_container.get_exposed_port(9000)
274+
host = s3_container.get_container_host_ip()
275+
port = s3_container.get_exposed_port(8333)
262276
return dict(
263277
endpoint=f"{host}:{port}",
264278
access_key="datajoint",

0 commit comments

Comments
 (0)