.localhost),
+ // which is why the endpoint is not 127.0.0.1.
+ const control = new S3ControlClient(hc.getClientConfig());
+ await control.send(
+ new ListTagsForResourceCommand({ AccountId: hc.getAccountId(), ResourceArn: "arn:aws:s3:::tc-node" }),
+ );
});
it("SQS", async () => {
diff --git a/integrations/testcontainers-python/README.md b/integrations/testcontainers-python/README.md
index ec2704b8..59b3e12d 100644
--- a/integrations/testcontainers-python/README.md
+++ b/integrations/testcontainers-python/README.md
@@ -31,7 +31,7 @@ def test_upload(homecloud):
| | |
| --- | --- |
| `HomeCloudContainer(image=DEFAULT_IMAGE, port=18080, docker_socket="/var/run/docker.sock", wait_for_services=("s3",), startup_timeout=180)` | `wait_for_services` takes `s3`, `ecr`, `route53`; everything else is ready with the API |
-| `get_endpoint()` | `http://127.0.0.1:18080` |
+| `get_endpoint()` | `http://localhost:18080` |
| `get_credentials()` | `Credentials(access_key_id, secret_access_key, region)` |
| `get_client(service, **kw)` / `get_resource(service, **kw)` | boto3 client / resource for HomeCloud |
| `aws_env()` | `AWS_ENDPOINT_URL`, keys and region for subprocesses (AWS CLI, Terraform) |
@@ -46,6 +46,12 @@ gets the Docker socket and **host networking**; the API listens on `127.0.0.1: None:
# Connection details
def get_endpoint(self) -> str:
- """The API URL, e.g. http://127.0.0.1:18080 (what AWS_ENDPOINT_URL should be)."""
+ """The API URL, e.g. http://localhost:18080 (what AWS_ENDPOINT_URL should be).
+
+ A loopback Docker host is named ``localhost``, as ``homecloud aws-env``
+ does: S3 Control (which the Terraform AWS provider calls for every
+ bucket) puts the account ID in front of the endpoint's host, and
+ ``123456789012.127.0.0.1`` does not resolve. HomeCloud listens on
+ 127.0.0.1 only; clients that try ::1 first fall back to it.
+ """
host = self.get_container_host_ip()
- if host == "localhost":
- host = "127.0.0.1"
+ if host in ("localhost", "127.0.0.1", "::1"):
+ host = "localhost"
return f"http://{host}:{self.port}"
def get_credentials(self) -> Credentials:
diff --git a/integrations/testcontainers-python/tests/test_homecloud.py b/integrations/testcontainers-python/tests/test_homecloud.py
index c792ce32..aa52eb6d 100644
--- a/integrations/testcontainers-python/tests/test_homecloud.py
+++ b/integrations/testcontainers-python/tests/test_homecloud.py
@@ -47,6 +47,10 @@ def test_s3(homecloud):
assert s3.get_object(Bucket="tc-python", Key="a.txt")["Body"].read() == b"hello"
bucket = homecloud.get_resource("s3").Bucket("tc-python")
assert [o.key for o in bucket.objects.all()] == ["a.txt"]
+ # S3 Control puts the account ID in front of the endpoint host
+ # (.localhost), which is why the endpoint is not 127.0.0.1.
+ control = homecloud.get_client("s3control")
+ control.list_tags_for_resource(AccountId=homecloud.account_id, ResourceArn="arn:aws:s3:::tc-python")
def test_sqs(homecloud):
diff --git a/integrations/testcontainers-python/tests/test_options.py b/integrations/testcontainers-python/tests/test_options.py
index 4185beba..1a695244 100644
--- a/integrations/testcontainers-python/tests/test_options.py
+++ b/integrations/testcontainers-python/tests/test_options.py
@@ -26,3 +26,14 @@ def test_command_and_socket():
hc = make(port=19090, docker_socket="/run/user/1000/docker.sock")
assert hc._command == ["serve", "--data-dir", "/data", "--addr", "127.0.0.1:19090"]
assert hc.volumes["/run/user/1000/docker.sock"]["bind"] == "/var/run/docker.sock"
+
+
+def test_endpoint_names_loopback_localhost():
+ for host, want in [
+ ("localhost", "http://localhost:18080"),
+ ("127.0.0.1", "http://localhost:18080"),
+ ("docker.example", "http://docker.example:18080"),
+ ]:
+ hc = make()
+ with mock.patch.object(HomeCloudContainer, "get_container_host_ip", return_value=host):
+ assert hc.get_endpoint() == want