Is there a way we can (integration) test a Lambda for AWS using testcontainers & the following LocalStackContainer:
new LocalStackContainer(DockerImageName.parse('localstack/localstack:0.11.6'))
.withServices(LocalStackContainer.Service.LAMBDA)
Specifically, how do I "upload" the Lambda to the locally running service, so that I can then trigger & test it?
I've managed to setup Localstack and a MySql testcontainer (in groovy spock) like so:
@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')
Once the container is up and running the lambda can be deployed using awslocal and standard CLI commands:
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}}"
)
Finally, the lambda can be manually triggered in tests like so:
localStack.execInContainer('awslocal', 'lambda', 'invoke', '--function-name', 'lambda-name', 'output0.json')