From 5218f716539b446bb8991bd0c0f389aef30428d8 Mon Sep 17 00:00:00 2001 From: grusev Date: Mon, 15 Sep 2025 13:43:17 +0300 Subject: [PATCH 01/15] test_library_get_key_path check --- python/tests/integration/arcticdb/test_s3.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tests/integration/arcticdb/test_s3.py b/python/tests/integration/arcticdb/test_s3.py index c575f3bd19..a3703f1b11 100644 --- a/python/tests/integration/arcticdb/test_s3.py +++ b/python/tests/integration/arcticdb/test_s3.py @@ -196,7 +196,6 @@ def test_wrapped_s3_storage(lib_name, wrapped_s3_storage_bucket): lib.write("s", data=create_df()) -@SKIP_CONDA_MARK # issue with fixture init will be fixed in https://github.com/man-group/ArcticDB/issues/2640 def test_library_get_key_path(lib_name, s3_and_nfs_storage_bucket, test_prefix): lib = s3_and_nfs_storage_bucket.create_version_store_factory(lib_name)() lib.write("s", data=create_df()) From a440c39960df5084472e70c7507815e7b110a51c Mon Sep 17 00:00:00 2001 From: grusev Date: Thu, 18 Sep 2025 17:09:22 +0300 Subject: [PATCH 02/15] except (botocore.exceptions.EndpointConnectionError, botocore.exceptions.ClientError) as e: --- python/arcticdb/storage_fixtures/s3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 1822c52234..fcf1bd1804 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -736,7 +736,7 @@ def create_bucket(s3_client, bucket_name, max_retries=15): try: s3_client.create_bucket(Bucket=bucket_name) return - except botocore.exceptions.EndpointConnectionError as e: + except (botocore.exceptions.EndpointConnectionError, botocore.exceptions.ClientError) as e: if i >= max_retries - 1: raise logger.warning(f"S3 create bucket failed. Retry {1}/{max_retries}") From d13d48c61d048b72071343ba62ac5ac7b9df4e39 Mon Sep 17 00:00:00 2001 From: grusev Date: Tue, 23 Sep 2025 09:27:04 +0300 Subject: [PATCH 03/15] use hyphen not underscore in bucket name --- python/arcticdb/storage_fixtures/s3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index fcf1bd1804..b9fa49fe58 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -791,7 +791,7 @@ def bucket_name(self, bucket_type="s3"): # We need the unique_id because we have tests that are creating the factory directly # and not using the fixtures # so this guarantees a unique bucket name - return f"test_{bucket_type}_bucket_{self.unique_id}_{self._bucket_id}" + return f"test-{bucket_type}-bucket-{self.unique_id}-{self._bucket_id}" def _start_server(self): port = self.port = get_ephemeral_port(2) From 1ce0fcb82443d705b39e8ecf0d947ed3b1cfdf72 Mon Sep 17 00:00:00 2001 From: grusev Date: Tue, 23 Sep 2025 15:30:23 +0300 Subject: [PATCH 04/15] More info --- python/arcticdb/storage_fixtures/s3.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index b9fa49fe58..35337cec70 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -731,6 +731,23 @@ def run_gcp_server(port, key_file, cert_file): ) +def get_buckets_check(s3_client): + try: + response = s3_client.list_buckets() + buckets = response.get("Buckets", []) + + if buckets: + print("Buckets found:") + for bucket in buckets: + print(f"- {bucket['Name']}") + else: + print("Client is alive, but no buckets exist.") + except botocore.exceptions.EndpointConnectionError: + print("Could not connect to Moto S3 server. Is it running?") + except botocore.exceptions.ClientError as e: + print(f"Client error: {e.response['Error']['Message']}") + + def create_bucket(s3_client, bucket_name, max_retries=15): for i in range(max_retries): try: @@ -740,6 +757,10 @@ def create_bucket(s3_client, bucket_name, max_retries=15): if i >= max_retries - 1: raise logger.warning(f"S3 create bucket failed. Retry {1}/{max_retries}") + logger.warning(f"Error: {e.response['Error']['Message']}") + get_buckets_check() + import pprint + pprint.pprint(e.response) time.sleep(1) From 8237632e63ed3f291afb42f1c2e0766d99a3569a Mon Sep 17 00:00:00 2001 From: grusev Date: Wed, 24 Sep 2025 08:26:53 +0300 Subject: [PATCH 05/15] Added param --- python/arcticdb/storage_fixtures/s3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 35337cec70..33750e1538 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -758,7 +758,7 @@ def create_bucket(s3_client, bucket_name, max_retries=15): raise logger.warning(f"S3 create bucket failed. Retry {1}/{max_retries}") logger.warning(f"Error: {e.response['Error']['Message']}") - get_buckets_check() + get_buckets_check(s3_client) import pprint pprint.pprint(e.response) time.sleep(1) From d456411c9384c3a72197ac60fdeb5c0c8edbaf06 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Wed, 24 Sep 2025 12:23:48 +0300 Subject: [PATCH 06/15] print to log --- python/arcticdb/storage_fixtures/s3.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 33750e1538..2d2f1faf17 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -735,17 +735,17 @@ def get_buckets_check(s3_client): try: response = s3_client.list_buckets() buckets = response.get("Buckets", []) - + if buckets: - print("Buckets found:") + logger.warning("Buckets found:") for bucket in buckets: - print(f"- {bucket['Name']}") + logger.warning(f"- {bucket['Name']}") else: - print("Client is alive, but no buckets exist.") + logger.warning("Client is alive, but no buckets exist.") except botocore.exceptions.EndpointConnectionError: - print("Could not connect to Moto S3 server. Is it running?") + logger.warning("Could not connect to Moto S3 server. Is it running?") except botocore.exceptions.ClientError as e: - print(f"Client error: {e.response['Error']['Message']}") + logger.warning(f"Client error: {e.response['Error']['Message']}") def create_bucket(s3_client, bucket_name, max_retries=15): @@ -760,6 +760,7 @@ def create_bucket(s3_client, bucket_name, max_retries=15): logger.warning(f"Error: {e.response['Error']['Message']}") get_buckets_check(s3_client) import pprint + pprint.pprint(e.response) time.sleep(1) From cadb30cb55c624f53da4b5d56854d4cdb30e7605 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Wed, 24 Sep 2025 13:01:01 +0300 Subject: [PATCH 07/15] try fix --- python/arcticdb/storage_fixtures/s3.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 2d2f1faf17..04db2bddbe 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -850,15 +850,19 @@ def _start_server(self): wait_for_server_to_come_up(self.endpoint, "moto", self._p, timeout=240) def _safe_enter(self): - for _ in range(3): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start + for _ in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start try: self._start_server() + self._s3_admin = self._boto(service="s3", key=self.default_key) + get_buckets_check(self._s3_admin) + logger.info("Moto S3 STARTED!!!") break except AssertionError as e: # Thrown by wait_for_server_to_come_up sys.stderr.write(repr(e)) GracefulProcessUtils.terminate(self._p) + except Exception as e: + logger.error(f"Error during startup of Moto S3. Trying again. Error: {e}") - self._s3_admin = self._boto(service="s3", key=self.default_key) return self def __exit__(self, exc_type, exc_value, traceback): From 52c2d02fb6755def38bdad355d634132295170b0 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Wed, 24 Sep 2025 13:16:01 +0300 Subject: [PATCH 08/15] better fix --- python/arcticdb/storage_fixtures/s3.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 04db2bddbe..fe5f2bdd14 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -815,8 +815,8 @@ def bucket_name(self, bucket_type="s3"): # so this guarantees a unique bucket name return f"test-{bucket_type}-bucket-{self.unique_id}-{self._bucket_id}" - def _start_server(self): - port = self.port = get_ephemeral_port(2) + def _start_server(self, seed=2): + port = self.port = get_ephemeral_port(seed) self.endpoint = f"{self.http_protocol}://{self.host}:{port}" self.working_dir = mkdtemp(suffix="MotoS3StorageFixtureFactory") self._iam_endpoint = f"{self.http_protocol}://localhost:{port}" @@ -850,9 +850,9 @@ def _start_server(self): wait_for_server_to_come_up(self.endpoint, "moto", self._p, timeout=240) def _safe_enter(self): - for _ in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start + for i in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start try: - self._start_server() + self._start_server(2 + i) self._s3_admin = self._boto(service="s3", key=self.default_key) get_buckets_check(self._s3_admin) logger.info("Moto S3 STARTED!!!") From 854136a9835099eaf413bb0e78dec6527f6ea982 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Wed, 24 Sep 2025 16:39:47 +0300 Subject: [PATCH 09/15] fix regression for gcp --- python/arcticdb/storage_fixtures/s3.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index fe5f2bdd14..a7c8d5fb78 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -13,6 +13,7 @@ import re import sys import platform +import pprint from tempfile import mkdtemp from urllib.parse import urlparse import boto3 @@ -753,16 +754,15 @@ def create_bucket(s3_client, bucket_name, max_retries=15): try: s3_client.create_bucket(Bucket=bucket_name) return - except (botocore.exceptions.EndpointConnectionError, botocore.exceptions.ClientError) as e: + except botocore.exceptions.EndpointConnectionError as e: if i >= max_retries - 1: raise logger.warning(f"S3 create bucket failed. Retry {1}/{max_retries}") - logger.warning(f"Error: {e.response['Error']['Message']}") + time.sleep(1) + except Exception as e: + logger.error(f"Error: {e.response['Error']['Message']}") get_buckets_check(s3_client) - import pprint - pprint.pprint(e.response) - time.sleep(1) class MotoS3StorageFixtureFactory(BaseS3StorageFixtureFactory): @@ -954,8 +954,8 @@ def create_fixture(self) -> NfsS3Bucket: class MotoGcpS3StorageFixtureFactory(MotoS3StorageFixtureFactory): - def _start_server(self): - port = self.port = get_ephemeral_port(3) + def _start_server(self, seed=9): + port = self.port = get_ephemeral_port(seed) self.endpoint = f"{self.http_protocol}://{self.host}:{port}" self.working_dir = mkdtemp(suffix="MotoGcpS3StorageFixtureFactory") self._iam_endpoint = f"{self.http_protocol}://localhost:{port}" From 86f8f2abc9fdcdf182f596de2d0bf8c486e5191c Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Wed, 24 Sep 2025 20:00:47 +0300 Subject: [PATCH 10/15] fixes --- python/arcticdb/storage_fixtures/s3.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index a7c8d5fb78..de5ba629db 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -745,8 +745,11 @@ def get_buckets_check(s3_client): logger.warning("Client is alive, but no buckets exist.") except botocore.exceptions.EndpointConnectionError: logger.warning("Could not connect to Moto S3 server. Is it running?") + raise except botocore.exceptions.ClientError as e: - logger.warning(f"Client error: {e.response['Error']['Message']}") + logger.warning(f"get_buckets_check - Client error: {e.response['Error']['Message']}") + pprint.pprint(e.response) + raise def create_bucket(s3_client, bucket_name, max_retries=15): @@ -760,9 +763,9 @@ def create_bucket(s3_client, bucket_name, max_retries=15): logger.warning(f"S3 create bucket failed. Retry {1}/{max_retries}") time.sleep(1) except Exception as e: - logger.error(f"Error: {e.response['Error']['Message']}") - get_buckets_check(s3_client) + logger.error(f"create_bucket - Error: {e.response['Error']['Message']}") pprint.pprint(e.response) + get_buckets_check(s3_client) class MotoS3StorageFixtureFactory(BaseS3StorageFixtureFactory): @@ -852,10 +855,11 @@ def _start_server(self, seed=2): def _safe_enter(self): for i in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start try: + logger.info(f"Attempt to start server - {i}") self._start_server(2 + i) self._s3_admin = self._boto(service="s3", key=self.default_key) get_buckets_check(self._s3_admin) - logger.info("Moto S3 STARTED!!!") + logger.info(f"Moto S3 STARTED!!! on port {self.port}") break except AssertionError as e: # Thrown by wait_for_server_to_come_up sys.stderr.write(repr(e)) From 3de329c19cee9fb313b3e74e0062411a851b3486 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Mon, 29 Sep 2025 13:16:27 +0300 Subject: [PATCH 11/15] fix --- python/arcticdb/storage_fixtures/mongo.py | 2 +- python/arcticdb/storage_fixtures/s3.py | 44 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/python/arcticdb/storage_fixtures/mongo.py b/python/arcticdb/storage_fixtures/mongo.py index 39349fcfa0..730e1031b9 100644 --- a/python/arcticdb/storage_fixtures/mongo.py +++ b/python/arcticdb/storage_fixtures/mongo.py @@ -117,7 +117,7 @@ class ManagedMongoDBServer(StorageFixtureFactory): def __init__(self, data_dir: Optional[str] = None, port=0, executable="mongod"): self._data_dir = data_dir or tempfile.mkdtemp("ManagedMongoDBServer") - self._port = port or get_ephemeral_port(5) + self._port = port or get_ephemeral_port(7) self._executable = executable self._client = None diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index de5ba629db..9f1cf88316 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -668,6 +668,11 @@ def __call__(self, environ, start_response): ): start_response("200 OK", [("Content-Type", "text/plain")]) return [b"Something to prove imds is reachable"] + + # Lets add ability to identify type as S3 + if path_info in ("/whoami"): + start_response("200 OK", [("Content-Type", "text/plain")]) + return [b"Moto AWS S3"] # Allow setting up a rate limit if path_info in ("/rate_limit", b"/rate_limit"): @@ -696,6 +701,13 @@ class GcpHostDispatcherApplication(HostDispatcherApplication): """GCP's S3 implementation does not have batch delete.""" def __call__(self, environ, start_response): + path_info: bytes = environ.get("PATH_INFO", "") + + # Lets add ability to identify type as GCP + if path_info in ("/whoami"): + start_response("200 OK", [("Content-Type", "text/plain")]) + return [b"Moto GCP"] + if environ["REQUEST_METHOD"] == "POST" and environ["QUERY_STRING"] == "delete": response_body = ( b'' @@ -732,6 +744,20 @@ def run_gcp_server(port, key_file, cert_file): ) +def is_server_type(url: str, server_type: str): + """Check if a server is of certain type. + + /whoami url is added to Moto* objects to identify GCP or S3""" + try: + response = requests.get(url, verify=False) + if response.status_code == 200 and server_type in response.text: + return True + except Exception as e: + logger.error(f"Error during server type check: {e}") + logger.error(f"Was not of expected type: status code {response.status_code}, text: {response.text}") + return False + + def get_buckets_check(s3_client): try: response = s3_client.list_buckets() @@ -765,7 +791,7 @@ def create_bucket(s3_client, bucket_name, max_retries=15): except Exception as e: logger.error(f"create_bucket - Error: {e.response['Error']['Message']}") pprint.pprint(e.response) - get_buckets_check(s3_client) + #get_buckets_check(s3_client) class MotoS3StorageFixtureFactory(BaseS3StorageFixtureFactory): @@ -817,6 +843,15 @@ def bucket_name(self, bucket_type="s3"): # and not using the fixtures # so this guarantees a unique bucket name return f"test-{bucket_type}-bucket-{self.unique_id}-{self._bucket_id}" + + def is_server_type(url: str, server_type: str): + try: + response = requests.get(url, verify=False) + if response.status_code == 200 and server_type in response.text: + return True + except Exception: + pass + return False def _start_server(self, seed=2): port = self.port = get_ephemeral_port(seed) @@ -851,6 +886,8 @@ def _start_server(self, seed=2): # There is a problem with the performance of the socket module in the MacOS 15 GH runners - https://github.com/actions/runner-images/issues/12162 # Due to this, we need to wait for the server to come up for a longer time wait_for_server_to_come_up(self.endpoint, "moto", self._p, timeout=240) + assert is_server_type(self.endpoint + "/whoami", "S3"), "The server has not identified as S3" + def _safe_enter(self): for i in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start @@ -858,7 +895,7 @@ def _safe_enter(self): logger.info(f"Attempt to start server - {i}") self._start_server(2 + i) self._s3_admin = self._boto(service="s3", key=self.default_key) - get_buckets_check(self._s3_admin) + #get_buckets_check(self._s3_admin) logger.info(f"Moto S3 STARTED!!! on port {self.port}") break except AssertionError as e: # Thrown by wait_for_server_to_come_up @@ -958,7 +995,7 @@ def create_fixture(self) -> NfsS3Bucket: class MotoGcpS3StorageFixtureFactory(MotoS3StorageFixtureFactory): - def _start_server(self, seed=9): + def _start_server(self, seed=20): port = self.port = get_ephemeral_port(seed) self.endpoint = f"{self.http_protocol}://{self.host}:{port}" self.working_dir = mkdtemp(suffix="MotoGcpS3StorageFixtureFactory") @@ -991,6 +1028,7 @@ def _start_server(self, seed=9): # There is a problem with the performance of the socket module in the MacOS 15 GH runners - https://github.com/actions/runner-images/issues/12162 # Due to this, we need to wait for the server to come up for a longer time wait_for_server_to_come_up(self.endpoint, "moto", self._p, timeout=240) + assert is_server_type(self.endpoint + "/whoami", "GCP"), "The server has not identified as GCP" def create_fixture(self) -> GcpS3Bucket: bucket = self.bucket_name("gcp") From 8d5b6158dc4f2cbed6e451279cb7e937284d2e20 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Mon, 29 Sep 2025 14:41:44 +0300 Subject: [PATCH 12/15] fixes --- python/arcticdb/storage_fixtures/s3.py | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index 9f1cf88316..b911fef362 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -668,11 +668,6 @@ def __call__(self, environ, start_response): ): start_response("200 OK", [("Content-Type", "text/plain")]) return [b"Something to prove imds is reachable"] - - # Lets add ability to identify type as S3 - if path_info in ("/whoami"): - start_response("200 OK", [("Content-Type", "text/plain")]) - return [b"Moto AWS S3"] # Allow setting up a rate limit if path_info in ("/rate_limit", b"/rate_limit"): @@ -694,6 +689,11 @@ def __call__(self, environ, start_response): else: self._reqs_till_rate_limit -= 1 + # Lets add ability to identify type as S3 + if "/whoami" in path_info: + start_response("200 OK", [("Content-Type", "text/plain")]) + return [b"Moto AWS S3"] + return super().__call__(environ, start_response) @@ -703,11 +703,6 @@ class GcpHostDispatcherApplication(HostDispatcherApplication): def __call__(self, environ, start_response): path_info: bytes = environ.get("PATH_INFO", "") - # Lets add ability to identify type as GCP - if path_info in ("/whoami"): - start_response("200 OK", [("Content-Type", "text/plain")]) - return [b"Moto GCP"] - if environ["REQUEST_METHOD"] == "POST" and environ["QUERY_STRING"] == "delete": response_body = ( b'' @@ -721,6 +716,12 @@ def __call__(self, environ, start_response): "501 Not Implemented", [("Content-Type", "text/xml"), ("Content-Length", str(len(response_body)))] ) return [response_body] + + # Lets add ability to identify type as GCP + if "/whoami" in path_info: + start_response("200 OK", [("Content-Type", "text/plain")]) + return [b"Moto GCP"] + return super().__call__(environ, start_response) @@ -746,16 +747,16 @@ def run_gcp_server(port, key_file, cert_file): def is_server_type(url: str, server_type: str): """Check if a server is of certain type. - + /whoami url is added to Moto* objects to identify GCP or S3""" try: - response = requests.get(url, verify=False) - if response.status_code == 200 and server_type in response.text: + response = requests.get(url, verify=False) + if response.status_code == 200 and server_type in response.text: return True except Exception as e: logger.error(f"Error during server type check: {e}") logger.error(f"Was not of expected type: status code {response.status_code}, text: {response.text}") - return False + return False def get_buckets_check(s3_client): @@ -775,7 +776,7 @@ def get_buckets_check(s3_client): except botocore.exceptions.ClientError as e: logger.warning(f"get_buckets_check - Client error: {e.response['Error']['Message']}") pprint.pprint(e.response) - raise + raise def create_bucket(s3_client, bucket_name, max_retries=15): @@ -791,7 +792,7 @@ def create_bucket(s3_client, bucket_name, max_retries=15): except Exception as e: logger.error(f"create_bucket - Error: {e.response['Error']['Message']}") pprint.pprint(e.response) - #get_buckets_check(s3_client) + # get_buckets_check(s3_client) class MotoS3StorageFixtureFactory(BaseS3StorageFixtureFactory): @@ -843,15 +844,15 @@ def bucket_name(self, bucket_type="s3"): # and not using the fixtures # so this guarantees a unique bucket name return f"test-{bucket_type}-bucket-{self.unique_id}-{self._bucket_id}" - + def is_server_type(url: str, server_type: str): try: - response = requests.get(url, verify=False) - if response.status_code == 200 and server_type in response.text: + response = requests.get(url, verify=False) + if response.status_code == 200 and server_type in response.text: return True except Exception: - pass - return False + pass + return False def _start_server(self, seed=2): port = self.port = get_ephemeral_port(seed) @@ -888,14 +889,13 @@ def _start_server(self, seed=2): wait_for_server_to_come_up(self.endpoint, "moto", self._p, timeout=240) assert is_server_type(self.endpoint + "/whoami", "S3"), "The server has not identified as S3" - def _safe_enter(self): for i in range(5): # For unknown reason, Moto, when running in pytest-xdist, will randomly fail to start try: logger.info(f"Attempt to start server - {i}") self._start_server(2 + i) self._s3_admin = self._boto(service="s3", key=self.default_key) - #get_buckets_check(self._s3_admin) + # get_buckets_check(self._s3_admin) logger.info(f"Moto S3 STARTED!!! on port {self.port}") break except AssertionError as e: # Thrown by wait_for_server_to_come_up From 2dd96346ebc1fe2b6dc1e16fd9665cf6173c4948 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Mon, 29 Sep 2025 16:37:52 +0300 Subject: [PATCH 13/15] remove old code --- python/arcticdb/storage_fixtures/s3.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/python/arcticdb/storage_fixtures/s3.py b/python/arcticdb/storage_fixtures/s3.py index b911fef362..cbba5cb754 100644 --- a/python/arcticdb/storage_fixtures/s3.py +++ b/python/arcticdb/storage_fixtures/s3.py @@ -759,26 +759,6 @@ def is_server_type(url: str, server_type: str): return False -def get_buckets_check(s3_client): - try: - response = s3_client.list_buckets() - buckets = response.get("Buckets", []) - - if buckets: - logger.warning("Buckets found:") - for bucket in buckets: - logger.warning(f"- {bucket['Name']}") - else: - logger.warning("Client is alive, but no buckets exist.") - except botocore.exceptions.EndpointConnectionError: - logger.warning("Could not connect to Moto S3 server. Is it running?") - raise - except botocore.exceptions.ClientError as e: - logger.warning(f"get_buckets_check - Client error: {e.response['Error']['Message']}") - pprint.pprint(e.response) - raise - - def create_bucket(s3_client, bucket_name, max_retries=15): for i in range(max_retries): try: @@ -792,7 +772,6 @@ def create_bucket(s3_client, bucket_name, max_retries=15): except Exception as e: logger.error(f"create_bucket - Error: {e.response['Error']['Message']}") pprint.pprint(e.response) - # get_buckets_check(s3_client) class MotoS3StorageFixtureFactory(BaseS3StorageFixtureFactory): @@ -895,7 +874,6 @@ def _safe_enter(self): logger.info(f"Attempt to start server - {i}") self._start_server(2 + i) self._s3_admin = self._boto(service="s3", key=self.default_key) - # get_buckets_check(self._s3_admin) logger.info(f"Moto S3 STARTED!!! on port {self.port}") break except AssertionError as e: # Thrown by wait_for_server_to_come_up From 4399fdbbc417fa23dec369f07ad1675b22148593 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Tue, 30 Sep 2025 08:33:45 +0300 Subject: [PATCH 14/15] azure also has a check for authenticity --- python/arcticdb/storage_fixtures/azure.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/python/arcticdb/storage_fixtures/azure.py b/python/arcticdb/storage_fixtures/azure.py index 15f2d1c646..6ba64853f7 100644 --- a/python/arcticdb/storage_fixtures/azure.py +++ b/python/arcticdb/storage_fixtures/azure.py @@ -13,6 +13,7 @@ import stat import tempfile import uuid +import requests from typing import TYPE_CHECKING, Optional, Union from tempfile import mkdtemp @@ -214,8 +215,23 @@ def _safe_enter(self): process_start_cmd=args, cwd=self.working_dir, ) + assert self.is_azurite(self.endpoint_root), f"Azurite not started at: {self.endpoint_root}" return self + def is_azurite(self, url: str, timeout: int = 60): + try: + response = requests.get(url, timeout=timeout) + headers = response.headers + + # Check for Azurite-specific headers + server_header = headers.get("Server", "").lower() + has_azurite_headers = "x-ms-request-id" in str(headers) and "azurite" in server_header + + return has_azurite_headers + + except requests.RequestException: + return False + def __exit__(self, exc_type, exc_value, traceback): with handle_cleanup_exception(self, "process", consequence="Subsequent file deletion may also fail. "): GracefulProcessUtils.terminate(self._p) From e6da748e30c8bbfbba0dc166faf4c5c7cf119483 Mon Sep 17 00:00:00 2001 From: Georgi Rusev Date: Tue, 30 Sep 2025 09:19:39 +0300 Subject: [PATCH 15/15] fix for azurite ssl --- python/arcticdb/storage_fixtures/azure.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/arcticdb/storage_fixtures/azure.py b/python/arcticdb/storage_fixtures/azure.py index 6ba64853f7..fcbcb80912 100644 --- a/python/arcticdb/storage_fixtures/azure.py +++ b/python/arcticdb/storage_fixtures/azure.py @@ -215,7 +215,9 @@ def _safe_enter(self): process_start_cmd=args, cwd=self.working_dir, ) - assert self.is_azurite(self.endpoint_root), f"Azurite not started at: {self.endpoint_root}" + if not self.ssl_test_support: + # Do not verify when ssl test support because of need of proper certs + assert self.is_azurite(self.endpoint_root), f"Azurite not started at: {self.endpoint_root}" return self def is_azurite(self, url: str, timeout: int = 60):