Тестирование интеграции LocalStackContainer с лямбда

#java #aws-lambda #spock #testcontainers #localstack

#java #aws-lambda #спок #тестовые контейнеры #localstack

Вопрос:

Есть ли способ, которым мы можем (интегрировать) протестировать лямбду для AWS, используя testcontainers и следующий LocalStackContainer:

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

В частности, как мне «загрузить» лямбду в локально запущенную службу, чтобы затем я мог ее запустить и протестировать?

Ответ №1:

После LocalStackContainer запуска вы можете выполнять команды внутри контейнера для настройки своей инфраструктуры. LocalStack предоставляет awslocal двоичный файл для создания любых ресурсов AWS.

Затем внутри вашего теста у вас может быть @BeforeAll шаг, на котором вы используете свою ссылку на контейнер и создаете все.

Следующий пример делает это для S3 и SQS (ссылка из этого сообщения в блоге):

 @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 может быть создан следующим образом:

 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
  

Комментарии:

1. Спасибо @rieckpil это выглядит как хорошая отправная точка! Я попробую!

Ответ №2:

Мне удалось настроить Localstack и MySQL testcontainer (в groovy 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 позволяет лямбде взаимодействовать с MySQL, SQS и т. Д.
  • Файл lambda jar копируется в контейнер (с помощью copyfiletocontainer)
  • Мне также нужны были KMS, поэтому seed.yaml инициализирует его (см. Документацию Local KMS)

После того, как контейнер запущен и запущен, lambda может быть развернут с помощью awslocal и стандартных команд CLI:

     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}}"
    )
  

Наконец, лямбда-код может быть запущен вручную в таких тестах:

 localStack.execInContainer('awslocal', 'lambda', 'invoke', '--function-name', 'lambda-name', 'output0.json')