Skip to content

Commit 691eeba

Browse files
authored
♻️Maintenance/remove minio-sdk (#5120)
1 parent 79785ba commit 691eeba

File tree

35 files changed

+272
-484
lines changed

35 files changed

+272
-484
lines changed

.github/dependabot.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ updates:
2929
- dependency-name: httpx
3030
versions:
3131
- 0.17.0
32-
- dependency-name: minio
33-
versions:
34-
- 7.0.0
3532
- package-ecosystem: pip
3633
directory: "/packages/service-library"
3734
schedule:

Makefile

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,23 +269,15 @@ CPU_COUNT = $(shell cat /proc/cpuinfo | grep processor | wc -l )
269269

270270

271271
.stack-ops.yml: .env $(docker-compose-configs)
272-
# Compiling config file for filestash
273-
$(eval TMP_PATH_TO_FILESTASH_CONFIG=$(shell set -o allexport && \
274-
source $(CURDIR)/.env && \
275-
set +o allexport && \
276-
python3 scripts/filestash/create_config.py))
277272
# Creating config for ops stack to $@
278-
# -> filestash config at $(TMP_PATH_TO_FILESTASH_CONFIG)
279273
ifdef ops_ci
280274
@$(shell \
281-
export TMP_PATH_TO_FILESTASH_CONFIG="${TMP_PATH_TO_FILESTASH_CONFIG}" && \
282275
scripts/docker/docker-compose-config.bash -e .env \
283276
services/docker-compose-ops-ci.yml \
284277
> $@ \
285278
)
286279
else
287280
@$(shell \
288-
export TMP_PATH_TO_FILESTASH_CONFIG="${TMP_PATH_TO_FILESTASH_CONFIG}" && \
289281
scripts/docker/docker-compose-config.bash -e .env \
290282
services/docker-compose-ops.yml \
291283
> $@ \
@@ -299,7 +291,6 @@ endif
299291
.deploy-ops: .stack-ops.yml
300292
# Deploy stack 'ops'
301293
ifndef ops_disabled
302-
# -> filestash config at $(TMP_PATH_TO_FILESTASH_CONFIG)
303294
docker stack deploy --with-registry-auth -c $< ops
304295
else
305296
@echo "Explicitly disabled with ops_disabled flag in CLI"
@@ -328,7 +319,6 @@ printf "$$rows" "Invitations" "http://$(get_my_ip).nip.io:8008/dev/doc" $${INVIT
328319
printf "$$rows" "Payments" "http://$(get_my_ip).nip.io:8011/dev/doc" $${PAYMENTS_USERNAME} $${PAYMENTS_PASSWORD};\
329320
printf "$$rows" "Rabbit Dashboard" "http://$(get_my_ip).nip.io:15672" admin adminadmin;\
330321
printf "$$rows" "Traefik Dashboard" "http://$(get_my_ip).nip.io:8080/dashboard/";\
331-
printf "$$rows" "Storage S3 Filestash" "http://$(get_my_ip).nip.io:9002" 12345678 12345678;\
332322
printf "$$rows" "Storage S3 Minio" "http://$(get_my_ip).nip.io:9001" 12345678 12345678;\
333323

334324
printf "\n%s\n" "⚠️ if a DNS is not used (as displayed above), the interactive services started via dynamic-sidecar";\
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# pylint: disable=redefined-outer-name
2+
# pylint: disable=unused-argument
3+
# pylint: disable=unused-import
4+
5+
6+
import contextlib
7+
import typing
8+
9+
import aioboto3
10+
import pytest
11+
from aiobotocore.session import ClientCreatorContext
12+
from botocore.client import Config
13+
from settings_library.s3 import S3Settings
14+
from types_aiobotocore_s3 import S3Client
15+
16+
17+
@pytest.fixture
18+
def s3_settings() -> S3Settings:
19+
return S3Settings.create_from_envs()
20+
21+
22+
@pytest.fixture
23+
async def s3_client(s3_settings: S3Settings) -> typing.AsyncIterator[S3Client]:
24+
session = aioboto3.Session()
25+
exit_stack = contextlib.AsyncExitStack()
26+
session_client = session.client(
27+
"s3",
28+
endpoint_url=s3_settings.S3_ENDPOINT,
29+
aws_access_key_id=s3_settings.S3_ACCESS_KEY,
30+
aws_secret_access_key=s3_settings.S3_SECRET_KEY,
31+
aws_session_token=s3_settings.S3_ACCESS_TOKEN,
32+
region_name=s3_settings.S3_REGION,
33+
config=Config(signature_version="s3v4"),
34+
)
35+
assert isinstance(session_client, ClientCreatorContext)
36+
client = typing.cast(S3Client, await exit_stack.enter_async_context(session_client))
37+
38+
yield client
39+
40+
await exit_stack.aclose()
41+
42+
43+
async def _empty_bucket(s3_client: S3Client, bucket_name: str) -> None:
44+
# List object versions
45+
response = await s3_client.list_object_versions(Bucket=bucket_name)
46+
47+
# Delete all object versions
48+
for version in response.get("Versions", []):
49+
assert "Key" in version
50+
assert "VersionId" in version
51+
await s3_client.delete_object(
52+
Bucket=bucket_name, Key=version["Key"], VersionId=version["VersionId"]
53+
)
54+
55+
# Delete all delete markers
56+
for marker in response.get("DeleteMarkers", []):
57+
assert "Key" in marker
58+
assert "VersionId" in marker
59+
await s3_client.delete_object(
60+
Bucket=bucket_name, Key=marker["Key"], VersionId=marker["VersionId"]
61+
)
62+
63+
# Delete remaining objects in the bucket
64+
response = await s3_client.list_objects(Bucket=bucket_name)
65+
for obj in response.get("Contents", []):
66+
assert "Key" in obj
67+
await s3_client.delete_object(Bucket=bucket_name, Key=obj["Key"])
68+
69+
70+
@pytest.fixture
71+
async def s3_bucket(
72+
s3_settings: S3Settings, s3_client: S3Client
73+
) -> typing.AsyncIterator[str]:
74+
bucket_name = s3_settings.S3_BUCKET_NAME
75+
76+
response = await s3_client.list_buckets()
77+
bucket_exists = bucket_name in [
78+
bucket_struct.get("Name") for bucket_struct in response["Buckets"]
79+
]
80+
if bucket_exists:
81+
await _empty_bucket(s3_client, bucket_name)
82+
83+
if not bucket_exists:
84+
await s3_client.create_bucket(Bucket=bucket_name)
85+
response = await s3_client.list_buckets()
86+
assert response["Buckets"]
87+
assert bucket_name in [
88+
bucket_struct.get("Name") for bucket_struct in response["Buckets"]
89+
], f"failed creating {bucket_name}"
90+
91+
yield bucket_name
92+
93+
await _empty_bucket(s3_client, bucket_name)
94+
95+
96+
@pytest.fixture
97+
async def with_bucket_versioning_enabled(s3_client: S3Client, s3_bucket: str) -> str:
98+
await s3_client.put_bucket_versioning(
99+
Bucket=s3_bucket,
100+
VersioningConfiguration={"MFADelete": "Disabled", "Status": "Enabled"},
101+
)
102+
return s3_bucket

packages/pytest-simcore/src/pytest_simcore/aws_server.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import pytest
88
import requests
99
from aiohttp.test_utils import unused_port
10+
from faker import Faker
1011
from moto.server import ThreadedMotoServer
1112
from settings_library.ec2 import EC2Settings
13+
from settings_library.s3 import S3Settings
1214

1315
from .helpers.utils_envs import EnvVarsDict, setenvs_from_dict
1416
from .helpers.utils_host import get_localhost_ip
@@ -71,16 +73,22 @@ def mocked_ec2_server_envs(
7173

7274

7375
@pytest.fixture
74-
async def mocked_s3_server_envs(
75-
mocked_aws_server: ThreadedMotoServer,
76-
reset_aws_server_state: None,
76+
def mocked_s3_server_settings(
77+
mocked_aws_server: ThreadedMotoServer, reset_aws_server_state: None, faker: Faker
78+
) -> S3Settings:
79+
return S3Settings(
80+
S3_ACCESS_KEY="xxx",
81+
S3_ENDPOINT=f"http://{mocked_aws_server._ip_address}:{mocked_aws_server._port}", # pylint: disable=protected-access # noqa: SLF001
82+
S3_SECRET_KEY="xxx", # noqa: S106
83+
S3_BUCKET_NAME=f"pytest{faker.pystr().lower()}",
84+
S3_SECURE=False,
85+
)
86+
87+
88+
@pytest.fixture
89+
def mocked_s3_server_envs(
90+
mocked_s3_server_settings: S3Settings,
7791
monkeypatch: pytest.MonkeyPatch,
7892
) -> EnvVarsDict:
79-
changed_envs = {
80-
"S3_SECURE": "false",
81-
"S3_ENDPOINT": f"{mocked_aws_server._ip_address}:{mocked_aws_server._port}", # pylint: disable=protected-access # noqa: SLF001
82-
"S3_ACCESS_KEY": "xxx",
83-
"S3_SECRET_KEY": "xxx",
84-
"S3_BUCKET_NAME": "pytestbucket",
85-
}
93+
changed_envs: EnvVarsDict = mocked_s3_server_settings.dict(exclude_unset=True)
8694
return setenvs_from_dict(monkeypatch, changed_envs)

packages/pytest-simcore/src/pytest_simcore/docker_compose.py

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import os
1414
import re
1515
import shutil
16-
import subprocess
1716
import sys
1817
from collections.abc import Iterator
1918
from copy import deepcopy
@@ -82,6 +81,9 @@ def testing_environ_vars(env_devel_file: Path) -> EnvVarsDict:
8281
if "DOCKER_IMAGE_TAG" not in os.environ:
8382
env_devel["DOCKER_IMAGE_TAG"] = "production"
8483

84+
# ensure we do not use the bucket of simcore or so
85+
env_devel["S3_BUCKET_NAME"] = "pytestbucket"
86+
8587
return {key: value for key, value in env_devel.items() if value is not None}
8688

8789

@@ -166,39 +168,12 @@ def simcore_docker_compose(
166168
return compose_specs
167169

168170

169-
@pytest.fixture(scope="module")
170-
def inject_filestash_config_path_env(
171-
osparc_simcore_scripts_dir: Path,
172-
env_file_for_testing: Path,
173-
) -> EnvVarsDict:
174-
create_filestash_config_py = (
175-
osparc_simcore_scripts_dir / "filestash" / "create_config.py"
176-
)
177-
178-
# ensures .env at git_root_dir, which will be used as current directory
179-
assert env_file_for_testing.exists()
180-
env_values = dotenv_values(env_file_for_testing)
181-
182-
process = subprocess.run(
183-
["python3", f"{create_filestash_config_py}"],
184-
shell=False,
185-
check=True,
186-
stdout=subprocess.PIPE,
187-
env=env_values,
188-
)
189-
filestash_config_json_path = Path(process.stdout.decode("utf-8").strip())
190-
assert filestash_config_json_path.exists()
191-
192-
return {"TMP_PATH_TO_FILESTASH_CONFIG": f"{filestash_config_json_path}"}
193-
194-
195171
@pytest.fixture(scope="module")
196172
def ops_docker_compose(
197173
osparc_simcore_root_dir: Path,
198174
osparc_simcore_scripts_dir: Path,
199175
env_file_for_testing: Path,
200176
temp_folder: Path,
201-
inject_filestash_config_path_env: dict[str, str],
202177
) -> dict[str, Any]:
203178
"""Filters only services in docker-compose-ops.yml and returns yaml data
204179
@@ -219,7 +194,6 @@ def ops_docker_compose(
219194
docker_compose_paths=docker_compose_path,
220195
env_file_path=env_file_for_testing,
221196
destination_path=temp_folder / "ops_docker_compose.yml",
222-
additional_envs=inject_filestash_config_path_env,
223197
)
224198
# NOTE: do not add indent. Copy&Paste log into editor instead
225199
print(
@@ -277,7 +251,7 @@ def ops_docker_compose_file(
277251
docker_compose_path = Path(temp_folder / "ops_docker_compose.filtered.yml")
278252

279253
# these services are useless when running in the CI
280-
ops_view_only_services = ["adminer", "redis-commander", "portainer", "filestash"]
254+
ops_view_only_services = ["adminer", "redis-commander", "portainer"]
281255
if "CI" in os.environ:
282256
print(
283257
f"WARNING: Services such as {ops_view_only_services!r} are removed from the stack when running in the CI"

packages/pytest-simcore/src/pytest_simcore/helpers/utils_envs.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ def setenvs_from_dict(
2929
) -> EnvVarsDict:
3030
for key, value in envs.items():
3131
assert isinstance(key, str)
32-
assert value is not None # None keys cannot be is defined w/o value
32+
assert (
33+
value is not None
34+
), f"{key=},{value=}" # None keys cannot be is defined w/o value
35+
converted_value = value
36+
if isinstance(value, bool):
37+
converted_value = f"{'true' if value else 'false'}"
3338
assert isinstance(
34-
value, str
35-
), "client MUST explicitly stringify values since some cannot be done automatically e.g. json-like values"
39+
converted_value, str
40+
), f"client MUST explicitly stringify values since some cannot be done automatically e.g. json-like values. problematic {key=},{value=}"
3641

37-
monkeypatch.setenv(key, value)
42+
monkeypatch.setenv(key, converted_value)
3843
return deepcopy(envs)
3944

4045

@@ -72,7 +77,7 @@ def delenvs_from_envfile(
7277
monkeypatch: pytest.MonkeyPatch,
7378
content_or_path: str | Path,
7479
raising: bool,
75-
**dotenv_kwags
80+
**dotenv_kwags,
7681
) -> EnvVarsDict:
7782
"""Batch monkeypatch.delenv(...) on all env vars in an envfile"""
7883
envs = load_dotenv(content_or_path, **dotenv_kwags)

0 commit comments

Comments
 (0)