hello
Last active
April 2, 2024 14:31
-
-
Save jhw/696638d42ac5e4381e93f77fbafca38d to your computer and use it in GitHub Desktop.
Eventbridge timer demo, pushing confirmations to Slack
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
env | |
*.pyc | |
__pycache__ | |
tmp | |
setenv-priv.sh |
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
AppName=event-timer-demo |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation delete-stack --stack-name $AppName |
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
#!/usr/bin/env bash | |
. app.props | |
echo "SlackWebhookUrl: $SLACK_WEBHOOK_URL" | |
aws cloudformation deploy --stack-name $AppName --template-file stack.json --capabilities CAPABILITY_NAMED_IAM --parameter-overrides SlackWebhookUrl=$SLACK_WEBHOOK_URL | |
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
from botocore.exceptions import ClientError | |
import boto3, os, re, sys, time | |
def fetch_log_events(logs, kwargs): | |
events, token = [], None | |
while True: | |
if token: | |
kwargs["nextToken"]=token | |
resp=logs.filter_log_events(**kwargs) | |
events+=resp["events"] | |
if "nextToken" in resp: | |
token=resp["nextToken"] | |
else: | |
break | |
return sorted(events, | |
key=lambda x: x["timestamp"]) | |
if __name__=="__main__": | |
try: | |
if len(sys.argv) < 3: | |
raise RuntimeError("please enter lambda name, window") | |
lambdaname, window = sys.argv[1:3] | |
if not re.search("^\\d+$", window): | |
raise RuntimeError("window is invalid") | |
window=int(window) | |
logs=boto3.client("logs") | |
starttime=int(1000*(time.time()-window)) | |
loggroupname="/aws/lambda/%s" % lambdaname | |
kwargs={"logGroupName": loggroupname, | |
"startTime": starttime, | |
"interleaved": True} | |
events=fetch_log_events(logs, kwargs) | |
for event in events: | |
msg=re.sub("\\r|\\n", "", event["message"]) | |
print (msg) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
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
import json, os | |
if __name__=="__main__": | |
if not os.path.exists("tmp"): | |
os.mkdir("tmp") | |
struct=json.loads(open("stack.json").read()) | |
with open("tmp/stack.json", 'w') as f: | |
f.write(json.dumps(struct, | |
indent=2)) |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-events --stack-name $AppName --query "StackEvents[].{\"1.Timestamp\":Timestamp,\"2.Id\":LogicalResourceId,\"3.Type\":ResourceType,\"4.Status\":ResourceStatus,\"5.Reason\":ResourceStatusReason}" |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stacks --stack-name $AppName --query 'Stacks[0].Outputs' --output table |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-resources --stack-name $AppName --query "StackResources[].{\"1.Timestamp\":Timestamp,\"2.LogicalId\":LogicalResourceId,\"3.PhysicalId\":PhysicalResourceId,\"4.Type\":ResourceType,\"5.Status\":ResourceStatus}" |
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
#!/usr/bin/env bash | |
aws cloudformation describe-stacks --query "Stacks[].{\"1.Name\":StackName,\"2.Status\":StackStatus}" |
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 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
awscli | |
boto3 | |
botocore | |
pyyaml | |
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
#!/usr/bin/env bash | |
export AWS_DEFAULT_OUTPUT=table | |
export AWS_PROFILE=#{your-aws-profile-here} | |
export AWS_REGION=#{your-aws-region-here} | |
export SLACK_WEBHOOK_URL=#{your-slack-webhook-url-here} | |
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
{ | |
"Outputs": {}, | |
"Parameters": { | |
"SlackWebhookUrl": { | |
"Type": "String" | |
} | |
}, | |
"Resources": { | |
"MyErrorSubscriptionFilter": { | |
"DependsOn": [ | |
"MyLogStream", | |
"SlackErrorPermission" | |
], | |
"Properties": { | |
"DestinationArn": { | |
"Fn::GetAtt": [ | |
"SlackErrorFunction", | |
"Arn" | |
] | |
}, | |
"FilterPattern": "ERROR", | |
"LogGroupName": { | |
"Fn::Sub": "/aws/lambda/${MyFunction}" | |
} | |
}, | |
"Type": "AWS::Logs::SubscriptionFilter" | |
}, | |
"MyEventInvokeConfig": { | |
"Properties": { | |
"FunctionName": { | |
"Ref": "MyFunction" | |
}, | |
"MaximumRetryAttempts": 0, | |
"Qualifier": "$LATEST" | |
}, | |
"Type": "AWS::Lambda::EventInvokeConfig" | |
}, | |
"MyFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "\nimport logging\n\nlogger=logging.getLogger()\nlogger.setLevel(logging.INFO)\n\ndef handler(event, context=None):\n logger.warning(str(event))\n" | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"MyRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"MyLogGroup": { | |
"Properties": { | |
"LogGroupName": { | |
"Fn::Sub": "/aws/lambda/${MyFunction}" | |
}, | |
"RetentionInDays": 3 | |
}, | |
"Type": "AWS::Logs::LogGroup" | |
}, | |
"MyLogStream": { | |
"DependsOn": [ | |
"MyLogGroup" | |
], | |
"Properties": { | |
"LogGroupName": { | |
"Fn::Sub": "/aws/lambda/${MyFunction}" | |
} | |
}, | |
"Type": "AWS::Logs::LogStream" | |
}, | |
"MyPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "MyFunction" | |
}, | |
"Principal": "events.amazonaws.com", | |
"SourceArn": { | |
"Fn::GetAtt": [ | |
"MyRule", | |
"Arn" | |
] | |
} | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"MyPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "my-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "MyRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"MyRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"MyRule": { | |
"Properties": { | |
"ScheduleExpression": "rate(1 minute)", | |
"Targets": [ | |
{ | |
"Arn": { | |
"Fn::GetAtt": [ | |
"MyFunction", | |
"Arn" | |
] | |
}, | |
"Id": { | |
"Fn::Sub": "my-rule-${AWS::StackName}" | |
}, | |
"Input": "{}" | |
} | |
] | |
}, | |
"Type": "AWS::Events::Rule" | |
}, | |
"MyWarningSubscriptionFilter": { | |
"DependsOn": [ | |
"MyLogStream", | |
"SlackWarningPermission" | |
], | |
"Properties": { | |
"DestinationArn": { | |
"Fn::GetAtt": [ | |
"SlackWarningFunction", | |
"Arn" | |
] | |
}, | |
"FilterPattern": "%WARNING|Task timed out%", | |
"LogGroupName": { | |
"Fn::Sub": "/aws/lambda/${MyFunction}" | |
} | |
}, | |
"Type": "AWS::Logs::SubscriptionFilter" | |
}, | |
"SlackErrorFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "import base64, gzip, json, os, urllib.request\n\n# https://colorswall.com/palette/3\n\nLevels={\"info\": \"#5bc0de\",\n \"warning\": \"#f0ad4e\",\n \"error\": \"#d9534f\"}\n\ndef post_webhook(struct, url):\n req = urllib.request.Request(url, method = \"POST\")\n req.add_header(\"Content-Type\", \"application/json\")\n data = json.dumps(struct).encode()\n return urllib.request.urlopen(req, data = data).read()\n\ndef handler(event, context = None,\n colour = Levels[os.environ[\"SLACK_LOGGING_LEVEL\"]],\n webhookurl = os.environ[\"SLACK_WEBHOOK_URL\"]):\n struct = json.loads(gzip.decompress(base64.b64decode(event[\"awslogs\"][\"data\"])))\n text = json.dumps(struct)\n struct = {\"attachments\": [{\"text\": text,\n \"color\": colour}]}\n post_webhook(struct, webhookurl)\n" | |
}, | |
"Environment": { | |
"Variables": { | |
"SLACK_LOGGING_LEVEL": "error", | |
"SLACK_WEBHOOK_URL": { | |
"Ref": "SlackWebhookUrl" | |
} | |
} | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"SlackErrorRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"SlackErrorPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "SlackErrorFunction" | |
}, | |
"Principal": "logs.amazonaws.com" | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"SlackErrorPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "slack-error-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "SlackErrorRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"SlackErrorRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"SlackWarningFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "import base64, gzip, json, os, urllib.request\n\n# https://colorswall.com/palette/3\n\nLevels={\"info\": \"#5bc0de\",\n \"warning\": \"#f0ad4e\",\n \"error\": \"#d9534f\"}\n\ndef post_webhook(struct, url):\n req = urllib.request.Request(url, method = \"POST\")\n req.add_header(\"Content-Type\", \"application/json\")\n data = json.dumps(struct).encode()\n return urllib.request.urlopen(req, data = data).read()\n\ndef handler(event, context = None,\n colour = Levels[os.environ[\"SLACK_LOGGING_LEVEL\"]],\n webhookurl = os.environ[\"SLACK_WEBHOOK_URL\"]):\n struct = json.loads(gzip.decompress(base64.b64decode(event[\"awslogs\"][\"data\"])))\n text = json.dumps(struct)\n struct = {\"attachments\": [{\"text\": text,\n \"color\": colour}]}\n post_webhook(struct, webhookurl)\n" | |
}, | |
"Environment": { | |
"Variables": { | |
"SLACK_LOGGING_LEVEL": "warning", | |
"SLACK_WEBHOOK_URL": { | |
"Ref": "SlackWebhookUrl" | |
} | |
} | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"SlackWarningRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"SlackWarningPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "SlackWarningFunction" | |
}, | |
"Principal": "logs.amazonaws.com" | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"SlackWarningPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "slack-warning-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "SlackWarningRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"SlackWarningRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
} | |
} | |
} |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment