commit fcb4920acccf3cd4dc195f25c06827b7e355d4cc Author: Kfir Dayan Date: Tue Jul 11 18:45:59 2023 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da6ebff --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.terraform +.terraform.lock.hcl +terraform.tfstate +terraform.tfstate.backup \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..efbc38d --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +## S3 bucket with a Lambda function as a listener and append to a DynamoDB table With Terraform + +This is a simple example of how to use a Lambda function as a listener for an S3 bucket and append the data to a DynamoDB table. + +### Prerequisites + +- Terraform 1.4.x +- AWS CLI +- AWS account with permissions to create the resources +- AWS credentials configured + +## Usage + +1. Clone this repository +2. go to ``` locals.tf ``` in the root directory and change the account_id to your own account id +3. need to make sure the javascript file inside ``` module/lambda/files/lambda_function.zip ``` is wil the right region and table name +4. Run `terraform init` +5. Run `terraform apply` + +## Example playlod file *.json + +``` json +{ + "id": "00a6fa25-df29-4701-9077-557932591766", + "timestamp": 23764783264, + "data": "CONTENT OF THE FILE" +} +``` + + +### Test +1. Upload a file to the S3 bucket +2. Check the DynamoDB table for the new item +3. check the CloudWatch logs for the Lambda function diff --git a/locals.tf b/locals.tf new file mode 100644 index 0000000..bd7c3ed --- /dev/null +++ b/locals.tf @@ -0,0 +1,7 @@ +locals { + account_id = "539634357948" + default_tags = { + Project = "my-project" + Owner = "my-team" + } +} \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..fb1f93d --- /dev/null +++ b/main.tf @@ -0,0 +1,29 @@ +provider "aws" { + region = var.regoin +} + +module "role" { + source = "./modules/iam/role" + account_id = local.account_id + s3_bucket = var.s3_bucket + dynamodb_table_name = var.dynamodb_table_name +} + +module "dynamodb" { + source = "./modules/dynamodb" + table_name = var.dynamodb_table_name +} + +module "s3" { + source = "./modules/s3" + s3_bucket = var.s3_bucket +} + +module "lambda_function" { + source = "./modules/lambda" + + lambda_function_role = module.role.arn + s3_bucket = var.s3_bucket + project = var.project + s3_arn = module.s3.s3_bucket_arn +} diff --git a/modules/dynamodb/main.tf b/modules/dynamodb/main.tf new file mode 100644 index 0000000..cd921ea --- /dev/null +++ b/modules/dynamodb/main.tf @@ -0,0 +1,67 @@ +resource "aws_dynamodb_table" "lambda_table" { + name = var.table_name + billing_mode = var.billing_mode + hash_key = var.hash_key + range_key = var.range_key + + attribute { + name = var.hash_key + type = var.hash_key_type + } + + attribute { + name = var.range_key + type = "N" + } + + attribute { + name = "data" + type = "S" + } + + attribute { + name = "timestampIndex" + type = var.sort_key_type + } + + global_secondary_index { + name = "data-index" + hash_key = "data" + projection_type = "ALL" + read_capacity = var.read_capacity_units + write_capacity = var.write_capacity_units + non_key_attributes = [] + } + + global_secondary_index { + name = "id-index" + hash_key = "id" + projection_type = "ALL" + read_capacity = var.read_capacity_units + write_capacity = var.write_capacity_units + non_key_attributes = [] + } + + global_secondary_index { + name = "timestamp-index" + hash_key = "timestampIndex" + range_key = var.range_key + read_capacity = var.read_capacity_units + write_capacity = var.write_capacity_units + projection_type = "INCLUDE" + non_key_attributes = ["id", "data"] + } +} + + +output "name" { + value = aws_dynamodb_table.lambda_table.name +} + +output "arn" { + value = aws_dynamodb_table.lambda_table.arn +} + +output "stream_arn" { + value = aws_dynamodb_table.lambda_table.stream_arn +} diff --git a/modules/dynamodb/variables.tf b/modules/dynamodb/variables.tf new file mode 100644 index 0000000..c00fcf7 --- /dev/null +++ b/modules/dynamodb/variables.tf @@ -0,0 +1,53 @@ +variable "table_name" { + description = "The name of the table" + type = string + default = "example" +} + +variable "billing_mode" { + description = "The billing mode of the table" + type = string + default = "PAY_PER_REQUEST" +} + +variable "range_key" { + description = "The name of the range key in the table" + type = string + default = "timestamp" +} + +variable "hash_key" { + description = "The name of the hash key in the table" + type = string + default = "id" +} + +variable "hash_key_type" { + description = "The type of the hash key in the table" + type = string + default = "S" +} + +variable "sort_key" { + description = "The name of the sort key in the table" + type = string + default = "timestamp" +} + +variable "sort_key_type" { + description = "The type of the sort key in the table" + type = string + default = "N" +} + +variable "read_capacity_units" { + description = "The number of read capacity units for the DynamoDB table" + type = number + default = 5 +} + +variable "write_capacity_units" { + description = "The number of write capacity units for the DynamoDB table" + type = number + default = 5 +} \ No newline at end of file diff --git a/modules/iam/role/main.tf b/modules/iam/role/main.tf new file mode 100644 index 0000000..147821b --- /dev/null +++ b/modules/iam/role/main.tf @@ -0,0 +1,90 @@ +data "aws_iam_policy_document" "assume_role_policy" { + statement { + effect = "Allow" + + actions = ["sts:AssumeRole"] + principals { + type = "Service" + identifiers = ["lambda.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "role_for_lambda" { + name = var.role_name + assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json + + depends_on = [data.aws_iam_policy_document.assume_role_policy] +} + +resource "aws_iam_role_policy" "lambda_policy" { + + name = "lambda_policy" + role = aws_iam_role.role_for_lambda.id + policy = <