Last active
September 26, 2024 14:35
-
-
Save nileshprasad137/79df2f979ed20b61cf0f27a1ac1229c0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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