From c6991d3c2ae651a2f6213a7334638bf1e8d92ba3 Mon Sep 17 00:00:00 2001 From: Tung Bui Date: Sun, 30 Jul 2023 20:49:15 +0700 Subject: [PATCH] i182: move serverless example to hands-on --- .../serverless}/.terraform.lock.hcl | 0 {serverless => hands-on/serverless}/README.md | 12 +- .../serverless}/lambda_http.py | 70 ++-- {serverless => hands-on/serverless}/main.tf | 316 +++++++++--------- .../serverless}/test_data.json | 12 +- 5 files changed, 205 insertions(+), 205 deletions(-) rename {serverless => hands-on/serverless}/.terraform.lock.hcl (100%) rename {serverless => hands-on/serverless}/README.md (97%) rename {serverless => hands-on/serverless}/lambda_http.py (96%) rename {serverless => hands-on/serverless}/main.tf (95%) rename {serverless => hands-on/serverless}/test_data.json (94%) diff --git a/serverless/.terraform.lock.hcl b/hands-on/serverless/.terraform.lock.hcl similarity index 100% rename from serverless/.terraform.lock.hcl rename to hands-on/serverless/.terraform.lock.hcl diff --git a/serverless/README.md b/hands-on/serverless/README.md similarity index 97% rename from serverless/README.md rename to hands-on/serverless/README.md index a68681c..e16df11 100644 --- a/serverless/README.md +++ b/hands-on/serverless/README.md @@ -1,6 +1,6 @@ -# Architecture: -[User] -> [API_Gateway] -> [Lambda] -> [DynamoDB] - -# References: -## https://developer.hashicorp.com/terraform/tutorials/aws/lambda-api-gateway -## https://dev.to/rolfstreefkerk/openapi-with-terraform-on-aws-api-gateway-17je +# Architecture: +[User] -> [API_Gateway] -> [Lambda] -> [DynamoDB] + +# References: +## https://developer.hashicorp.com/terraform/tutorials/aws/lambda-api-gateway +## https://dev.to/rolfstreefkerk/openapi-with-terraform-on-aws-api-gateway-17je diff --git a/serverless/lambda_http.py b/hands-on/serverless/lambda_http.py similarity index 96% rename from serverless/lambda_http.py rename to hands-on/serverless/lambda_http.py index f4a69b1..a9d8ecf 100644 --- a/serverless/lambda_http.py +++ b/hands-on/serverless/lambda_http.py @@ -1,36 +1,36 @@ -from __future__ import print_function - -import boto3 -import json - -print('Loading function') - - -def lambda_handler(event, context): - '''Provide an event that contains the following keys: - - - operation: one of the operations in the operations dict below - - tableName: required for operations that interact with DynamoDB - - payload: a parameter to pass to the operation being performed - ''' - #print("Received event: " + json.dumps(event, indent=2)) - - operation = event['operation'] - - if 'tableName' in event: - dynamo = boto3.resource('dynamodb').Table(event['tableName']) - - operations = { - 'create': lambda x: dynamo.put_item(**x), - 'read': lambda x: dynamo.get_item(**x), - 'update': lambda x: dynamo.update_item(**x), - 'delete': lambda x: dynamo.delete_item(**x), - 'list': lambda x: dynamo.scan(**x), - 'echo': lambda x: x, - 'ping': lambda x: 'pong' - } - - if operation in operations: - return operations[operation](event.get('payload')) - else: +from __future__ import print_function + +import boto3 +import json + +print('Loading function') + + +def lambda_handler(event, context): + '''Provide an event that contains the following keys: + + - operation: one of the operations in the operations dict below + - tableName: required for operations that interact with DynamoDB + - payload: a parameter to pass to the operation being performed + ''' + #print("Received event: " + json.dumps(event, indent=2)) + + operation = event['operation'] + + if 'tableName' in event: + dynamo = boto3.resource('dynamodb').Table(event['tableName']) + + operations = { + 'create': lambda x: dynamo.put_item(**x), + 'read': lambda x: dynamo.get_item(**x), + 'update': lambda x: dynamo.update_item(**x), + 'delete': lambda x: dynamo.delete_item(**x), + 'list': lambda x: dynamo.scan(**x), + 'echo': lambda x: x, + 'ping': lambda x: 'pong' + } + + if operation in operations: + return operations[operation](event.get('payload')) + else: raise ValueError('Unrecognized operation "{}"'.format(operation)) \ No newline at end of file diff --git a/serverless/main.tf b/hands-on/serverless/main.tf similarity index 95% rename from serverless/main.tf rename to hands-on/serverless/main.tf index a78e4d5..a969e1d 100644 --- a/serverless/main.tf +++ b/hands-on/serverless/main.tf @@ -1,158 +1,158 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 4.0" - } - } -} - -provider "aws" { - region = "us-east-1" -} - -# IAM role for Lambda - -resource "aws_iam_role" "lamda_apigateway_role" { - name = "lamda_apigateway_role" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }] - }) -} - -# IAM policy -resource "aws_iam_policy" "lamda_apigateway_policy" { - name = "lamda_apigateway_policy" - - # Terraform's "jsonencode" function converts a - # Terraform expression result to valid JSON syntax. - policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Action = [ - "dynamodb:DeleteItem", - "dynamodb:GetItem", - "dynamodb:PutItem", - "dynamodb:Query", - "dynamodb:Scan", - "dynamodb:UpdateItem" - ], - Effect = "Allow", - Resource = ["*"] - }, - { - Resource = ["*"], - Action = [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - Effect = "Allow" - } - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lamda_apigateway_role_policy" { - policy_arn = aws_iam_policy.lamda_apigateway_policy.arn - role = aws_iam_role.lamda_apigateway_role.name -} - -# Create Lambda function -data "archive_file" "lambda" { - type = "zip" - source_file = "lambda_http.py" - output_path = "lambda_http_payload.zip" -} - -resource "aws_lambda_function" "demo_http_lambda" { - # If the file is not in the current working directory you will need to include a - # path.module in the filename. - filename = "lambda_http_payload.zip" - function_name = "demo_http_lambda" - role = aws_iam_role.lamda_apigateway_role.arn - - source_code_hash = data.archive_file.lambda.output_base64sha256 - - runtime = "python3.8" - handler = "lambda_http.lambda_handler" - environment { - variables = { - foo = "bar" - } - } -} - -# Create DynamoDB table -resource "aws_dynamodb_table" "basic-dynamodb-table" { - name = "demo_dynamo_db_table" - hash_key = "id" - billing_mode = "PROVISIONED" - read_capacity = 5 - write_capacity = 5 - - attribute { - name = "id" - type = "S" - } - - tags = { - Name = "dynamodb-table-1" - Environment = "production" - } -} - -# Deploy API Gateway -resource "aws_api_gateway_rest_api" "example" { - body = jsonencode({ - openapi = "3.0.1" - info = { - title = "example" - version = "1.0" - } - paths = { - "/path1" = { - post = { - x-amazon-apigateway-integration = { - httpMethod = "POST" - payloadFormatVersion = "1.0" - type = "AWS_PROXY" - uri = "arn:aws:lambda:us-east-1:665370576662:function:demo_http_lambda" - } - } - } - } - }) - - name = "example" - - endpoint_configuration { - types = ["REGIONAL"] - } -} - -resource "aws_api_gateway_deployment" "example" { - rest_api_id = aws_api_gateway_rest_api.example.id - - triggers = { - redeployment = sha1(jsonencode(aws_api_gateway_rest_api.example.body)) - } - - lifecycle { - create_before_destroy = true - } -} - -resource "aws_api_gateway_stage" "example" { - deployment_id = aws_api_gateway_deployment.example.id - rest_api_id = aws_api_gateway_rest_api.example.id - stage_name = "example" -} +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +provider "aws" { + region = "us-east-1" +} + +# IAM role for Lambda + +resource "aws_iam_role" "lamda_apigateway_role" { + name = "lamda_apigateway_role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }] + }) +} + +# IAM policy +resource "aws_iam_policy" "lamda_apigateway_policy" { + name = "lamda_apigateway_policy" + + # Terraform's "jsonencode" function converts a + # Terraform expression result to valid JSON syntax. + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = [ + "dynamodb:DeleteItem", + "dynamodb:GetItem", + "dynamodb:PutItem", + "dynamodb:Query", + "dynamodb:Scan", + "dynamodb:UpdateItem" + ], + Effect = "Allow", + Resource = ["*"] + }, + { + Resource = ["*"], + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + Effect = "Allow" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lamda_apigateway_role_policy" { + policy_arn = aws_iam_policy.lamda_apigateway_policy.arn + role = aws_iam_role.lamda_apigateway_role.name +} + +# Create Lambda function +data "archive_file" "lambda" { + type = "zip" + source_file = "lambda_http.py" + output_path = "lambda_http_payload.zip" +} + +resource "aws_lambda_function" "demo_http_lambda" { + # If the file is not in the current working directory you will need to include a + # path.module in the filename. + filename = "lambda_http_payload.zip" + function_name = "demo_http_lambda" + role = aws_iam_role.lamda_apigateway_role.arn + + source_code_hash = data.archive_file.lambda.output_base64sha256 + + runtime = "python3.8" + handler = "lambda_http.lambda_handler" + environment { + variables = { + foo = "bar" + } + } +} + +# Create DynamoDB table +resource "aws_dynamodb_table" "basic-dynamodb-table" { + name = "demo_dynamo_db_table" + hash_key = "id" + billing_mode = "PROVISIONED" + read_capacity = 5 + write_capacity = 5 + + attribute { + name = "id" + type = "S" + } + + tags = { + Name = "dynamodb-table-1" + Environment = "production" + } +} + +# Deploy API Gateway +resource "aws_api_gateway_rest_api" "example" { + body = jsonencode({ + openapi = "3.0.1" + info = { + title = "example" + version = "1.0" + } + paths = { + "/path1" = { + post = { + x-amazon-apigateway-integration = { + httpMethod = "POST" + payloadFormatVersion = "1.0" + type = "AWS_PROXY" + uri = "arn:aws:lambda:us-east-1:665370576662:function:demo_http_lambda" + } + } + } + } + }) + + name = "example" + + endpoint_configuration { + types = ["REGIONAL"] + } +} + +resource "aws_api_gateway_deployment" "example" { + rest_api_id = aws_api_gateway_rest_api.example.id + + triggers = { + redeployment = sha1(jsonencode(aws_api_gateway_rest_api.example.body)) + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_api_gateway_stage" "example" { + deployment_id = aws_api_gateway_deployment.example.id + rest_api_id = aws_api_gateway_rest_api.example.id + stage_name = "example" +} diff --git a/serverless/test_data.json b/hands-on/serverless/test_data.json similarity index 94% rename from serverless/test_data.json rename to hands-on/serverless/test_data.json index ca73113..b33bf95 100644 --- a/serverless/test_data.json +++ b/hands-on/serverless/test_data.json @@ -1,7 +1,7 @@ -{ - "operation": "echo", - "payload": { - "somekey1": "somevalue1", - "somekey2": "somevalue2" - } +{ + "operation": "echo", + "payload": { + "somekey1": "somevalue1", + "somekey2": "somevalue2" + } } \ No newline at end of file