|
9 | 9 | "path": "Tree",
|
10 | 10 | "constructInfo": {
|
11 | 11 | "fqn": "constructs.Construct",
|
12 |
| - "version": "10.0.9" |
| 12 | + "version": "10.1.33" |
13 | 13 | }
|
14 | 14 | },
|
15 | 15 | "aws-ecs-integ": {
|
|
1143 | 1143 | "aws:cdk:cloudformation:type": "AWS::Lambda::Function",
|
1144 | 1144 | "aws:cdk:cloudformation:props": {
|
1145 | 1145 | "code": {
|
1146 |
| - "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(event))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(event))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n \n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n \n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n \n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" |
| 1146 | + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" |
1147 | 1147 | },
|
1148 | 1148 | "role": {
|
1149 | 1149 | "Fn::GetAtt": [
|
|
1240 | 1240 | },
|
1241 | 1241 | "constructInfo": {
|
1242 | 1242 | "fqn": "constructs.Construct",
|
1243 |
| - "version": "10.0.9" |
| 1243 | + "version": "10.1.33" |
1244 | 1244 | }
|
1245 | 1245 | },
|
1246 | 1246 | "LifecycleHookDrainHook": {
|
|
1735 | 1735 | "fqn": "@aws-cdk/aws-iam.CfnRole",
|
1736 | 1736 | "version": "0.0.0"
|
1737 | 1737 | }
|
| 1738 | + }, |
| 1739 | + "DefaultPolicy": { |
| 1740 | + "id": "DefaultPolicy", |
| 1741 | + "path": "aws-ecs-integ/myService/TaskDef/TaskRole/DefaultPolicy", |
| 1742 | + "children": { |
| 1743 | + "Resource": { |
| 1744 | + "id": "Resource", |
| 1745 | + "path": "aws-ecs-integ/myService/TaskDef/TaskRole/DefaultPolicy/Resource", |
| 1746 | + "attributes": { |
| 1747 | + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", |
| 1748 | + "aws:cdk:cloudformation:props": { |
| 1749 | + "policyDocument": { |
| 1750 | + "Statement": [ |
| 1751 | + { |
| 1752 | + "Action": [ |
| 1753 | + "logs:CreateLogStream", |
| 1754 | + "logs:DescribeLogGroups", |
| 1755 | + "logs:DescribeLogStreams", |
| 1756 | + "logs:PutLogEvents", |
| 1757 | + "ssmmessages:CreateControlChannel", |
| 1758 | + "ssmmessages:CreateDataChannel", |
| 1759 | + "ssmmessages:OpenControlChannel", |
| 1760 | + "ssmmessages:OpenDataChannel" |
| 1761 | + ], |
| 1762 | + "Effect": "Allow", |
| 1763 | + "Resource": "*" |
| 1764 | + } |
| 1765 | + ], |
| 1766 | + "Version": "2012-10-17" |
| 1767 | + }, |
| 1768 | + "policyName": "myServiceTaskDefTaskRoleDefaultPolicyD48473C0", |
| 1769 | + "roles": [ |
| 1770 | + { |
| 1771 | + "Ref": "myServiceTaskDefTaskRole1C1DE6CC" |
| 1772 | + } |
| 1773 | + ] |
| 1774 | + } |
| 1775 | + }, |
| 1776 | + "constructInfo": { |
| 1777 | + "fqn": "@aws-cdk/aws-iam.CfnPolicy", |
| 1778 | + "version": "0.0.0" |
| 1779 | + } |
| 1780 | + } |
| 1781 | + }, |
| 1782 | + "constructInfo": { |
| 1783 | + "fqn": "@aws-cdk/aws-iam.Policy", |
| 1784 | + "version": "0.0.0" |
| 1785 | + } |
1738 | 1786 | }
|
1739 | 1787 | },
|
1740 | 1788 | "constructInfo": {
|
|
1942 | 1990 | "minimumHealthyPercent": 50
|
1943 | 1991 | },
|
1944 | 1992 | "enableEcsManagedTags": false,
|
| 1993 | + "enableExecuteCommand": true, |
1945 | 1994 | "healthCheckGracePeriodSeconds": 60,
|
1946 | 1995 | "launchType": "EC2",
|
1947 | 1996 | "loadBalancers": [
|
|
0 commit comments