Skip to content

Commit 2c6c4a5

Browse files
committed
warns if all
1 parent 57ff7c0 commit 2c6c4a5

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

services/autoscaling/src/simcore_service_autoscaling/core/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class Config(EC2Settings.Config):
6060
class EC2InstancesSettings(BaseCustomSettings):
6161
EC2_INSTANCES_ALLOWED_TYPES: dict[str, EC2InstanceBootSpecific] = Field(
6262
...,
63-
description="Defines which EC2 instances are considered as candidates for new EC2 instance and their respective boot specific parameters",
63+
description="Defines which EC2 instances are considered as candidates for new EC2 instance and their respective boot specific parameters"
64+
"WARNING: if empty, all available ec2 instances are allowed",
6465
)
6566

6667
EC2_INSTANCES_KEY_NAME: str = Field(

services/autoscaling/src/simcore_service_autoscaling/modules/auto_scaling_core.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import datetime
55
import itertools
66
import logging
7+
import typing
78
from typing import Final, cast
89

910
import arrow
@@ -333,24 +334,31 @@ async def _sorted_allowed_instance_types(app: FastAPI) -> list[EC2InstanceType]:
333334
ec2_client = get_ec2_client(app)
334335

335336
# some instances might be able to run several tasks
337+
selected_names = list(
338+
app_settings.AUTOSCALING_EC2_INSTANCES.EC2_INSTANCES_ALLOWED_TYPES
339+
)
340+
assert set(selected_names).issubset(typing.get_args(InstanceTypeType)) # nosec
341+
336342
allowed_instance_types: list[
337343
EC2InstanceType
338344
] = await ec2_client.get_ec2_instance_capabilities(
339-
cast(
340-
set[InstanceTypeType],
341-
set(
342-
app_settings.AUTOSCALING_EC2_INSTANCES.EC2_INSTANCES_ALLOWED_TYPES,
343-
),
344-
)
345+
cast(set[InstanceTypeType], set(selected_names))
345346
)
346347

347-
def _sort_according_to_allowed_types(instance_type: EC2InstanceType) -> int:
348-
assert app_settings.AUTOSCALING_EC2_INSTANCES # nosec
349-
return list(
350-
app_settings.AUTOSCALING_EC2_INSTANCES.EC2_INSTANCES_ALLOWED_TYPES
351-
).index(f"{instance_type.name}")
348+
if selected_names:
352349

353-
allowed_instance_types.sort(key=_sort_according_to_allowed_types)
350+
def _as_selection(instance_type: EC2InstanceType) -> int:
351+
assert app_settings.AUTOSCALING_EC2_INSTANCES # nosec
352+
return selected_names.index(f"{instance_type.name}")
353+
354+
allowed_instance_types.sort(key=_as_selection)
355+
else:
356+
# NOTE An empty set to get_ec2_instance_capabilities it will return ALL of the instances
357+
_logger.warning(
358+
"All %s instances are allowed since EC2_INSTANCES_ALLOWED_TYPES is set to empty (=%s)",
359+
len(allowed_instance_types),
360+
selected_names,
361+
)
354362
return allowed_instance_types
355363

356364

@@ -1131,7 +1139,7 @@ async def _autoscale_cluster(
11311139
# 1. check if we have pending tasks and resolve them by activating some drained nodes
11321140
unrunnable_tasks = await auto_scaling_mode.list_unrunnable_tasks(app)
11331141
_logger.info("found %s unrunnable tasks", len(unrunnable_tasks))
1134-
1142+
# NOTE: this function predicts how dask will assign a task to a machine
11351143
queued_or_missing_instance_tasks, cluster = await _assign_tasks_to_current_cluster(
11361144
app, unrunnable_tasks, cluster, auto_scaling_mode
11371145
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# pylint: disable=redefined-outer-name
2+
# pylint: disable=unused-argument
3+
# pylint: disable=unused-variable
4+
# pylint: disable=too-many-arguments
5+
6+
7+
import logging
8+
9+
import pytest
10+
from fastapi import FastAPI
11+
from pytest_simcore.helpers.monkeypatch_envs import EnvVarsDict, setenvs_from_dict
12+
from simcore_service_autoscaling.modules.auto_scaling_core import (
13+
_sorted_allowed_instance_types,
14+
)
15+
16+
17+
@pytest.fixture
18+
def with_empty_ec2_intances_allowed_types(
19+
monkeypatch: pytest.MonkeyPatch,
20+
app_environment: EnvVarsDict,
21+
disabled_rabbitmq: None,
22+
mocked_ec2_server_envs: EnvVarsDict,
23+
mocked_ssm_server_envs: EnvVarsDict,
24+
mocked_redis_server: None,
25+
) -> EnvVarsDict:
26+
return app_environment | setenvs_from_dict(
27+
monkeypatch,
28+
{
29+
"EC2_INSTANCES_ALLOWED_TYPES": "{}",
30+
},
31+
)
32+
33+
34+
async def test_sorted_allowed_instance_types__warns_with_all_available(
35+
with_empty_ec2_intances_allowed_types: EnvVarsDict,
36+
initialized_app: FastAPI,
37+
caplog: pytest.LogCaptureFixture,
38+
):
39+
app = initialized_app
40+
41+
selected_names = list(
42+
app.state.settings.AUTOSCALING_EC2_INSTANCES.EC2_INSTANCES_ALLOWED_TYPES
43+
)
44+
assert not selected_names
45+
46+
with caplog.at_level(logging.WARNING):
47+
allowed = await _sorted_allowed_instance_types(app)
48+
assert allowed
49+
assert len(allowed) > 100
50+
51+
assert len(caplog.records) == 1

0 commit comments

Comments
 (0)