Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,10 @@ Respuesta errada (404)
## Send us your challenge
Cuando termines el reto, luego de forkear el repositorio, debes crear un pull request to our repository indicando en la descripción de este tu nombre y correo.

### Tiempo de resolución: 3 días
### Tiempo de resolución: 3 días



``
"lambda:package": "npm run build && zip -r lambda-deploy.zip dist node_modules"
``
160 changes: 160 additions & 0 deletions api-gateway.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Crear el API Gateway REST
resource "aws_api_gateway_rest_api" "my_api" {
name = "io-api-prd"
description = "API Gateway REST API for invoking Step Functions and Lambda"
}

# Crear el recurso del API Gateway para payments
resource "aws_api_gateway_resource" "payments" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
parent_id = aws_api_gateway_rest_api.my_api.root_resource_id
path_part = "payments"
}

# Crear el recurso del API Gateway para accounts
resource "aws_api_gateway_resource" "accounts" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
parent_id = aws_api_gateway_rest_api.my_api.root_resource_id
path_part = "accounts"
}

// Unit
resource "aws_api_gateway_resource" "account" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
parent_id = aws_api_gateway_resource.accounts.id
path_part = "{accountId}"
}


# Crear el metodo POST para el recurso payments
resource "aws_api_gateway_method" "post_payment" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.payments.id
http_method = "POST"
authorization = "NONE"
}

# Crear el metodo GET para el recurso accounts
resource "aws_api_gateway_method" "get_account" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.account.id
http_method = "GET"
authorization = "NONE"
request_parameters = {
"method.request.path.accountId" = true
}
}

# Crear la integración de la Step Function con el API Gateway para payments
resource "aws_api_gateway_integration" "post_payment" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.payments.id
http_method = aws_api_gateway_method.post_payment.http_method
integration_http_method = "POST"
type = "AWS"
uri = "arn:aws:apigateway:${var.aws_region}:states:action/StartExecution"
credentials = aws_iam_role.apigateway_stepfunctions_role.arn
request_templates = {
"application/json" = <<EOF
{
"input": "$util.escapeJavaScript($input.json('$'))",
"stateMachineArn": "${aws_sfn_state_machine.sfn_state_machine.arn}"
}
EOF
}
passthrough_behavior = "WHEN_NO_MATCH"
}

# Crear la integración de la función Lambda con el API Gateway para accounts
resource "aws_api_gateway_integration" "get_account" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.account.id
http_method = aws_api_gateway_method.get_account.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.get-account.invoke_arn
}

# Crear la respuesta del metodo POST para payments
resource "aws_api_gateway_method_response" "post_payment_200" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.payments.id
http_method = aws_api_gateway_method.post_payment.http_method
status_code = "200"
}

# Crear la respuesta del metodo GET para account
resource "aws_api_gateway_method_response" "get_account_200" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.account.id
http_method = aws_api_gateway_method.get_account.http_method
status_code = "200"
}

# Crear la respuesta de integración para POST payments
resource "aws_api_gateway_integration_response" "post_payment_200" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.payments.id
http_method = aws_api_gateway_method.post_payment.http_method
status_code = aws_api_gateway_method_response.post_payment_200.status_code
}

# Crear la respuesta de integración para GET account
resource "aws_api_gateway_integration_response" "get_account_200" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
resource_id = aws_api_gateway_resource.account.id
http_method = aws_api_gateway_method.get_account.http_method
status_code = aws_api_gateway_method_response.get_account_200.status_code
}

# Crear el deployment del API Gateway
resource "aws_api_gateway_deployment" "my_api_deployment" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
depends_on = [
aws_api_gateway_integration.post_payment,
aws_api_gateway_integration.get_account
]
}

# Crear la etapa del API Gateway
resource "aws_api_gateway_stage" "my_api_stage" {
rest_api_id = aws_api_gateway_rest_api.my_api.id
deployment_id = aws_api_gateway_deployment.my_api_deployment.id
stage_name = "v1"
}

# Crear el rol de IAM para la integración de API Gateway con Step Functions
resource "aws_iam_role" "apigateway_stepfunctions_role" {
name = "apigateway_stepfunctions_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}

# Adjuntar la política de permisos al rol de integración de API Gateway con Step Functions
resource "aws_iam_role_policy" "apigateway_stepfunctions_policy" {
role = aws_iam_role.apigateway_stepfunctions_role.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "states:StartExecution",
"Resource": "${aws_sfn_state_machine.sfn_state_machine.arn}"
}
]
}
EOF
}
14 changes: 14 additions & 0 deletions dynamodb-accounts.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "aws_dynamodb_table" "accounts" {
name = "accounts"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"

attribute {
name = "id"
type = "S"
}

tags = {
Name = "accounts"
}
}
23 changes: 23 additions & 0 deletions dynamodb-transactions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# DynamoDB table for transactions enabled with dynamodb streams new and old images
resource "aws_dynamodb_table" "transactions" {
name = "transactions"
billing_mode = "PAY_PER_REQUEST"
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
hash_key = "source"
range_key = "id"

attribute {
name = "source"
type = "S"
}

attribute {
name = "id"
type = "S"
}

tags = {
Name = "transactions"
}
}
134 changes: 134 additions & 0 deletions execute-pyment-stf.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# ...

resource "aws_sfn_state_machine" "sfn_state_machine" {
name = "my-state-machine"
role_arn = aws_iam_role.iam_for_sfn.arn

definition = jsonencode({
StartAt = "GetAccount"
States = {
GetAccount = {
Type = "Task"
Resource = "arn:aws:states:::dynamodb:getItem"
Parameters = {
TableName = "accounts"
Key = {
"id" = { "S.$" = "$.accountId" }
}
}
ResultPath = "$.resultGetAccount"
Next = "ValidateAccount"
}
ValidateAccount = {
Type = "Choice"
Choices = [
{
Variable = "$.resultGetAccount.Item"
IsPresent = true
Next = "execute-payments"
}
]
Default = "Fail"
}
execute-payments = {
Type = "Task"
Resource = aws_lambda_function.execute-payments.arn
Parameters = {
"accountId.$" = "$.resultGetAccount.Item.id.S"
"amount.$" = "$.amount"
}
ResultPath = "$.paymentResult"
Next = "SaveTransaction"
}
SaveTransaction = {
Type = "Task"
Resource = "arn:aws:states:::dynamodb:putItem"
Parameters = {
TableName = "transactions"
Item = {
"source" = { "S.$" = "$.paymentResult.source" }
"id" = { "S.$" = "$.paymentResult.id" }
"data" = {
"M" = {
"accountId" = { "S.$" = "$.resultGetAccount.Item.id.S" }
"amount" = { "N.$" = "States.JsonToString($.paymentResult.amount)" }
}
}
}
}
ResultPath = "$.putTransactionResult"
Next = "Success"
}
Success = {
Type = "Succeed"
}
Fail = {
Type = "Fail"
}
}
})
}

resource "aws_iam_role" "iam_for_sfn" {
name = "iam_for_sfn"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}

resource "aws_iam_policy" "sfn_policy_lambda" {
name = "sfn_policy_lambda"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:ListFunctions"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_policy" "sfn_policy_dynamodb" {
name = "sfn_policy_dynamodb"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem"
],
"Resource": "*"
}
]
}
EOF
}

resource "aws_iam_role_policy_attachment" "sfn_policy_lambda_attachment" {
role = aws_iam_role.iam_for_sfn.name
policy_arn = aws_iam_policy.sfn_policy_lambda.arn
}
resource "aws_iam_role_policy_attachment" "sfn_policy_dynamodb_attachment" {
role = aws_iam_role.iam_for_sfn.name
policy_arn = aws_iam_policy.sfn_policy_dynamodb.arn
}
Loading