Skip to content

Commit 6cec07c

Browse files
committed
Enh(aws): Disk usage management
1 parent 7818602 commit 6cec07c

6 files changed

Lines changed: 172 additions & 3 deletions

File tree

aws/setup/batch/environment.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
"sg-014723b4566a8214d"
3232
],
3333
"instanceRole": "arn:aws:iam::039984708918:instance-profile/kilian-codeclash-ecsInstanceRole",
34+
"launchTemplate": {
35+
"launchTemplateName": "kilian-codeclash-launch-template"
36+
},
3437
"ec2Configuration": [
3538
{
3639
"imageType": "ECS_AL2"

aws/setup/batch/iam-ebs.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"Role": {
3+
"Path": "/",
4+
"RoleName": "kilian-codeclash-ecs-role-for-ebs-volumes",
5+
"AssumeRolePolicyDocument": {
6+
"Version": "2012-10-17",
7+
"Statement": [
8+
{
9+
"Effect": "Allow",
10+
"Principal": {
11+
"Service": "ecs.amazonaws.com"
12+
},
13+
"Action": "sts:AssumeRole"
14+
}
15+
]
16+
},
17+
"Description": "ECS Infrastructure role for managing EBS volumes",
18+
"MaxSessionDuration": 3600,
19+
"Tags": [
20+
{
21+
"Key": "project",
22+
"Value": "codeclash"
23+
},
24+
{
25+
"Key": "author",
26+
"Value": "kilian"
27+
}
28+
]
29+
}
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"LaunchTemplateName": "kilian-codeclash-launch-template",
3+
"LaunchTemplateData": {
4+
"BlockDeviceMappings": [
5+
{
6+
"DeviceName": "/dev/xvda",
7+
"Ebs": {
8+
"VolumeSize": 50,
9+
"VolumeType": "gp3"
10+
}
11+
}
12+
]
13+
},
14+
"TagSpecifications": [
15+
{
16+
"ResourceType": "launch-template",
17+
"Tags": [
18+
{
19+
"Key": "project",
20+
"Value": "codeclash"
21+
},
22+
{
23+
"Key": "author",
24+
"Value": "kilian"
25+
}
26+
]
27+
}
28+
]
29+
}

aws/setup/batch/pull.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ def pull_job_definition(job_name: str, batch_client) -> dict:
4646
return job_data
4747

4848

49+
def pull_launch_template(template_name: str, ec2_client) -> dict:
50+
"""Pull EC2 launch template from AWS."""
51+
response = ec2_client.describe_launch_templates(LaunchTemplateNames=[template_name])
52+
template_data = response["LaunchTemplates"][0]
53+
54+
# Get the latest version of the template
55+
version_response = ec2_client.describe_launch_template_versions(
56+
LaunchTemplateId=template_data["LaunchTemplateId"], Versions=["$Latest"]
57+
)
58+
template_version = version_response["LaunchTemplateVersions"][0]
59+
60+
# Combine template metadata with version data
61+
result = {
62+
"LaunchTemplateName": template_data["LaunchTemplateName"],
63+
"LaunchTemplateData": template_version["LaunchTemplateData"],
64+
}
65+
66+
# Add tags if they exist
67+
if template_data.get("Tags"):
68+
result["TagSpecifications"] = [
69+
{
70+
"ResourceType": "launch-template",
71+
"Tags": [{"Key": tag["Key"], "Value": tag["Value"]} for tag in template_data["Tags"]],
72+
}
73+
]
74+
75+
logger.info(f"✅ Successfully pulled launch template: {template_name}")
76+
return result
77+
78+
4979
def clean_response_data(data: dict, is_iam_role: bool) -> dict:
5080
"""Clean AWS response data to remove metadata and format for JSON storage."""
5181
if is_iam_role:
@@ -55,6 +85,11 @@ def clean_response_data(data: dict, is_iam_role: bool) -> dict:
5585
cleaned.pop("ResponseMetadata", None)
5686
cleaned.pop("createdAt", None)
5787
cleaned.pop("schedulingPriority", None)
88+
# Remove AWS-specific metadata fields for job definitions
89+
cleaned.pop("jobDefinitionArn", None)
90+
cleaned.pop("revision", None)
91+
cleaned.pop("status", None)
92+
cleaned.pop("containerOrchestrationType", None)
5893
return cleaned
5994

6095

@@ -72,15 +107,21 @@ def pull_file(json_path: Path, region: str) -> None:
72107
case "iam-job-role.json":
73108
data = pull_iam_role("kilian-codeclash-job-role", boto3.client("iam", region_name=region))
74109
cleaned_data = clean_response_data(data, is_iam_role=True)
110+
case "iam-ebs.json":
111+
data = pull_iam_role("kilian-codeclash-ecs-role-for-ebs-volumes", boto3.client("iam", region_name=region))
112+
cleaned_data = clean_response_data(data, is_iam_role=True)
75113
case "environment.json":
76114
data = pull_compute_environment("codeclash-batch", boto3.client("batch", region_name=region))
77115
cleaned_data = clean_response_data(data, is_iam_role=False)
78116
case "job_queue.json":
79117
data = pull_job_queue("codeclash-queue", boto3.client("batch", region_name=region))
80118
cleaned_data = clean_response_data(data, is_iam_role=False)
81119
case "job_definition.json":
82-
data = pull_job_definition("codeclash-default-job", boto3.client("batch", region_name=region))
120+
data = pull_job_definition("codeclash-ebs-20g", boto3.client("batch", region_name=region))
83121
cleaned_data = clean_response_data(data, is_iam_role=False)
122+
case "launch_template.json":
123+
data = pull_launch_template("kilian-codeclash-launch-template", boto3.client("ec2", region_name=region))
124+
cleaned_data = data # No cleaning needed for launch templates
84125
case _:
85126
logger.error(f"Unknown filename: {filename}")
86127
raise ValueError(f"Unknown filename: {filename}")

aws/setup/batch/push.py

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Any
99

1010
import boto3
11+
from botocore.exceptions import ClientError
1112

1213
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
1314
logger = logging.getLogger(__name__)
@@ -173,10 +174,15 @@ def push_job_definition(job_data: dict, batch_client) -> None:
173174
register_params = {
174175
"jobDefinitionName": job_name,
175176
"type": job_data.get("type", "container"),
176-
"containerProperties": job_data["containerProperties"],
177177
"platformCapabilities": job_data.get("platformCapabilities", ["EC2"]),
178178
}
179179

180+
# Handle both old containerProperties and new ecsProperties formats
181+
if "ecsProperties" in job_data:
182+
register_params["ecsProperties"] = job_data["ecsProperties"]
183+
elif "containerProperties" in job_data:
184+
register_params["containerProperties"] = job_data["containerProperties"]
185+
180186
if "parameters" in job_data:
181187
register_params["parameters"] = job_data["parameters"]
182188
if "tags" in job_data:
@@ -188,20 +194,70 @@ def push_job_definition(job_data: dict, batch_client) -> None:
188194
logger.info(f"✅ Successfully pushed job definition: {job_name}:{revision}")
189195

190196

197+
def _update_launch_template(template_data: dict, existing_template: dict, ec2_client) -> None:
198+
"""Update existing launch template by creating a new version."""
199+
template_name = template_data["LaunchTemplateName"]
200+
logger.info(f"Launch template {template_name} already exists, creating new version")
201+
202+
create_params = {
203+
"LaunchTemplateId": existing_template["LaunchTemplateId"],
204+
"LaunchTemplateData": template_data["LaunchTemplateData"],
205+
}
206+
207+
response = ec2_client.create_launch_template_version(**create_params)
208+
version = response["LaunchTemplateVersion"]["VersionNumber"]
209+
210+
logger.info(f"✅ Successfully created new version {version} for launch template: {template_name}")
211+
212+
213+
def _create_launch_template(template_data: dict, ec2_client) -> None:
214+
"""Create new launch template."""
215+
template_name = template_data["LaunchTemplateName"]
216+
logger.info(f"Creating new launch template: {template_name}")
217+
218+
create_params = {
219+
"LaunchTemplateName": template_name,
220+
"LaunchTemplateData": template_data["LaunchTemplateData"],
221+
}
222+
223+
if "TagSpecifications" in template_data:
224+
create_params["TagSpecifications"] = template_data["TagSpecifications"]
225+
226+
ec2_client.create_launch_template(**create_params)
227+
logger.info(f"✅ Successfully created launch template: {template_name}")
228+
229+
230+
def push_launch_template(template_data: dict, ec2_client) -> None:
231+
"""Push EC2 launch template to AWS."""
232+
template_name = template_data["LaunchTemplateName"]
233+
234+
try:
235+
response = ec2_client.describe_launch_templates(LaunchTemplateNames=[template_name])
236+
existing_template = response["LaunchTemplates"][0]
237+
_update_launch_template(template_data, existing_template, ec2_client)
238+
except ClientError as e:
239+
if e.response["Error"]["Code"] == "InvalidLaunchTemplateName.NotFoundException":
240+
_create_launch_template(template_data, ec2_client)
241+
else:
242+
raise
243+
244+
191245
def push_file(json_path: Path, region: str) -> None:
192246
"""Push a single JSON file to AWS."""
193247
data = json.loads(json_path.read_text())
194248
filename = json_path.name
195249

196250
match filename:
197-
case "iam-environment-role.json" | "iam-execution-role.json" | "iam-job-role.json":
251+
case "iam-environment-role.json" | "iam-execution-role.json" | "iam-job-role.json" | "iam-ebs.json":
198252
push_iam_role(data, boto3.client("iam", region_name=region))
199253
case "environment.json":
200254
push_compute_environment(data, boto3.client("batch", region_name=region))
201255
case "job_queue.json":
202256
push_job_queue(data, boto3.client("batch", region_name=region))
203257
case "job_definition.json":
204258
push_job_definition(data, boto3.client("batch", region_name=region))
259+
case "launch_template.json":
260+
push_launch_template(data, boto3.client("ec2", region_name=region))
205261
case _:
206262
logger.error(f"Unknown filename: {filename}")
207263
raise ValueError(f"Unknown filename: {filename}")

aws/setup/docker/docker_entrypoint.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ echo " AWS_BATCH_JOB_ATTEMPT: ${AWS_BATCH_JOB_ATTEMPT:-<not set>}"
2828
echo " AWS_BATCH_JOB_ID: ${AWS_BATCH_JOB_ID:-<not set>}"
2929
echo " AWS_BATCH_JQ_NAME: ${AWS_BATCH_JQ_NAME:-<not set>}"
3030

31+
echo "💾 Disk usage before job:"
32+
df -h
33+
3134
source .venv/bin/activate
3235

3336
echo "═══════════════════════════════════════════════════════════════════════════════"
@@ -36,6 +39,13 @@ echo "$@"
3639
echo "═══════════════════════════════════════════════════════════════════════════════"
3740
# Execute the remaining command arguments
3841
exec "$@"
42+
echo "═══════════════════════════════════════════════════════════════════════════════"
43+
echo "✅ User provided command finished"
44+
echo "═══════════════════════════════════════════════════════════════════════════════"
45+
46+
echo "💾 Disk usage after job:"
47+
df -h
48+
3949
echo "═══════════════════════════════════════════════════════════════════════════════"
4050
echo "✅ docker_entrypoint.sh finished"
4151
echo "═══════════════════════════════════════════════════════════════════════════════"

0 commit comments

Comments
 (0)