#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')