I have a CDK app that uses a lambda function to check for changes to the content of a website. I want that SMS to be sent to a mobile number if the change is detected.
In my AWS CDK project, I created my stack, that builds the lambda function and the SNS
file: lib/lambda_query_website_aws_cdk-stack.ts
import * as cdk from '@aws-cdk/core';
import events = require('@aws-cdk/aws-events');
import targets = require('@aws-cdk/aws-events-targets');
import lambda = require('@aws-cdk/aws-lambda');
import * as sns from '@aws-cdk/aws-sns';
import * as subscriptions from '@aws-cdk/aws-sns-subscriptions';
import fs = require('fs')
export class LambdaQueryWebsiteAwsCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const lambdaFn = new lambda.Function(this, 'Singleton', {
code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
handler: 'index.main',
timeout: cdk.Duration.seconds(300),
runtime: lambda.Runtime.PYTHON_3_6,
environment: {
'PREV_RESPONSE': ''
}
});
// Runs every 30 minutes from 6:00 to 23:00
// See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html
const rule = new events.Rule(this, 'Rule', {
schedule: events.Schedule.expression('cron(0/30 6-23 * * ? *)')
});
rule.addTarget(new targets.LambdaFunction(lambdaFn));
// Create an SNS Topic.
// The producer or publisher is the lambda function ??
//The subscriber or consumer is the sms phone number 15551231234
const myTopic = new sns.Topic(this, 'MyTopic');
myTopic.addSubscription(new subscriptions.SmsSubscription(' 15551231234'));
}
}
Here is the lambda function
file lambda-handler.py
import os
import urllib.request
url= "https://mywebsite.com"
def main(event, context):
print("I'm running!")
response = urllib.request.urlopen(url)
response_text = response.read()
html = response_text.decode('utf-8')
if os.getenv('PREV_RESPONSE',default="HTML_BODY") != html:
print("There was a change on the web site")
os.environ['PREV_RESPONSE'] = HTML
# TODO:
# Send the SMS notifying about the change
How do I make the SNS service know that the message needs to be sent?
BR
CodePudding user response:
Try something like this
export class LambdaQueryWebsiteAwsCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const myTopic = new sns.Topic(this, 'MyTopic');
myTopic.addSubscription(new subscriptions.SmsSubscription(' 15551231234'));
const lambdaFn = new lambda.Function(this, 'Singleton', {
code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
handler: 'index.main',
timeout: cdk.Duration.seconds(300),
runtime: lambda.Runtime.PYTHON_3_6,
environment: {
'PREV_RESPONSE': '',
'SNS_TOPIC_ARN': myTopic.topicArn // Include topic ARN as environment variable
}
});
myTopic.grantPublish(lambdaFn.role) // Grant lambda function permission to publish to topic
// Runs every 30 minutes from 6:00 to 23:00
// See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html
const rule = new events.Rule(this, 'Rule', {
schedule: events.Schedule.expression('cron(0/30 6-23 * * ? *)')
});
rule.addTarget(new targets.LambdaFunction(lambdaFn));
}
}
And in your python function
import os
import boto3
import urllib.request
url= "https://mywebsite.com"
client = boto3.client("sns")
SNS_TOPIC_ARN = os.getenv("SNS_TOPIC_ARN")
def main(event, context):
print("I'm running!")
response = urllib.request.urlopen(url)
response_text = response.read()
html = response_text.decode('utf-8')
if os.getenv('PREV_RESPONSE',default="HTML_BODY") != html:
os.environ['PREV_RESPONSE'] = html
response = client.publish(
TopicArn=SNS_TOPIC_ARN,
Message='There was a change on the web site',
Subject='Some change!'
)