From b425a5f1f83cebd103203bc8cd084d23c6f250f7 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Fri, 28 Jun 2024 16:28:30 +0200 Subject: [PATCH 01/18] add initial file for metamodeling load test --- .../locust_files/metamodeling/workflow.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/performance/locust_files/metamodeling/workflow.py diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py new file mode 100644 index 00000000000..65054a4b7f5 --- /dev/null +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -0,0 +1,26 @@ +from locust import HttpUser +from urllib3 import PoolManager, Retry + + +class MetaModelingUser(HttpUser): + def __init__(self, *args, **kwargs): + retry_strategy = Retry( + total=4, + backoff_factor=4.0, + status_forcelist={429, 503, 504}, + allowed_methods={ + "DELETE", + "GET", + "HEAD", + "OPTIONS", + "PUT", + "TRACE", + "POST", + "PATCH", + "CONNECT", + }, + respect_retry_after_header=True, + raise_on_status=True, + ) + pool_manager = PoolManager(key_retries=retry_strategy) + super().__init__(*args, **kwargs, pool_manager=pool_manager) From bdbf26513cb27dd922669a7cba314001e6414daa Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Fri, 28 Jun 2024 16:30:45 +0200 Subject: [PATCH 02/18] minor change --- tests/performance/locust_files/metamodeling/workflow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index 65054a4b7f5..cf97f7737a9 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -22,5 +22,6 @@ def __init__(self, *args, **kwargs): respect_retry_after_header=True, raise_on_status=True, ) - pool_manager = PoolManager(key_retries=retry_strategy) - super().__init__(*args, **kwargs, pool_manager=pool_manager) + super().__init__( + *args, **kwargs, pool_manager=PoolManager(key_retries=retry_strategy) + ) From 0e7353b53853df332ab1aaaf39d88156fb974ab9 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Fri, 28 Jun 2024 16:59:06 +0200 Subject: [PATCH 03/18] catch username and password from env --- .../locust_files/metamodeling/workflow.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index cf97f7737a9..9744d5c4f5c 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -1,9 +1,19 @@ -from locust import HttpUser +from locust import HttpUser, task +from pydantic import Field +from pydantic_settings import BaseSettings +from requests.auth import HTTPBasicAuth from urllib3 import PoolManager, Retry +class UserSettings(BaseSettings): + username: str = Field(default=...) + password: str = Field(default=...) + + class MetaModelingUser(HttpUser): def __init__(self, *args, **kwargs): + config = UserSettings() + self._auth = HTTPBasicAuth(username=config.username, password=config.password) retry_strategy = Retry( total=4, backoff_factor=4.0, @@ -25,3 +35,11 @@ def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs, pool_manager=PoolManager(key_retries=retry_strategy) ) + + def on_start(self) -> None: + response = self.client.get("/v0/me", auth=self._auth) + response.raise_for_status() + + @task + def create_and_run_job(self): + self.client.get("/v0/me", auth=self._auth) From 2afeb3c59beafc99fe3d2d8170698035d32ac227 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Fri, 28 Jun 2024 17:32:26 +0200 Subject: [PATCH 04/18] start using env vars --- tests/performance/Makefile | 3 +-- tests/performance/docker-compose.yml | 10 +++++----- .../performance/locust_files/metamodeling/workflow.py | 10 ++++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/performance/Makefile b/tests/performance/Makefile index 38137391643..0d42bfa9fd8 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -45,6 +45,5 @@ down: ## stops and removes osparc locust containers test: ## runs osparc locust with target=locust_test_file.py in headless mode for a minute. Will fail if 5% more fail requests or average response time is above 50ms, optional host can be set @$(call check_defined, target, please define target file when calling $@ - e.g. ```make $@ target=MY_LOCUST_FILE.py```) @export LOCUST_FILE=$(target); \ - export TARGET_URL=$(if $(host),$(host),"http://$(get_my_ip):9081"); \ - export LOCUST_OPTIONS="--headless --print-stats --users=100 --spawn-rate=20 --run-time=1m --check-fail-ratio=0.01 --check-avg-response-time=$(if $(resp_time),$(resp_time),200)"; \ + @export ENV_FILE=$(dirname ${LOCUST_FILE}); \ docker compose --file docker-compose.yml up --scale worker=4 --exit-code-from=master diff --git a/tests/performance/docker-compose.yml b/tests/performance/docker-compose.yml index 2623454210e..b95ad4c691c 100644 --- a/tests/performance/docker-compose.yml +++ b/tests/performance/docker-compose.yml @@ -7,14 +7,14 @@ services: - ./locust_files:/mnt/locust - ./locust_report:/reporting command: > - -f /mnt/locust/${LOCUST_FILE} --host ${TARGET_URL} --html - /reporting/locust_html.html ${LOCUST_OPTIONS} --master + -f /mnt/locust/${LOCUST_FILE} --html /reporting/locust_html.html --master + env_file: + - ${ENV_FILE} worker: image: itisfoundation/locust:${LOCUST_VERSION} volumes: - ./locust_files:/mnt/locust command: -f /mnt/locust/${LOCUST_FILE} --worker --master-host master - environment: - - SC_USER_NAME=${SC_USER_NAME} - - SC_PASSWORD=${SC_PASSWORD} + env_file: + - ${ENV_FILE} diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index 9744d5c4f5c..fd192cce0f5 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -1,19 +1,21 @@ from locust import HttpUser, task from pydantic import Field -from pydantic_settings import BaseSettings +from pydantic_settings import BaseSettings, SettingsConfigDict from requests.auth import HTTPBasicAuth from urllib3 import PoolManager, Retry class UserSettings(BaseSettings): - username: str = Field(default=...) - password: str = Field(default=...) + key: str = Field(default=...) + secret: str = Field(default=...) + + model_config = SettingsConfigDict(env_prefix="osparc_api_") class MetaModelingUser(HttpUser): def __init__(self, *args, **kwargs): config = UserSettings() - self._auth = HTTPBasicAuth(username=config.username, password=config.password) + self._auth = HTTPBasicAuth(username=config.key, password=config.secret) retry_strategy = Retry( total=4, backoff_factor=4.0, From a634060c339639ac82b7b1678e42b3decf29b6ce Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 09:49:02 +0200 Subject: [PATCH 05/18] fixes --- tests/performance/Makefile | 3 ++- tests/performance/docker-compose.yml | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/performance/Makefile b/tests/performance/Makefile index 0d42bfa9fd8..7806bef241f 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -45,5 +45,6 @@ down: ## stops and removes osparc locust containers test: ## runs osparc locust with target=locust_test_file.py in headless mode for a minute. Will fail if 5% more fail requests or average response time is above 50ms, optional host can be set @$(call check_defined, target, please define target file when calling $@ - e.g. ```make $@ target=MY_LOCUST_FILE.py```) @export LOCUST_FILE=$(target); \ - @export ENV_FILE=$(dirname ${LOCUST_FILE}); \ + echo "LOCUST_FILE=$${LOCUST_FILE}";\ + export ENV_FILE=$(dirname $(realpath locust_files/$${LOCUST_FILE}))/.env; \ docker compose --file docker-compose.yml up --scale worker=4 --exit-code-from=master diff --git a/tests/performance/docker-compose.yml b/tests/performance/docker-compose.yml index b95ad4c691c..a71ee43b26f 100644 --- a/tests/performance/docker-compose.yml +++ b/tests/performance/docker-compose.yml @@ -9,12 +9,10 @@ services: command: > -f /mnt/locust/${LOCUST_FILE} --html /reporting/locust_html.html --master env_file: - - ${ENV_FILE} + - ./locust_files/${ENV_FILE} worker: image: itisfoundation/locust:${LOCUST_VERSION} volumes: - ./locust_files:/mnt/locust command: -f /mnt/locust/${LOCUST_FILE} --worker --master-host master - env_file: - - ${ENV_FILE} From c155da3c459b33befe3a425dc330ca43df056d58 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 11:10:42 +0200 Subject: [PATCH 06/18] update locust version --- tests/performance/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/Makefile b/tests/performance/Makefile index 7806bef241f..8a61cb476c0 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -3,7 +3,7 @@ # include ../../scripts/common.Makefile -LOCUST_VERSION=2.5.1 +LOCUST_VERSION=2.29.1 export LOCUST_VERSION # UTILS From 91df612b60ab6b9580b61f741e9f372784b16298 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 11:26:54 +0200 Subject: [PATCH 07/18] add .env-devel files --- tests/performance/Makefile | 2 +- tests/performance/locust_files/.env-devel | 11 +++++++++++ .../performance/locust_files/metamodeling/.env-devel | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/performance/locust_files/.env-devel create mode 100644 tests/performance/locust_files/metamodeling/.env-devel diff --git a/tests/performance/Makefile b/tests/performance/Makefile index 8a61cb476c0..cfd7be61d4b 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -45,6 +45,6 @@ down: ## stops and removes osparc locust containers test: ## runs osparc locust with target=locust_test_file.py in headless mode for a minute. Will fail if 5% more fail requests or average response time is above 50ms, optional host can be set @$(call check_defined, target, please define target file when calling $@ - e.g. ```make $@ target=MY_LOCUST_FILE.py```) @export LOCUST_FILE=$(target); \ - echo "LOCUST_FILE=$${LOCUST_FILE}";\ export ENV_FILE=$(dirname $(realpath locust_files/$${LOCUST_FILE}))/.env; \ + if [ ! -f $${ENV_FILE} ]; then cp $(dirname $${ENV_FILE}/.env-devel $${ENV_FILE}); fi \; docker compose --file docker-compose.yml up --scale worker=4 --exit-code-from=master diff --git a/tests/performance/locust_files/.env-devel b/tests/performance/locust_files/.env-devel new file mode 100644 index 00000000000..39c32b6a3e4 --- /dev/null +++ b/tests/performance/locust_files/.env-devel @@ -0,0 +1,11 @@ +# user +SC_USER_NAME= +SC_PASSWORD= + +# locust settings +LOCUST_HOST=http://10.43.103.193.nip.io:8005 +LOCUST_USERS=100 +LOCUST_HEADLESS=true +LOCUST_PRINT_STATS=true +LOCUST_SPAWN_RATE=20 +LOCUST_RUN_TIME=1m diff --git a/tests/performance/locust_files/metamodeling/.env-devel b/tests/performance/locust_files/metamodeling/.env-devel new file mode 100644 index 00000000000..bf545fd12df --- /dev/null +++ b/tests/performance/locust_files/metamodeling/.env-devel @@ -0,0 +1,11 @@ +# user +OSPARC_API_KEY= +OSPARC_API_SECRET= + +# locust settings +LOCUST_HOST=http://10.43.103.193:9081 +LOCUST_USERS=100 +LOCUST_HEADLESS=true +LOCUST_PRINT_STATS=true +LOCUST_SPAWN_RATE=20 +LOCUST_RUN_TIME=1m From 242787d171e71e9d80d3358a7581959b0a1e6f34 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 11:39:38 +0200 Subject: [PATCH 08/18] make setup work for catalog_services.py --- tests/performance/Makefile | 4 ++-- tests/performance/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/performance/Makefile b/tests/performance/Makefile index cfd7be61d4b..f12827f098c 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -45,6 +45,6 @@ down: ## stops and removes osparc locust containers test: ## runs osparc locust with target=locust_test_file.py in headless mode for a minute. Will fail if 5% more fail requests or average response time is above 50ms, optional host can be set @$(call check_defined, target, please define target file when calling $@ - e.g. ```make $@ target=MY_LOCUST_FILE.py```) @export LOCUST_FILE=$(target); \ - export ENV_FILE=$(dirname $(realpath locust_files/$${LOCUST_FILE}))/.env; \ - if [ ! -f $${ENV_FILE} ]; then cp $(dirname $${ENV_FILE}/.env-devel $${ENV_FILE}); fi \; + export ENV_FILE=$$(dirname $$(realpath locust_files/$${LOCUST_FILE}))/.env; \ + if [ ! -f $${ENV_FILE} ]; then cp $$(dirname $${ENV_FILE})/.env-devel $${ENV_FILE}; fi; \ docker compose --file docker-compose.yml up --scale worker=4 --exit-code-from=master diff --git a/tests/performance/docker-compose.yml b/tests/performance/docker-compose.yml index a71ee43b26f..30dc25ba9f7 100644 --- a/tests/performance/docker-compose.yml +++ b/tests/performance/docker-compose.yml @@ -9,7 +9,7 @@ services: command: > -f /mnt/locust/${LOCUST_FILE} --html /reporting/locust_html.html --master env_file: - - ./locust_files/${ENV_FILE} + - ${ENV_FILE} worker: image: itisfoundation/locust:${LOCUST_VERSION} From ebc3fe0ea787b74240c32513f867b1029483e3b6 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 11:40:35 +0200 Subject: [PATCH 09/18] improve doc --- tests/performance/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/Makefile b/tests/performance/Makefile index f12827f098c..dfce104fb36 100644 --- a/tests/performance/Makefile +++ b/tests/performance/Makefile @@ -42,7 +42,7 @@ down: ## stops and removes osparc locust containers docker compose --file docker-compose.yml down .PHONY: test -test: ## runs osparc locust with target=locust_test_file.py in headless mode for a minute. Will fail if 5% more fail requests or average response time is above 50ms, optional host can be set +test: ## runs osparc locust. locust and test confiuration are specified in .env file next to target file @$(call check_defined, target, please define target file when calling $@ - e.g. ```make $@ target=MY_LOCUST_FILE.py```) @export LOCUST_FILE=$(target); \ export ENV_FILE=$$(dirname $$(realpath locust_files/$${LOCUST_FILE}))/.env; \ From e7d1d6d49a68e6151143463c024cb3728ee32d36 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 11:51:49 +0200 Subject: [PATCH 10/18] update locust image --- tests/performance/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/Dockerfile b/tests/performance/Dockerfile index 634e2d6776a..ac556948a18 100644 --- a/tests/performance/Dockerfile +++ b/tests/performance/Dockerfile @@ -6,6 +6,8 @@ FROM locustio/locust:${LOCUST_VERSION} RUN pip3 --version && \ pip3 install \ faker \ + pydantic \ + pydantic-settings \ python-dotenv \ locust-plugins==2.1.1 &&\ pip3 freeze --verbose From 9f5c7b161a53eff6f27bd3e40016718f33ea80d8 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 13:12:47 +0200 Subject: [PATCH 11/18] can now run metamodeling workflow --- tests/performance/docker-compose.yml | 2 ++ tests/performance/locust_files/metamodeling/workflow.py | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance/docker-compose.yml b/tests/performance/docker-compose.yml index 30dc25ba9f7..b95ad4c691c 100644 --- a/tests/performance/docker-compose.yml +++ b/tests/performance/docker-compose.yml @@ -16,3 +16,5 @@ services: volumes: - ./locust_files:/mnt/locust command: -f /mnt/locust/${LOCUST_FILE} --worker --master-host master + env_file: + - ${ENV_FILE} diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index fd192cce0f5..35ec1ae0e67 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -34,13 +34,11 @@ def __init__(self, *args, **kwargs): respect_retry_after_header=True, raise_on_status=True, ) - super().__init__( - *args, **kwargs, pool_manager=PoolManager(key_retries=retry_strategy) - ) + self.pool_manager = PoolManager(retries=retry_strategy) + super().__init__(*args, **kwargs) def on_start(self) -> None: response = self.client.get("/v0/me", auth=self._auth) - response.raise_for_status() @task def create_and_run_job(self): From 9caf1b4a6c2a230b1dda2a1f13d166fa8e6ad2d5 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 14:08:53 +0200 Subject: [PATCH 12/18] add template id --- .../locust_files/metamodeling/.env-devel | 1 + .../locust_files/metamodeling/workflow.py | 51 ++++++++++++++++--- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/tests/performance/locust_files/metamodeling/.env-devel b/tests/performance/locust_files/metamodeling/.env-devel index bf545fd12df..8d39422a4b8 100644 --- a/tests/performance/locust_files/metamodeling/.env-devel +++ b/tests/performance/locust_files/metamodeling/.env-devel @@ -1,6 +1,7 @@ # user OSPARC_API_KEY= OSPARC_API_SECRET= +TEMPLATE_UUID= # locust settings LOCUST_HOST=http://10.43.103.193:9081 diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index 35ec1ae0e67..c57406f525a 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -1,21 +1,28 @@ +from pathlib import Path +from tempfile import TemporaryDirectory +from uuid import UUID + from locust import HttpUser, task from pydantic import Field -from pydantic_settings import BaseSettings, SettingsConfigDict +from pydantic_settings import BaseSettings from requests.auth import HTTPBasicAuth from urllib3 import PoolManager, Retry class UserSettings(BaseSettings): - key: str = Field(default=...) - secret: str = Field(default=...) + osparc_api_key: str = Field(default=...) + osparc_api_secret: str = Field(default=...) - model_config = SettingsConfigDict(env_prefix="osparc_api_") + template_uuid: UUID = Field(default=...) class MetaModelingUser(HttpUser): def __init__(self, *args, **kwargs): - config = UserSettings() - self._auth = HTTPBasicAuth(username=config.key, password=config.secret) + self._user_settings = UserSettings() + self._auth = HTTPBasicAuth( + username=self._user_settings.osparc_api_key, + password=self._user_settings.osparc_api_secret, + ) retry_strategy = Retry( total=4, backoff_factor=4.0, @@ -35,11 +42,39 @@ def __init__(self, *args, **kwargs): raise_on_status=True, ) self.pool_manager = PoolManager(retries=retry_strategy) + super().__init__(*args, **kwargs) def on_start(self) -> None: - response = self.client.get("/v0/me", auth=self._auth) + self.client.get("/v0/me", auth=self._auth) # fail fast @task def create_and_run_job(self): - self.client.get("/v0/me", auth=self._auth) + with TemporaryDirectory() as tmp_dir: + file = Path(tmp_dir) / "input.json" + file.write_text( + """ + { + "f1": 3 + } + """ + ) + input_file_uuid = self.upload_file(file) + + response = self.client.post( + f"/v0/studies/{self._user_settings.template_uuid}/jobs", + json={ + "values": {"InputFile1": f"{input_file_uuid}"}, + }, + auth=self._auth, + ) + response.raise_for_status() + + def upload_file(self, file: Path) -> UUID: + assert file.is_file() + files = {"file": open(f"{file.resolve()}", "rb")} + response = self.client.put("/v0/files/content", files=files, auth=self._auth) + response.raise_for_status() + file_uuid = response.json().get("id") + assert file_uuid is not None + return UUID(file_uuid) From 594a87d3b0e5cbe98a9016f0bb22a99afa1f79b2 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 15:18:49 +0200 Subject: [PATCH 13/18] further additions to test --- tests/performance/Dockerfile | 1 + .../locust_files/metamodeling/workflow.py | 63 ++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/tests/performance/Dockerfile b/tests/performance/Dockerfile index ac556948a18..d1843031f4c 100644 --- a/tests/performance/Dockerfile +++ b/tests/performance/Dockerfile @@ -9,5 +9,6 @@ RUN pip3 --version && \ pydantic \ pydantic-settings \ python-dotenv \ + tenacity \ locust-plugins==2.1.1 &&\ pip3 freeze --verbose diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index c57406f525a..a8fa2ab4a24 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -1,13 +1,23 @@ +from datetime import timedelta from pathlib import Path from tempfile import TemporaryDirectory +from typing import Final from uuid import UUID from locust import HttpUser, task from pydantic import Field from pydantic_settings import BaseSettings from requests.auth import HTTPBasicAuth +from tenacity import ( + Retrying, + retry_if_exception_type, + stop_after_delay, + wait_exponential, +) from urllib3 import PoolManager, Retry +_MAX_WAIT_SECONDS: Final[int] = 60 + class UserSettings(BaseSettings): osparc_api_key: str = Field(default=...) @@ -47,9 +57,25 @@ def __init__(self, *args, **kwargs): def on_start(self) -> None: self.client.get("/v0/me", auth=self._auth) # fail fast + self._input_json_uuid = None + self._job_uuid = None + + def on_stop(self) -> None: + if self._input_json_uuid is not None: + response = self.client.delete( + f"/v0/files/{self._input_json_uuid}", name="/v0/files/[file_id]" + ) + response.raise_for_status() + if self._job_uuid is not None: + response = self.client.delete( + f"/v0/studies/{self._user_settings.template_uuid}/jobs/{self._job_uuid}", + name="/v0/studies/[study_id]/jobs/[job_id]", + ) + response.raise_for_status() @task def create_and_run_job(self): + # upload file with TemporaryDirectory() as tmp_dir: file = Path(tmp_dir) / "input.json" file.write_text( @@ -59,16 +85,49 @@ def create_and_run_job(self): } """ ) - input_file_uuid = self.upload_file(file) + self._input_json_uuid = self.upload_file(file) + # create job response = self.client.post( f"/v0/studies/{self._user_settings.template_uuid}/jobs", json={ - "values": {"InputFile1": f"{input_file_uuid}"}, + "values": {"InputFile1": f"{self._input_json_uuid}"}, }, auth=self._auth, + name="/v0/studies/[study_id]/jobs", + ) + response.raise_for_status() + job_uuid = response.json().get("id") + assert job_uuid is not None + self._job_uuid = UUID(job_uuid) + + # start job + response = self.client.post( + f"/v0/studies/{self._user_settings.template_uuid}/jobs/{self._job_uuid}:start", + auth=self._auth, + name="/v0/studies/[study_id]/jobs/[job_id]:start", ) response.raise_for_status() + state = response.json().get("state") + for attempt in Retrying( + stop=stop_after_delay(timedelta(seconds=_MAX_WAIT_SECONDS)), + wait=wait_exponential(), + retry=retry_if_exception_type(RuntimeError), + ): + with attempt: + response = self.client.post( + f"/v0/studies/{self._user_settings.template_uuid}/jobs/{self._job_uuid}:inspect", + auth=self._auth, + name="/v0/studies/[study_id]/jobs/[job_id]:inspect", + ) + response.raise_for_status() + state = response.json().get("state") + if not state in {"SUCCESS", "FAILED"}: + raise RuntimeError( + f"Computation not finished after attempt {attempt.retry_state.attempt_number}" + ) + + assert state == "SUCCESS" def upload_file(self, file: Path) -> UUID: assert file.is_file() From fb3d1479305cb1c2c3109b34c8239741ade92367 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 15:30:50 +0200 Subject: [PATCH 14/18] download outputs --- .../locust_files/metamodeling/workflow.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/locust_files/metamodeling/workflow.py b/tests/performance/locust_files/metamodeling/workflow.py index a8fa2ab4a24..a085719c795 100644 --- a/tests/performance/locust_files/metamodeling/workflow.py +++ b/tests/performance/locust_files/metamodeling/workflow.py @@ -129,6 +129,19 @@ def create_and_run_job(self): assert state == "SUCCESS" + response = self.client.post( + f"/v0/studies/{self._user_settings.template_uuid}/jobs/{self._job_uuid}/outputs", + auth=self._auth, + name="/v0/studies/[study_id]/jobs/[job_id]/outputs", + ) + response.raise_for_status() + results = response.json() + assert results is not None + output_file = results.get("OutputFile1") + assert output_file is not None + output_file_uuid = output_file.get("id") + assert output_file_uuid is not None + def upload_file(self, file: Path) -> UUID: assert file.is_file() files = {"file": open(f"{file.resolve()}", "rb")} From c7a8c2b7666e07006cd4464e0f12bf4fb19a4f01 Mon Sep 17 00:00:00 2001 From: Mads Bisgaard Date: Mon, 1 Jul 2024 15:45:07 +0200 Subject: [PATCH 15/18] document the load test --- .../locust_files/metamodeling/passer.py | 15 +++++++++++++++ .../metamodeling/study_template.png | Bin 0 -> 99265 bytes .../locust_files/metamodeling/workflow.py | 7 +++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/performance/locust_files/metamodeling/passer.py create mode 100644 tests/performance/locust_files/metamodeling/study_template.png diff --git a/tests/performance/locust_files/metamodeling/passer.py b/tests/performance/locust_files/metamodeling/passer.py new file mode 100644 index 00000000000..9e16f69e52d --- /dev/null +++ b/tests/performance/locust_files/metamodeling/passer.py @@ -0,0 +1,15 @@ +import json +import os +import pathlib as pl + +input_path = pl.Path(os.environ["INPUT_FOLDER"]) +output_path = pl.Path(os.environ["OUTPUT_FOLDER"]) + +input_file_path = input_path / "input.json" +output_file_path = output_path / "output.json" + +input_content = json.loads(input_file_path.read_text()) + +print(input_content) + +output_file_path.write_text(json.dumps(input_content)) diff --git a/tests/performance/locust_files/metamodeling/study_template.png b/tests/performance/locust_files/metamodeling/study_template.png new file mode 100644 index 0000000000000000000000000000000000000000..d1b498a54ec91ea0bf68a92f6c5eb63ec199bfa1 GIT binary patch literal 99265 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 Date: Tue, 2 Jul 2024 10:05:42 +0200 Subject: [PATCH 16/18] @pcrespov pr feedback --- tests/performance/Dockerfile | 4 ++-- tests/performance/locust_files/.env-devel | 6 ++--- .../locust_files/metamodeling/.env-devel | 8 +++---- .../locust_files/metamodeling/passer.py | 23 ++++++++++++------- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/performance/Dockerfile b/tests/performance/Dockerfile index d1843031f4c..36219fc25ad 100644 --- a/tests/performance/Dockerfile +++ b/tests/performance/Dockerfile @@ -6,9 +6,9 @@ FROM locustio/locust:${LOCUST_VERSION} RUN pip3 --version && \ pip3 install \ faker \ + locust-plugins==2.1.1 \ pydantic \ pydantic-settings \ python-dotenv \ - tenacity \ - locust-plugins==2.1.1 &&\ + tenacity && \ pip3 freeze --verbose diff --git a/tests/performance/locust_files/.env-devel b/tests/performance/locust_files/.env-devel index 39c32b6a3e4..a0828e4312a 100644 --- a/tests/performance/locust_files/.env-devel +++ b/tests/performance/locust_files/.env-devel @@ -1,9 +1,9 @@ # user -SC_USER_NAME= -SC_PASSWORD= +SC_USER_NAME= +SC_PASSWORD= # locust settings -LOCUST_HOST=http://10.43.103.193.nip.io:8005 +LOCUST_HOST= LOCUST_USERS=100 LOCUST_HEADLESS=true LOCUST_PRINT_STATS=true diff --git a/tests/performance/locust_files/metamodeling/.env-devel b/tests/performance/locust_files/metamodeling/.env-devel index 8d39422a4b8..84629c235d7 100644 --- a/tests/performance/locust_files/metamodeling/.env-devel +++ b/tests/performance/locust_files/metamodeling/.env-devel @@ -1,10 +1,10 @@ # user -OSPARC_API_KEY= -OSPARC_API_SECRET= -TEMPLATE_UUID= +OSPARC_API_KEY= +OSPARC_API_SECRET= +TEMPLATE_UUID=