Skip to content

Instantly share code, notes, and snippets.

@nileshprasad137
Last active September 26, 2024 14:35
Show Gist options
  • Save nileshprasad137/79df2f979ed20b61cf0f27a1ac1229c0 to your computer and use it in GitHub Desktop.
Save nileshprasad137/79df2f979ed20b61cf0f27a1ac1229c0 to your computer and use it in GitHub Desktop.
"""
This AWS Lambda function is designed to monitor Amazon ECS deployment state changes and send a notification to a Slack channel if a deployment fails. The function uses AWS EventBridge (formerly CloudWatch Events) to trigger on ECS deployment state changes and posts the failure details to different Slack channels based on the environment (staging or production).
### How it works:
- When an ECS deployment fails, the function is triggered by an EventBridge rule that listens to `ECS Deployment State Change` events particularly SERVICE_DEPLOYMENT_FAILED event.
- It parses the event details to extract the deployment ID, failure reason, and environment (staging or production).
- Using the ARN provided in the event, the function generates a direct link to the ECS resource in the AWS Console.
- The function then posts a message to the appropriate Slack webhook (either staging or production), including relevant details about the failure and the direct link for investigation.
### Prerequisites:
- You must have Slack webhooks configured for your staging and production channels.
- The Lambda function must have appropriate permissions to be triggered by EventBridge and to post messages to Slack.
### Environment Variables:
- `SLACK_WEBHOOK_STAGING`: The Slack webhook URL for staging environment alerts.
- `SLACK_WEBHOOK_PROD`: The Slack webhook URL for production environment alerts.
"""
import json
import urllib3
import os
# Slack webhook URLs from environment variables
staging_webhook_url = os.environ['SLACK_WEBHOOK_STAGING']
prod_webhook_url = os.environ['SLACK_WEBHOOK_PROD']
http = urllib3.PoolManager()
def get_arn_url(arn):
arn_parts = arn.split(":")
region = arn_parts[3]
resource = arn_parts[5]
if resource.startswith("service/"):
# For ECS Service ARN
_, cluster_name, service_name = resource.split("/")
url = f"https://{region}.console.aws.amazon.com/ecs/v2/clusters/{cluster_name}/services/{service_name}/health?region={region}"
elif resource.startswith("cluster/"):
# For ECS Cluster ARN
_, cluster_name = resource.split("/")
url = f"https://{region}.console.aws.amazon.com/ecs/v2/clusters/{cluster_name}/services?region={region}"
else:
# Default case for unrecognized resource type
url = "Unsupported ARN format"
return url
def lambda_handler(event, context):
# Extract necessary information from the event
detail = event.get('detail', {})
deployment_id = detail.get('deploymentId')
reason = detail.get('reason')
region = event.get('region')
resources = event.get('resources', [])
# Determine the environment based on the resource ARN
if any('staging' in resource for resource in resources):
webhook_url = staging_webhook_url
environment = "Staging"
elif any('prod' in resource for resource in resources):
webhook_url = prod_webhook_url
environment = "Production"
else:
# In case the environment is not recognized
webhook_url = staging_webhook_url # Default to staging, or handle error
environment = "Unknown"
# Generate the ARN URL
arn_url = get_arn_url(resources[0]) if resources else "ARN not provided"
# Form the Slack message
message = {
"text": f"ECS Deployment Failed in {environment} ({region}).\n"
f"Deployment ID: {deployment_id}\n"
f"Reason: {reason}\n"
f"More details: {arn_url}"
}
# Post the message to the appropriate Slack webhook
response = http.request(
'POST',
webhook_url,
body=json.dumps(message),
headers={'Content-Type': 'application/json'},
)
return {
'statusCode': response.status,
'body': response.data.decode('utf-8')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment