Skip to content

Commit c825f9b

Browse files
author
Jim Robinson
committed
Add scale up/down command
1 parent dd7233b commit c825f9b

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

croudtech_ecs_tools/cli.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from click.decorators import command
66
from click.termui import prompt
77
import os
8-
from croudtech_ecs_tools.ecs import Ecs
8+
from croudtech_ecs_tools.ecs import Ecs, EcsScaler
99
import json
1010

1111

@@ -206,5 +206,23 @@ def list_service_discovery_endpoints(cluster):
206206
ecs_manager = Ecs(cluster=cluster)
207207
print(json.dumps(ecs_manager.list_ecs_service_endpoints(), indent=2, default=str))
208208

209+
@cli.command()
210+
@click.option("--cluster", required=True)
211+
def show_service_ips(cluster):
212+
ecs_manager = Ecs(cluster=cluster)
213+
print(json.dumps(ecs_manager.show_service_ips(), indent=2, default=str))
214+
215+
@cli.command()
216+
@click.argument("environment")
217+
def scale_up(environment):
218+
ecs_scaler = EcsScaler(environment)
219+
ecs_scaler.scale_up()
220+
221+
@cli.command()
222+
@click.argument("environment")
223+
def scale_down(environment):
224+
ecs_scaler = EcsScaler(environment)
225+
ecs_scaler.scale_down()
226+
209227
if __name__ == "__main__":
210-
cli()
228+
cli()

croudtech_ecs_tools/ecs.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
from typing import List
1111
import json
12+
from datetime import datetime
13+
import click
14+
15+
1216

1317
def parse_arn(arn):
1418
elements = arn.split(':')
@@ -87,3 +91,80 @@ def list_ecs_service_endpoints(self):
8791

8892
return self._ecs_service_endpoints
8993

94+
class EcsScaler:
95+
def __init__(self, environment) -> None:
96+
self.environment = environment
97+
98+
@property
99+
def ecs_client(self):
100+
if not hasattr(self, "_ecs_client"):
101+
self._ecs_client = boto3.client("ecs")
102+
return self._ecs_client
103+
104+
def get_ecs_clusters(self):
105+
clusters = self.ecs_client.describe_clusters(
106+
clusters=self.ecs_client.list_clusters()["clusterArns"],
107+
include=["TAGS"]
108+
)
109+
110+
return [cluster for cluster in clusters["clusters"] if {"key": "Environment", "value": self.environment} in cluster["tags"]]
111+
112+
def get_services(self):
113+
services = {}
114+
for cluster in self.get_ecs_clusters():
115+
if cluster["clusterArn"] not in services:
116+
services[cluster["clusterArn"]] = {}
117+
paginator = self.ecs_client.get_paginator('list_services')
118+
response_iterator = paginator.paginate(
119+
cluster=cluster["clusterArn"],
120+
)
121+
for page in response_iterator:
122+
for service in page["serviceArns"]:
123+
service_data = self.ecs_client.describe_services(
124+
services=page["serviceArns"],
125+
cluster=cluster["clusterArn"],
126+
include=["TAGS"]
127+
)
128+
for service in service_data["services"]:
129+
services[cluster["clusterArn"]][service["serviceArn"]] = service
130+
131+
return services
132+
133+
def scale_down(self):
134+
services = self.get_services()
135+
for cluster_arn, services in services.items():
136+
for service_arn, service in services.items():
137+
desired_count = str(service["desiredCount"])
138+
if int(desired_count) > 0:
139+
self.ecs_client.tag_resource(resourceArn=service_arn, tags=[
140+
{
141+
"key": "downscaler_desired_count",
142+
"value": desired_count
143+
},
144+
{
145+
"key": "downscaler_scaled_down_at",
146+
"value": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
147+
}
148+
])
149+
self.ecs_client.update_service(service=service_arn, cluster=cluster_arn, desiredCount=0)
150+
click.echo(f"Scaled down {service_arn} from {desired_count}")
151+
152+
def scale_up(self):
153+
services = self.get_services()
154+
for cluster_arn, services in services.items():
155+
for service_arn, service in services.items():
156+
try:
157+
desired_count = self.serviceTagsDict(service)["downscaler_desired_count"]
158+
self.ecs_client.tag_resource(resourceArn=service_arn, tags=[
159+
{
160+
"key": "downscaler_scaled_up_at",
161+
"value": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
162+
}
163+
])
164+
self.ecs_client.update_service(service=service_arn, cluster=cluster_arn, desiredCount=int(desired_count))
165+
click.echo(f"Scaled up {service_arn} to {desired_count}")
166+
except KeyError:
167+
pass
168+
169+
def serviceTagsDict(self, service):
170+
return {tag["key"]: tag["value"] for tag in service["tags"]}

0 commit comments

Comments
 (0)