LocalStackContainer集成测试lambda

问题描述

有没有一种方法可以使用testcontainers和以下LocalStackContainer(集成)为AWS测试Lambda:

new LocalStackContainer(DockerImageName.parse('localstack/localstack:0.11.6'))
    .withServices(LocalStackContainer.Service.LAMBDA)

具体来说,如何将Lambda“上载”到本地运行的服务,以便随后触发并测试它?

解决方法

启动LocalStackContainer之后,您可以在容器内执行命令以设置基础结构。 LocalStack提供awslocal二进制文件以创建任何AWS资源。

在测试内部,您可以执行一个@BeforeAll步骤,您可以在其中使用容器引用并创建所有内容。

以下示例对S3和SQS(来自此blog post的引用)执行此操作:

@Testcontainers
@SpringBootTest
public class YourLocalStackIT {
 
  @Container
  static LocalStackContainer localStack = new LocalStackContainer("0.11.6")
    .withServices(S3,SQS)
    .withEnv("DEFAULT_REGION","eu-central-1");
 
  @BeforeAll
  static void beforeAll() throws IOException,InterruptedException {
    localStack.execInContainer("awslocal","sqs","create-queue","--queue-name",QUEUE_NAME);
    localStack.execInContainer("awslocal","s3","mb","s3://" + BUCKET_NAME);
  }
 
  private static final String QUEUE_NAME = "order-event-test-queue";
  private static final String BUCKET_NAME = "order-event-test-bucket";
 
  // ... actual test
}

您可以将其用作模板,以准备您的AWS Lambda函数。

关于源代码上传,我认为将.zip版本的Lambda也挂载或复制到容器中以在内部访问它是很有意义的。

可以如下创建NodeJS lambada:

awslocal lambda create-function \
    --region eu-central1 \
    --function-name your-api \
    --runtime nodejs8.10 \
    --handler lambda.apiHandler \
    --memory-size 128 \
    --zip-file fileb://api-handler.zip
,

我已经成功设置了Localstack和一个MySql testcontainer(在普通的spock中),如下所示:

  @Shared
  public static Network network = Network.newNetwork()

  @Shared
  @ClassRule
  public static MySQLContainer mySql = new MySQLContainer(DockerImageName.parse('mysql:5.7'))
    .withNetwork(network)
    .withNetworkAliases(MY_SQL_HOST_NAME) as MySQLContainer

  @Shared
  @ClassRule
  public static LocalStackContainer localStack = new LocalStackContainer(DockerImageName.parse('localstack/localstack:0.11.6'))
    .withServices(SQS,LAMBDA,CLOUDWATCH,DYNAMODB,KMS,STS,IAM)
    .withNetwork(network)
    .withEnv('LAMBDA_DOCKER_NETWORK',network.name)
    .withCopyFileToContainer(MountableFile.forHostPath(new File('the jar file').path),'/opt/code/localstack/lambda.jar')
    .withCopyFileToContainer(MountableFile.forClasspathResource('seed.yaml'),'/init/seed.yaml')
  • 这将建立桥接网络,以便两个容器可以 互相交流。还将LAMBDA_DOCKER_NETWORK设置为允许lambda与MySql,SQS等进行通信。
  • 将lambda jar文件复制到容器(withCopyFileToContainer)
  • 我还需要KMS,因此seed.yaml会对其进行初始化(请参阅本地KMS文档)

一旦容器启动并运行,就可以使用awslocal和标准CLI命令部署lambda:

    def result = localStack.execInContainer(
      'awslocal','lambda','create-function','--function-name','lambda-name','--runtime','java8','--handler','uk.co.blah.blah.Handler','--role','arn:aws:iam::123456:role/irrelevant','--zip-file','fileb://lambda.jar','--environment',"Variables={MY_SQL_USERNAME=${mySql.username},MY_SQL_PASSWORD=${encryptedDbPassword},PLATFORM_DB_URL=${"jdbc:mysql://${MY_SQL_HOST_NAME}:3306"}," +
        "AWS_REGION=${localStack.region}}"
    )

最后,可以在如下测试中手动触发lambda:

localStack.execInContainer('awslocal','invoke','output0.json')

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...