StackGen Emerges from appCD to Disrupt IaC Learn More
Deploying a Newsfeed Application on AWS Lambda Using StackGen
September 13, 2024 •Sangam Biradar
Do you find yourself missing your old RSS feed? Or have you been thinking that you would like a place to quickly and easily display updates on what you’ve been working on? A newsfeed application might be just the thing for you!
In this post, I’ll use a feed parser, StackGen, and AWS Lambda to deploy a simple newsfeed app. Follow along to deploy your own!
Why use AWS Lambda?
AWS Lambda is a serverless Function as a Service that allows you to run code without needing to provision and manage servers. This makes it an ideal service to run little fun apps like this newsfeed. There are lots of other use cases for Lambda that I encourage you to explore, and with a fairly robust free tier, it’s easy to get started with your own pet projects.
Even without the need to provision servers, you still need to know some AWS magic to get Lambda up and running, which is where StackGen comes in.
Join us as we get our newsfeed up and running!
Prerequisites
To follow along with this, we assume you have the following:
- Python installed locally
- AWS account
- Terraform Installed locally
- GitHub account / GitHub CLI
- GIT Bash / WSL (for windows user)
Step One: Get the newsfeed application
First, fork the newsfeed app code, which you can find here:
https://github.com/appcd-demo/news-feed
This is a Python application which will call AWS Lambda, read, and parse a newsfeed.
Now, let's see what the application does:
```
import feedparser
def lambda_handler(event, context):
feed_url = 'https://lwkd.info/feed.xml'
feed = feedparser.parse(feed_url)
html_content = """
Here we are asking AWS Lambda to read and parse from the XML file we’ve defined. Next we describe how we want the output to appear:
<html>
<head>
<title>{}</title>
<style>
body
h1
h2
a
a:hover
p
.content
hr
</style>
</head>
<body>
The next section defines how the feed will be parsed and fed into the HTML we just defined.
""".format(feed.feed.title)
html_content += f"<h1>{feed.feed.title}</h1>"
for entry in feed.entries:
html_content += "<div class='content'>"
html_content += f"<h2><a href='{entry.link}'>{entry.title}</a></h2>"
html_content += f"<p><em>Published: {entry.published}</em></p>"
html_content += f"<p>{entry.summary}</p>"
html_content += entry.get('content', [{'value': entry.summary}])[0]['value']
html_content += "</div>"
html_content += "<hr>"
html_content += "</body></html>"
return {
'statusCode': 200,
'body': html_content,
'headers': {
'Content-Type': 'text/html'
}
}
`When you look at the whole, we have the AWS Lambda function that fetches and parses an RSS feed using the feedparser library. It generates an HTML page displaying the feed's title, along with each entry's title, publication date, summary, and content from the given `feedurl` The function returns this HTML page as the HTTP response.
Step Two: Prepare the application for deployment
Now that you have composed an HTML response coming from AWS Lambda, you need the infrastructure to run it. First, build the application by running the provided `build.sh` command:
git clone https://github.com/appcd-demo/news-feed
cd news-feed
sh build.sh
The `build.sh` contains the following:
```
#!/bin/bash
set -e
pip install --target ./package feedparser
cd package
zip -r ../main.zip .
cd ../
zip -g main.zip main.py
```
The above script will :
- Install the dependencies: The script installs the `feedparser` library and its dependencies into a `./package` directory using `pip`.
- Package the dependencies: It then changes the directory to `./package` and creates a `main.zip` file, containing all the installed dependencies.
- Add the AWS Lambda newsfeed application: The script returns to the original directory, where it adds the `main.py` (your application’s code) to the existing `main.zip`, ensuring both the code and dependencies are included in the final deployment package.
Now you have a ZIP file ready to be uploaded and deployed as an AWS Lambda function.
Step Three: Run StackGen
To get the AWS Lambda setup we need, we’ll use StackGen’s infrastructure from code capability to generate the IaC we need for speedy deployment.
To run StackGen:
- Log in.
- Create an appStack from our newsfeed code repository, and
- Get our topology
Log in
First, log in to cloud.stackgen.com. If you don’t have an account, you can easily log in with your GitHub, GitLab, Google, or BitBucket credentials.
Create a new appStack
Next, create an appStack from the newsfeed repository. (You can read more about what an appStack is here.)
Select “New appStack” from the StackGen page or the upper right button.
Choose “appStack from Source code”:
Add the new repository by selecting “Add from GitHub Repositories”, or if you have used StackGen before and already have repositories added, choose “Want to add another repository?”
Locate your newsfeed repository, choose it, and select “Proceed”:
The component name, path, branch, and language (Python) will all be pre-filled for you. Select “Proceed”:
Choose AWS Lambda, since our application runs on AWS Lambda and select “Proceed”:
Give your appStack a name (and if you are feeling very motivated, a description and a tag), then select “Create”:
The StackGen analyzer takes a few seconds to scan the repository’s components and configuration.
The StackGen analyzer has reviewed the code and, based on the service and pre-configured security best practices, we've generated a visual topology, along with its resource mapping:
The analysis identified three resources:
- AWS Lambda (that's our news-feed-function )
- IAM Role
- CloudWatch Log Group
Select the `news-feed-function` to view all the required fields for that Lambda function.
Earlier in this post we built and packaged our AWS Lambda function in a main.zip file. Add that file name under “Code Configuration”:
To make our Function URL publicly accessible, set the Function URL option to `True`. Then save your changes.
Step Four: Deploy your application
You’ve created a topology and configured the resources within it. The next step is to export the topology so the resources are created and deploy your application.
Export your generated Infrastructure as Code (IaC) from the topology page, and it will contain all the information we added in the previous step. Choose the "Export IaC -> Export IaC files" option.
Create a terraform folder, unzip the exported IaC file from StackGen, and also add the previously created main.zip file:
➜ mkdir terraform
➜ cd terraform
Verify that everything worked by navigating into the Terraform folder. You should see your generated IaC and main.zip:
➜ terraform git:(main) ✗ ls
README.md modules outputs.tf terraform.tfstate
main.zip modules.tf.json provider.tf variables.tf
Add your AWS credentials by exporting them as environment variables:
export AWS_ACCESS_KEY_ID=<your-access-key-id>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<your-session-token>
Replace <your-access-key-id>, <your-secret-access-key>, and <your-session-token> with your actual AWS credentials. This will allow you to securely authenticate with AWS and provision your serverless application
Now you’re ready to run Terraform.
Type terraform init to set up your environment so that Terraform can manage your infrastructure according to the configuration auto generated from StackGen.
You’ll see Terraform working like this:
➜ terraform git:(main) ✗ terraform init
Initializing the backend...
Initializing modules...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v5.63.1
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
- Run `terraform plan` to show you what changes Terraform plans to make to your infrastructure:
➜ terraform git:(main) ✗ terraform plan
var.region
Enter the AWS region in which to deploy the project (us-east-1, ca-west-1, eu-west-3, etc):
Enter a value: enter your aws region where you want to deploy
Apply the Terraform configuration using `terraform apply` once you're ok with the plan and want to proceed with provisioning the infrastructure:
➜ terraform git:(main) ✗ terraform apply
var.region
AWS region in which the project needs to be set up (example: us-east-1, ca-west-1, eu-west-3, etc)
Enter a value: <enter aws region where you want to deploy >
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
You can watch the deployment of your application to AWS!
Outputs:
aws_cloudwatch_log_group_aws_lambda_news_feed_function_arn = "arn:aws:logs:us-east-1:438465137822:log-group:/aws/lambda/news-feed-function"
aws_cloudwatch_log_group_aws_lambda_news_feed_function_name = "/aws/lambda/news-feed-function"
aws_iam_role_news_feed_role_arn = "arn:aws:iam::438465137822:role/news-feed-role"
aws_iam_role_news_feed_role_name = "news-feed-role"
aws_lambda_news_feed_function_function_arn = "arn:aws:lambda:us-east-1:438465137822:function:news-feed-function"
aws_lambda_news_feed_function_function_name = "news-feed-function"
aws_lambda_news_feed_function_function_url = "https://ue3z4eswm24a6kvncbp3d7joi40mdkqc.lambda-url.us-east-1.on.aws/"
aws_lambda_news_feed_function_invoke_arn = "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:438465137822:function:news-feed-function/invocations"
You will see the AWS processes in Terraform. This output includes the created resources:
- CloudWatch Log Group ARN-
- CloudWatch Log Group Name
- IAM Role ARN
- IAM Role Name
- Lambda Function ARN
- Lambda Function Name
- Lambda Function URL
To see your application up and running out in the world, copy the AWS Lambda URL in the Terraform output and open that link in your browser. It will look something like:
aws_lambda_news_feed_function_function_url = "<Your-Function-URL>"
Terraform Destroy - destroy all remote objects managed by a particular Terraform configuration terraform git:(main) ✗ terraform Destroy
We successfully destroyed our application !
Conclusion
Now you’re ready to impress your friends and colleagues with your newsfeed! Or at least to try StackGen on another pet project.
StackGen supports Python and Java apps in AWS Lambda, EKS, and ECS, as well as Azure AKS.
If you want to simplify and automate the deployment of Serverless applications, while ensuring that AWS best practices and security recommendations are in place, look no further than StackGen!
Don’t see your language supported, or have feedback for us? Let us know at support@stackgen.com. We’d love to hear from you! Join Our Community on Slack - DevInfraDays.