Skip to content

Commit

Permalink
Initial commit of ECRDeploy
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Lesierse committed Mar 14, 2018
1 parent 10af7dd commit cb9907d
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
.env
template-packaged.yml
5 changes: 4 additions & 1 deletion README.md
@@ -1,2 +1,5 @@
# aws-ecs-automation
# AWS ECS Automation
Collection of solutions to automate AWS ECS related tasks

## ECR Deployment Trigger
Lambda function that will create a CloudWatch event rule which will be triggered as soon as a Docker image is pushed to ECR and deploys it automatically to a ECS Cluster.
33 changes: 33 additions & 0 deletions ecr-deploy/README.md
@@ -0,0 +1,33 @@
# ECR Deployment Trigger
This Lambda function will create a CloudWatch event rule which will be triggered as soon as a Docker image is pushed to ECR and deploys it automatically to a ECS Cluster.

## Installation
For the installation of this Lambda function you need to take the following steps.

### Prepare
Use Python 3.6 and [Virtualenv](https://virtualenv.pypa.io/en/stable) to install your virtual environment get the required packages.

```sh
virtualenv -p python3 --no-site-packages --distribute .env && source .env/bin/activate && pip install -r requirements.txt
```

### S3 Bucket
As S3 bucket is required as destination for the AWS SAM package. If you don't have one already, create one:

```sh
aws s3 mb s3://your-aws-sam-bucket
```

### Package
Use the AWS CLI to create and upload the AWS SAM package to S3:

```sh
aws cloudformation package --template-file template.yml --output-template-file template-packaged.yml --s3-bucket your-aws-sam-bucket
```

### Deploy
Use the AWS CLI to deploy the AWS SAM package using CloudFormation:

```sh
aws cloudformation deploy --capabilities CAPABILITY_IAM --template-file template-packaged.yml --stack-name <YOUR STACK NAME> --parameter-overrides Cluster=<YOUR CLUSTER>
```
86 changes: 86 additions & 0 deletions ecr-deploy/deploy_handler.py
@@ -0,0 +1,86 @@
import os
import boto3


def lambda_handler(event, context):
cluster = os.environ['CLUSTER']
region = event['region']
ecs = boto3.client('ecs', region_name=region)

repositoryName = event['detail']['responseElements']['image']['repositoryName']
registryId = event['detail']['responseElements']['image']['registryId']
imageTag = event['detail']['responseElements']['image']['imageId']['imageTag']
image = f'{registryId}.dkr.ecr.{region}.amazonaws.com/{repositoryName}'

def get_task_definitions():
response = ecs.list_task_definition_families(status='ACTIVE')
families = response['families']
while ('nextToken' in response):
response = ecs.list_task_definition_families(nextToken=response['nextToken'])
families.append(response['families'])

taskDefinitions = [ecs.describe_task_definition(taskDefinition=family)['taskDefinition'] for family in families]
return [
taskDefinition for taskDefinition in taskDefinitions
if any([c for c in taskDefinition['containerDefinitions'] if c['image'].startswith(image)])
]

def update_task_definition(taskDefinition, newTaskDefinitions, image, imageTag):
family = taskDefinition['family']
containerDefinitions = taskDefinition['containerDefinitions']
print(f'Update task definition: {family}')
[
update_container_definition(containerDefinition, image, imageTag)
for containerDefinition in containerDefinitions
if containerDefinition['image'].startswith(image)
]

response = ecs.register_task_definition(
family=family,
taskRoleArn=taskDefinition['taskRoleArn'],
containerDefinitions=containerDefinitions,
volumes=taskDefinition['volumes'],
placementConstraints=taskDefinition['placementConstraints'],
requiresCompatibilities=taskDefinition['compatibilities'])
oldTaskDefinitionArn = taskDefinition['taskDefinitionArn']
newTaskDefinitionArn = response['taskDefinition']['taskDefinitionArn']
newTaskDefinitions[strip_arn(oldTaskDefinitionArn)] = newTaskDefinitionArn
return newTaskDefinitionArn

def update_container_definition(containerDefinition, image, imageTag):
print(f'Update container definition to {image}:{imageTag}')
containerDefinition['image'] = f'{image}:{imageTag}'

def get_services(cluster):
response = ecs.list_services(cluster=cluster)
service_arns = response['serviceArns']
while ('nextToken' in response):
response = ecs.list_services(cluster=cluster, nextToken=response['nextToken'])
service_arns.append(response['serviceArns'])
return [
service for service in ecs.describe_services(cluster=cluster, services=service_arns)['services']
if service['status'] == 'ACTIVE'
]

def update_service(service, newTaskDefinitionArn):
serviceArn = service['serviceArn']
print(f'Update service {serviceArn} with {newTaskDefinitionArn}')
response = ecs.update_service(cluster=cluster, service=serviceArn, taskDefinition=newTaskDefinitionArn)

def strip_arn(arn):
return arn[:arn.rindex(":")]

# Update Task Definitions
taskDefinitions = get_task_definitions()

newTaskDefinitions = {}
[update_task_definition(taskDefinition, newTaskDefinitions, image, imageTag) for taskDefinition in taskDefinitions]

if newTaskDefinitions:
services = get_services(cluster)
# Update Services
[
update_service(service, newTaskDefinitions[strip_arn(service['taskDefinition'])])
for service in services
if strip_arn(service['taskDefinition']) in newTaskDefinitions.keys()
]
1 change: 1 addition & 0 deletions ecr-deploy/requirements.txt
@@ -0,0 +1 @@
boto3>=1.6.7
31 changes: 31 additions & 0 deletions ecr-deploy/template.yml
@@ -0,0 +1,31 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Parameters:
Cluster:
Type: String
Description: Name of the ECS Cluster
Resources:
ECRDeploy:
Type: 'AWS::Serverless::Function'
Properties:
Handler: deploy_handler.lambda_handler
Runtime: python3.6
CodeUri: .
Description: Triggered when a Docker image is pushed to ECR and deploys it automatically to the ECS cluster
Environment:
Variables:
CLUSTER:
Ref: Cluster
Policies: AmazonEC2ContainerServiceFullAccess
Events:
ECRPutImage:
Type: CloudWatchEvent
Properties:
Pattern:
source:
- aws.ecr
detail:
eventSource:
- ecr.amazonaws.com
eventName:
- PutImage

0 comments on commit cb9907d

Please sign in to comment.