Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔨 Fix: e2e Performance Tests in CI #6707

Merged
merged 4 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions tests/performance/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export ENV_FILE
NETWORK_NAME=dashboards_timenet

# UTILS
get_my_ip := $(shell (hostname --all-ip-addresses || hostname -i) 2>/dev/null | cut --delimiter=" " --fields=1)
# NOTE: keep short arguments for `cut` so it works in both BusyBox (alpine) AND Ubuntu
get_my_ip := $(shell (hostname --all-ip-addresses || hostname -i) 2>/dev/null | cut -d " " -f 1)

# Check that given variables are set and all have non-empty values,
# die with an error otherwise.
Expand All @@ -28,6 +29,7 @@ __check_defined = \
$(error Undefined $1$(if $2, ($2))))



.PHONY: build
build: ## builds distributed osparc locust docker image
docker \
Expand All @@ -42,6 +44,8 @@ build: ## builds distributed osparc locust docker image
push:
docker push itisfoundation/locust:$(LOCUST_VERSION)



.PHONY: down
down: ## stops and removes osparc locust containers
docker compose --file docker-compose.yml down
Expand All @@ -55,6 +59,8 @@ test: ## runs osparc locust. Locust and test configuration are specified in ENV_
fi
docker compose --file docker-compose.yml up --scale worker=4 --exit-code-from=master



.PHONY: dashboards-up dashboards-down

dashboards-up: ## Create Grafana dashboard for inspecting locust results. See dashboard on localhost:3000
Expand All @@ -68,6 +74,8 @@ dashboards-up: ## Create Grafana dashboard for inspecting locust results. See da
dashboards-down:
@locust-compose down



.PHONY: install-ci install-dev

install-dev:
Expand All @@ -80,4 +88,4 @@ install-ci:
.PHONY: config
config:
@$(call check_defined, input, please define inputs when calling $@ - e.g. ```make $@ input="--help"```)
@uv run locust_settings.py $(input) | tee .env
@uv run locust_settings.py $(input) | tee "${ENV_FILE}"
4 changes: 2 additions & 2 deletions tests/performance/locust_files/platform_ping_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
assert locust_plugins # nosec


class LocustAuth(BaseSettings):
class MonitoringBasicAuth(BaseSettings):
SC_USER_NAME: str = Field(default=..., examples=["<your username>"])
SC_PASSWORD: str = Field(default=..., examples=["<your password>"])


class WebApiUser(FastHttpUser):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
_auth = LocustAuth()
_auth = MonitoringBasicAuth()
self.auth = (
_auth.SC_USER_NAME,
_auth.SC_PASSWORD,
Expand Down
50 changes: 48 additions & 2 deletions tests/performance/locust_settings.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "parse",
# "pydantic",
# "pydantic-settings",
# ]
# ///
# pylint: disable=unused-argument
# pylint: disable=no-self-use
# pylint: disable=no-name-in-module

import importlib.util
import inspect
import json
from datetime import timedelta
from pathlib import Path
from types import ModuleType
from typing import Final

from parse import Result, parse
Expand All @@ -26,6 +37,37 @@
assert _LOCUST_FILES_DIR.is_dir()


def _check_load_and_instantiate_settings_classes(file_path: str):
module_name = Path(file_path).stem
spec = importlib.util.spec_from_file_location(module_name, file_path)
if spec is None or spec.loader is None:
msg = f"Invalid {file_path=}"
raise ValueError(msg)

module: ModuleType = importlib.util.module_from_spec(spec)

# Execute the module in its own namespace
try:
spec.loader.exec_module(module)
except Exception as e:
msg = f"Failed to load module {module_name} from {file_path}"
raise ValueError(msg) from e

# Filter subclasses of BaseSettings
settings_classes = [
obj
for _, obj in inspect.getmembers(module, inspect.isclass)
if issubclass(obj, BaseSettings) and obj is not BaseSettings
]

for settings_class in settings_classes:
try:
settings_class()
except Exception as e:
msg = f"Missing env vars for {settings_class.__name__} in {file_path=}: {e}"
raise ValueError(msg) from e


class LocustSettings(BaseSettings):
model_config = SettingsConfigDict(cli_parse_args=True)

Expand All @@ -44,8 +86,8 @@ class LocustSettings(BaseSettings):
LOCUST_RUN_TIME: timedelta
LOCUST_SPAWN_RATE: PositiveInt = Field(default=20)

# Options for Timescale + Grafana Dashboards
# SEE https://github.com/SvenskaSpel/locust-plugins/blob/master/locust_plugins/timescale/
# Timescale: Log and graph results using TimescaleDB and Grafana dashboards
# SEE https://github.com/SvenskaSpel/locust-plugins/tree/master/locust_plugins/dashboards
#
LOCUST_TIMESCALE: NonNegativeInt = Field(
default=1,
Expand Down Expand Up @@ -87,6 +129,10 @@ def _validate_locust_file(cls, v: Path) -> Path:
if not v.is_relative_to(_LOCUST_FILES_DIR):
msg = f"{v} must be a test file relative to {_LOCUST_FILES_DIR}"
raise ValueError(msg)

# NOTE: CHECK that all the env-vars are defined for this test
# _check_load_and_instantiate_settings_classes(f"{v}")

return v.relative_to(_TEST_DIR)

@field_serializer("LOCUST_RUN_TIME")
Expand Down
Loading