Skip to content

Commit 6751dc8

Browse files
authored
Merge pull request #39 from vertti/fix-10-service-limit
Fix: Handle AWS ECS 10-service limit in describe_services
2 parents 4f1eea1 + 934fc64 commit 6751dc8

File tree

6 files changed

+82
-7
lines changed

6 files changed

+82
-7
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "lazy-ecs"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
description = "A CLI tool for working with AWS services"
55
readme = "README.md"
66
authors = [

src/lazy_ecs/core/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import threading
99
from collections.abc import Iterator
1010
from contextlib import contextmanager, suppress
11-
from typing import TYPE_CHECKING, Literal
11+
from typing import TYPE_CHECKING, Any, Literal
1212

1313
from rich.console import Console
1414
from rich.spinner import Spinner
@@ -80,6 +80,12 @@ def show_spinner() -> Iterator[None]:
8080
yield
8181

8282

83+
def batch_items(items: list[Any], batch_size: int) -> Iterator[list[Any]]:
84+
"""Split a list into batches of specified size."""
85+
for i in range(0, len(items), batch_size):
86+
yield items[i : i + batch_size]
87+
88+
8389
def paginate_aws_list(
8490
client: ECSClient,
8591
operation_name: Literal[

src/lazy_ecs/features/service/service.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from ...core.base import BaseAWSService
99
from ...core.types import ServiceEvent, ServiceInfo
10-
from ...core.utils import determine_service_status, extract_name_from_arn, paginate_aws_list
10+
from ...core.utils import batch_items, determine_service_status, extract_name_from_arn, paginate_aws_list
1111

1212
if TYPE_CHECKING:
1313
from typing import Any
@@ -31,9 +31,13 @@ def get_service_info(self, cluster_name: str) -> list[ServiceInfo]:
3131
if not service_names:
3232
return []
3333

34-
response = self.ecs_client.describe_services(cluster=cluster_name, services=service_names)
35-
services = response.get("services", [])
36-
return [_create_service_info(service) for service in services]
34+
all_services = [
35+
service
36+
for batch in batch_items(service_names, 10)
37+
for service in self.ecs_client.describe_services(cluster=cluster_name, services=batch).get("services", [])
38+
]
39+
40+
return [_create_service_info(service) for service in all_services]
3741

3842
def get_desired_task_definition_arn(self, cluster_name: str, service_name: str) -> str | None:
3943
response = self.ecs_client.describe_services(cluster=cluster_name, services=[service_name])

tests/test_aws_service.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,32 @@ def test_get_service_info(ecs_client_with_services) -> None:
268268
assert "pending_count" in info
269269

270270

271+
def test_get_service_info_with_more_than_10_services():
272+
with mock_aws():
273+
client = boto3.client("ecs", region_name="us-east-1")
274+
client.create_cluster(clusterName="production")
275+
276+
client.register_task_definition(
277+
family="app-task",
278+
containerDefinitions=[{"name": "app", "image": "nginx", "memory": 256}],
279+
)
280+
281+
for i in range(15):
282+
client.create_service(
283+
cluster="production",
284+
serviceName=f"service-{i:02d}",
285+
taskDefinition="app-task",
286+
desiredCount=2,
287+
)
288+
289+
service = ECSService(client)
290+
service_info = service.get_service_info("production")
291+
292+
assert len(service_info) == 15
293+
service_names = {info["name"] for info in service_info}
294+
assert all(any(f"service-{i:02d}" in name for name in service_names) for i in range(15))
295+
296+
271297
def test_get_tasks(ecs_client_with_tasks) -> None:
272298
service = ECSService(ecs_client_with_tasks)
273299
tasks = service.get_tasks("production", "web-api")

tests/test_utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Tests for utility functions."""
2+
3+
from lazy_ecs.core.utils import batch_items
4+
5+
6+
def test_batch_items_basic():
7+
batches = list(batch_items([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3))
8+
9+
assert batches == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
10+
11+
12+
def test_batch_items_exact_fit():
13+
batches = list(batch_items([1, 2, 3, 4, 5, 6], 3))
14+
15+
assert batches == [[1, 2, 3], [4, 5, 6]]
16+
17+
18+
def test_batch_items_single_batch():
19+
batches = list(batch_items([1, 2, 3], 10))
20+
21+
assert batches == [[1, 2, 3]]
22+
23+
24+
def test_batch_items_empty_list():
25+
batches = list(batch_items([], 5))
26+
27+
assert batches == []
28+
29+
30+
def test_batch_items_size_one():
31+
batches = list(batch_items([1, 2, 3, 4, 5], 1))
32+
33+
assert batches == [[1], [2], [3], [4], [5]]
34+
35+
36+
def test_batch_items_strings():
37+
batches = list(batch_items(["a", "b", "c", "d", "e", "f", "g"], 3))
38+
39+
assert batches == [["a", "b", "c"], ["d", "e", "f"], ["g"]]

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)