通过terraform定义以下lambda函数和DynamoDB:

provider "aws" {
  region                  = "us-east-1"  # Change to your desired region
  access_key              = "test"       # Access key for LocalStack
  secret_key              = "test"       # Secret key for LocalStack
  skip_credentials_validation = true
  skip_requesting_account_id = true

  endpoints {
    dynamodb    = "http://localhost:4566"  # LocalStack DynamoDB endpoint
    lambda      = "http://localhost:4566"
    iam         = "http://localhost:4566"
  }
}

resource "aws_iam_role" "lambda_execution_role" {
  name = "lambda_execution_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "sts:AssumeRole",
        Effect = "Allow",
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_dynamodb_access" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"
  role       = aws_iam_role.lambda_execution_role.name
}

resource "aws_iam_role_policy" "lambda_execution_policy" {
  name   = "lambda_execution_policy"
  role   = aws_iam_role.lambda_execution_role.id

  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ],
        Effect   = "Allow",
        Resource = "*"
      },
      {
        Action   = "lambda:InvokeFunction",
        Effect   = "Allow",
        Resource = aws_lambda_function.add_user_post.arn
      }
      # Add more permissions as needed
    ]
  })
}

resource "aws_lambda_function" "add_user_post" {
  function_name = "AddUserPost"
  handler       =   "addUserPostFunction.lambda_handler"
  runtime       = "python3.8"
  filename      = data.archive_file.lambda_function_add_user_post.output_path  # ZIP file containing your Python code
  role          = aws_iam_role.lambda_execution_role.arn
  source_code_hash = filebase64sha256(data.archive_file.lambda_function_add_user_post.output_path)

  environment {
    variables = {
      TABLE_NAME = "UserProfileTable"
    }
  }
}

data "archive_file" "lambda_function_add_user_post" {
  type          = "zip"
  source_dir    = "${path.module}/Source"
  output_path   = "${path.module}/lambda_function_add_user_post.zip"


}

DynamoDB:

 provider "aws" {
      region                  = "us-east-1"  # Change to your desired region
      access_key              = "test"       # Access key for LocalStack
      secret_key              = "test"       # Secret key for LocalStack
      skip_credentials_validation = true
      skip_requesting_account_id = true
    
    
      endpoints {
        dynamodb    = "http://localhost:4566"  # LocalStack DynamoDB endpoint
        lambda      = "http://localhost:4566"
      }
    }
    
    resource "aws_dynamodb_table" "users_table" {
      name           = "UserProfileTable"
      billing_mode   = "PROVISIONED"  # Or use "PAY_PER_REQUEST" for on-demand capacity
      read_capacity  = 5
      write_capacity = 5
      hash_key = "UserID"
      range_key = "PostID"
    
      attribute {
        name = "UserID"
        type = "N"
      }
    
      attribute {
        name = "PostID"
        type = "N"
      }
    
    
    
      tags = {
        Name    = "dynamodb-table-1"
        Environment = "production"
      }
    }

然后是lambda执行的.py函数:

import boto3
import os


dynamodb = boto3.resource('dynamodb', region_name='us-east-1', endpoint_url='http://localhost:4566')

def lambda_handler(event, context):
    try:
        # Your DynamoDB table name
        table_name = os.environ["TABLE_NAME"]

        # Sample data to be added to DynamoDB
        item = {
            'userid': '1',
            'postid': '1',
            'content': 'Yay!',
        }

        # DynamoDB put operation
        table = dynamodb.Table(table_name)
        result = table.put_item(Item=item)

        print('Item added to DynamoDB:', result)

        return {
            'statusCode': 200,
            'body': 'Item added to DynamoDB successfully',
        }
    except Exception as e:
        print('Error adding item to DynamoDB:', e)

        return {
            'statusCode': 500,
            'body': 'Error adding item to DynamoDB',
        }

Terraform apply判断这两个基础设施组件不会产生任何错误,我可以通过awslocal dynamodb list-tablesawslocal lambda list-functions判断它们是否存在,并且它们返回期望值.

然而,在 run 时:awslocal --endpoint-url=http://localhost:4566 lambda invoke --function-name AddUserPost --payload '{}' output.json

我得到

{
    "StatusCode": 200,
    "FunctionError": "Unhandled",
    "ExecutedVersion": "$LATEST"
}

output.json只股票的yield 率为: {"errorMessage":"2024-02-10T16:42:23Z cd163c6c-75d4-4be2-9539-cec447c3624a Task timed out after 3.00 seconds"}

unhandled函数错误让我认为问题出在lambda函数中定义的处理程序上,但我已经三次判断了这个函数的语法/拼写,我非常确定它是正确的.不确定如何继续.

编辑:根据Helder下面的回答,有必要修改插入中的数据类型.这消除了一个错误,但随后导致invoke导致无法连接到端点.这个stack question有一个答案,说明boto3运行时应该将endpoint_url=‘http://host.docker.internal:4566`.设置为对mewhy不清楚这是必要的,但它完全解决了这个问题.

推荐答案

错误似乎出在您试图放入DynamoDB中的数据中

在表属性声明中,我们可以看到:

      attribute {
        name = "UserID"
        type = "N"
      }
    
      attribute {
        name = "PostID"
        type = "N"
      }

当我们呼叫table.put_item(Item=item)的时候,你必须保持同样的情况

我让它是这样工作的:

        item = {
            'UserID': 1,
            'PostID': 1,
            'content': 'Yay!',
        }

I can see the item created correctly in the table:


完全公开我没有使用本地堆栈直接在AWS中测试,从 comments 来看,本地堆栈可能会吞下错误,并让lambda超时

Python相关问答推荐

如何调整spaCy token 化器,以便在德国模型中将数字拆分为行末端的点

仿制药的类型铸造

为什么我的Python代码在if-else声明中的行之前执行if-else声明中的行?

如何让剧作家等待Python中出现特定cookie(然后返回它)?

. str.替换pandas.series的方法未按预期工作

有症状地 destruct 了Python中的regex?

优化pytorch函数以消除for循环

加速Python循环

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

如何在Python中使用另一个数据框更改列值(列表)

从Windows Python脚本在WSL上运行Linux应用程序

为什么\b在这个正则表达式中不解释为反斜杠

Odoo16:模板中使用的docs变量在哪里定义?

比Pandas 更好的 Select

Polars Group by描述扩展

如何在FastAPI中替换Pydantic的constr,以便在BaseModel之外使用?'

具有不匹配列的2D到3D广播

时间戳上的SOAP头签名无效

将索引表转换为Numy数组

是否将列表分割为2?