Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New serverless pattern - apigw-lambda-translate-cdk #2026

Merged
merged 12 commits into from
Jan 15, 2024
30 changes: 30 additions & 0 deletions apigw-lambda-translate-cdk/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

### Project Structure within apigw-lambda-translate:
```
apigw-lambda-translate-cdk
- app.py
- cdk.json
- src/
- lambda_function.py
- architecture.png
- requirements.txt
```

## Common Errors & Troubleshooting

### "ValueError: Must setup local AWS configuration with a region supported by AWS Services."
Solution: You must set an AWS region with `export AWS_DEFAULT_REGION=<your-region>`

### Error creating role
```
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the CreateRole operation: User: <user-arn> is not authorized to perform: iam:CreateRole on resource: <role-arn> because no identity-based policy allows the iam:CreateRole action
```
Solution: you must ensure the IAM role you are using has sufficient permissions to create IAM roles

#### Error processing tar file(exit status 1): write /path/libcublas.so.11: no space left on device
Issue: Docker has run out of memory due to too many images
Solution: Delete unused images in the Docker application and then [prune docker](https://docs.docker.com/config/pruning/) in command line

#### ConnectionResetError: [Errno 104] Connection reset by peer
Issue: Pip issue
Solution: Clear pip cache (`python3 -m pip cache purge`) and run again
89 changes: 89 additions & 0 deletions apigw-lambda-translate-cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# API Gateway -> Lambda -> Translate
This patterns shows CDK deployment on how to leverage Amazon API Gateway, AWS Lambda, and Amazon Translate to perform language translation in a serverless fashion.

## Architecture
![Diagram](src/architecture.png)

### What resources will be created?
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
This CDK code will create the following:
- One Lambda function (to invoke the Translate API)
- One API Gateway (to trigger the Lambda function with user input. The API Gateway does not perform any authorization or authentication of the incoming requests and this pattern should only be used for demonstration purposes only.)
- One IAM role (for the Lambda function to invoke Translate service)

## Requirements

### Development Environment
**Cloud 9**

This demonstration for this pattern is executed in an AWS Cloud9 environment. The EC2 instance used is t2.micro (1 GiB RAM + 1 vCPU). However, users have an option to deploy the application using CDK from local environment as well.

### AWS setup
**Region**

If you have not yet run `aws configure` and set a default region, you must do so, or you can also run `export AWS_DEFAULT_REGION=<your-region>`. The region used in the demonstration is us-east-1. Please make sure the region selected supports both Translate and Comprehend service.
(If the user does not know the source language that needs to be translated, the source language is set as `auto` in the lambda function and Translate service internally invokes Comprehend API to detect the source language.)

**Authorization**

You must use a role that has sufficient permissions to create IAM roles, as well as CloudFormation resources

#### Python >=3.8
Make sure you have [python3](https://www.python.org/downloads/) installed at a version >=3.8.x in the CDK environment. The demonstration uses python 3.10.

#### AWS CDK
Make sure you have the [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install) installed in the Cloud9 environment.


## Setup

### Set up environment and gather packages

```
cd apigw-lambda-translate-cdk
```

Install the required dependencies (aws-cdk-lib and constructs) into your Python environment
```
pip install -r requirements.txt
```

### Gather and deploy resources with the CDK

First synthesize, which executes the application, defines which resources will be created, and translates this into a CloudFormation template
```
cdk synth
```
All AWS CDK v2 deployments use dedicated AWS resources to hold data during deployment. Therefore, your AWS account and Region must be bootstrapped to create these resources before you can deploy. If you haven't already bootstrapped execute the below command
```
cdk bootstrap
```
and deploy with
```
cdk deploy
```

The deployment will create a API Gateway and a Lambda function.

## How it works
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
The API Gateway handles the incoming requests from the user and it invokes the relevant route. The Lambda function, triggered by API Gateway, invokes the Translate's TranslateText API and the analyzed response from Translate is routed back to the requester. The target language for translation is set to French by default and users are requested to change it as per their use-case.

## Testing
Upon successful deployment of the stack, the Output section would provide the `APIEndpoint` in the CDK environment. Alternatively, the `APIEndpoint` can be found from the Outputs section of the `CloudFormation` stack.

Use the below format to the test the API (replace the API Endpoint with the one retrieved from the above step):
```bash
curl -d '{"input": "I love AWS Services."}' -H 'Content-Type: application/json' https://<abcdefg>.execute-api.<region>.amazonaws.com/TranslateText
```

A response as below would be seen on the terminal console:
```
{
"Translated Text": "J'adore AWS Services.",
"statusCode": 200,
"Source Text": "I love AWS Services."
}
```

## Cleanup

To clean up the resources created as part of this demonstration, run the command `cdk destroy` in the directory `apigw-lambda-translate-cdk`. In addition, users are advised to terminate the Cloud9 EC2 instance to avoid any unexpected charges.
94 changes: 94 additions & 0 deletions apigw-lambda-translate-cdk/apigw-lambda-translate-cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"title": "API Gateway - Lambda - Translate",
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
"description": "Perform language translation using Translate through Lambda and API Gateway",
"language": "Python",
"level": "200",
"framework": "CDK",
"introBox": {
"headline": "How it works",
"text": [
"This patterns shows CDK deployment on how to leverage Amazon API Gateway, AWS Lambda, and Amazon Translate to perform language translation in a serverless fashion."
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-lambda-translate-cdk",
"templateURL": "serverless-patterns/apigw-lambda-translate-cdk",
"projectFolder": "apigw-lambda-translate-cdk",
"templateFile": "app.py"
}
},
"resources": {
"bullets": [
{
"text": "Amazon Translate",
"link": "https://docs.aws.amazon.com/translate/latest/dg/what-is.html"
},
{
"text": "Amazon Translate Features",
"Link": "https://aws.amazon.com/translate/"
},
{
"text": "Amazon API Gateway",
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html"
},
{
"text": "Amazon API Gateway Features",
"link": "https://aws.amazon.com/api-gateway/"
}
]
},
"deploy": {
"text": [
"cdk deploy"
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
]
},
"testing": {
"text": [
"See the GitHub repo for detailed testing instructions."
]
},
"cleanup": {
"text": [
"Delete the stack: <code>cdk destroy</code>."
awsarippa marked this conversation as resolved.
Show resolved Hide resolved
]
},
"authors": [
{
"name": "Arjun Arippa",
"image": "https://github.com/awsarippa/amazon-textract-comprehend-pii-analysis/blob/main/image.png",
"bio": "Arjun Arippa is a Solutions Architect based in Bangalore, India. He works with some of the strategic and global customers in India, to build and architect their applications on AWS. Before joining AWS, Arjun spent over a decade working as a Software Developer. Reach out to him on LinkedIn",
"linkedin": "arjun-arippa"
}
],
"patternArch": {
"icon1": {
"x": 20,
"y": 50,
"service": "apigw",
"label": "API Gateway HTTP API"
},
"icon2": {
"x": 50,
"y": 50,
"service": "lambda",
"label": "AWS Lambda"
},
"icon3": {
"x": 80,
"y": 50,
"service": "translate",
"label": "Amazon Translate"
},
"line1": {
"from": "icon1",
"to": "icon2",
"label": ""
},
"line2": {
"from": "icon2",
"to": "icon3",
"label": ""
}
}
}
76 changes: 76 additions & 0 deletions apigw-lambda-translate-cdk/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from aws_cdk import (
Duration,
Stack,
aws_iam as iam,
aws_lambda as lambda_,
CfnOutput
)
import aws_cdk.aws_apigatewayv2_alpha as _apigw
from aws_cdk.aws_apigatewayv2_integrations_alpha import HttpLambdaIntegration
from constructs import Construct

DIRNAME = os.path.dirname(__file__)


class ApigwLambdaTranslateServerless(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)

# IAM role to invoke lambda
lambda_cfn_role = iam.Role(
self,
"CfnRole",
assumed_by=iam.ServicePrincipal("apigateway.amazonaws.com"),
)
lambda_cfn_role.add_managed_policy(
iam.ManagedPolicy.from_aws_managed_policy_name("AWSLambdaExecute")
)

# Lambda function for processing the incoming request from API Gateway. Source and Target language are passed as environment variables to the Lambda function.
lambda_function = lambda_.Function(
self,
"TranslateTextLambda",
runtime=lambda_.Runtime.PYTHON_3_10,
handler="lambda_function.lambda_handler",
code=lambda_.Code.from_asset(os.path.join(DIRNAME, "src")),
timeout=Duration.minutes(1),
memory_size=256,
environment={
"environment": "dev",
"src_lang": "auto",
"target_lang": "fr"
},
)

# lambda policy
lambda_function.add_to_role_policy(
iam.PolicyStatement(
actions=[
"translate:TranslateText",
"comprehend:DetectDominantLanguage"
],
resources=["*"],
)
)

# api gateway with http
http_api = _apigw.HttpApi(self, "TranslateTextApi")

# added routes with POST method and integrated with the lambda function
http_api.add_routes(
path="/TranslateText",
methods=[_apigw.HttpMethod.ANY],
integration=HttpLambdaIntegration("TranslateTextIntegration", lambda_function)
)

# Outputs
CfnOutput(self, "API Endpoint", description="API Endpoint", value=http_api.api_endpoint)


app = cdk.App()
filestack = ApigwLambdaTranslateServerless(app, "ApigwLambdaTranslateServerless")

app.synth()
51 changes: 51 additions & 0 deletions apigw-lambda-translate-cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"app": "python3 app.py",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"requirements*.txt",
"source.bat",
"**/__init__.py",
"python/__pycache__",
"tests"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true
}
}
Loading
Loading