diff --git a/.env.test b/.env.test index d15ee6f..cca44ff 100644 --- a/.env.test +++ b/.env.test @@ -18,6 +18,10 @@ S3_ENDPOINT_URL=http://minio:9000 S3_ACCESS_KEY=JANE_DOE S3_SECRET_KEY=JANE_DOE S3_REGION=us-east-1 +# Public S3 endpoint: `minio` above only resolves inside the compose network, but +# presigned URLs are opened by the browser. Works because boto3 presigns with SigV2, +# which ignores the Host -- a SigV4 backend would need a Host-rewriting proxy. +S3_PROXY_URL=http://localhost:9000 # Prefix used by pyro-api to build per-org S3 bucket names. Must be a valid # bucket-name prefix (lowercase letters, digits, hyphens). Empty => InvalidBucketName. diff --git a/README.md b/README.md index 1aca242..abfa4c4 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,9 @@ This repository provides a Docker Compose configuration to run a full Pyronear d ### Prerequisites * Docker and Docker Compose -* Add this line to your hosts file (`/etc/hosts` on Linux/macOS, `C:\Windows\System32\drivers\etc\hosts` on Windows): - ``` - 127.0.0.1 minio - ``` + +> **Upgrading?** The `127.0.0.1 minio` hosts entry is no longer needed (`S3_PROXY_URL` +> replaces it) — harmless if left in place, but you can remove it. --- @@ -104,6 +103,9 @@ docker logs engine * **MinIO console (S3 GUI)**: [http://localhost:9001](http://localhost:9001) * Manage buckets, upload/delete files +* **MinIO S3 API**: `minio:9000` from the compose network (`S3_ENDPOINT_URL`), + [http://localhost:9000](http://localhost:9000) from the host (`S3_PROXY_URL`, used + for presigned image URLs) --- diff --git a/docker-compose.yml b/docker-compose.yml index b73bec8..8ad2d71 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,8 @@ services: - S3_ACCESS_KEY=${S3_ACCESS_KEY} - S3_SECRET_KEY=${S3_SECRET_KEY} - S3_REGION=${S3_REGION} + # Host used in presigned URLs, which the browser opens (`minio` is compose-only). + - S3_PROXY_URL=${S3_PROXY_URL:-} - SERVER_NAME=${SERVER_NAME} - PLATFORM_URL=${PLATFORM_URL:-http://localhost:8080} - TEMPORAL_API_URL=${TEMPORAL_API_URL:-} diff --git a/tests/test_media.py b/tests/test_media.py index 0bffcdf..adbf5bd 100644 --- a/tests/test_media.py +++ b/tests/test_media.py @@ -6,8 +6,8 @@ # Load environment variables from .env file load_dotenv() -# Get S3 endpoint URL and credentials from environment variables -s3_endpoint_url = os.getenv("S3_ENDPOINT_URL") + "/" +# Tests run on the host: prefer the public endpoint, `minio` is compose-only. +s3_endpoint_url = (os.getenv("S3_PROXY_URL") or os.getenv("S3_ENDPOINT_URL")) + "/" s3_access_key = os.getenv("S3_ACCESS_KEY") s3_secret_key = os.getenv("S3_SECRET_KEY") s3_region = os.getenv("S3_REGION") @@ -28,10 +28,13 @@ def s3_client(): def test_s3_bucket(s3_client): response = s3_client.list_buckets() - assert response["Buckets"][0]["Name"] == "admin" - assert response["Buckets"][1]["Name"].endswith("-alert-api-1") + bucket_names = [bucket["Name"] for bucket in response["Buckets"]] - bucket_contents = s3_client.list_objects_v2(Bucket=response["Buckets"][1]["Name"]) + # One bucket per organization: {SERVER_NAME}-alert-api-{org_id} + alert_buckets = [name for name in bucket_names if name.endswith("-alert-api-1")] + assert alert_buckets, bucket_names + + bucket_contents = s3_client.list_objects_v2(Bucket=alert_buckets[0]) print(bucket_contents) [item["Key"] for item in bucket_contents.get("Contents", [])] # assert keys != []