ApexでデプロイしたLambdaのトリガーをTerraformで管理する

awsnode.jsterraform

Apexでfunctionをデプロイするとトリガーが登録されないのであとで追加することになる。 これを手作業で行うこともできるのだが、せっかくなのでアプリケーションと一緒に管理したい。 そんなときのためにterraformコマンドをラップしたapex infraが用意されている。

TerraformでVPCを管理するmoduleを作る - sambaiz-net

functionsと同列にinfrastructureディレクトリを作成してtfファイルを置く。 その下に環境ごとのディレクトリを作成することもできて、その場合は –env で指定した環境のものが使われる。

- functions
- infrastructure
  main.tf
  variables.tf
  - modules
    - cloudwatch_schedule
      main.tf
      variables.tf
project.json 

functionをデプロイするとそのARNが変数で取れるようになる。

$ apex list --tfvars
apex_function_hello="arn:aws:lambda:ap-northeast-1:*****:function:usetf_hello"

今回設定するトリガーはCloudwatch Eventのスケジューリング。作成するリソースは以下の通り。

$ cat infrastructure/modules/cloudwatch_schefule/variables.tf
variable "lambda_function_name" {}
variable "lambda_function_arn" {}
variable "schedule_expression" {
    description = "cloudwatch schedule expression e.g. \"cron(0/5 * * * ? *)\""
}

$ cat infrastructure/modules/cloudwatch_schefule/main.tf
resource "aws_cloudwatch_event_rule" "lambda" {
  name        = "lambda_rule_${var.lambda_function_name}"
  description = "invoke lambda ${var.lambda_function_name}"
  schedule_expression = "${var.schedule_expression}"
}
 
resource "aws_cloudwatch_event_target" "lambda" {
  target_id = "lambda_target_${var.lambda_function_name}"
  rule      = "${aws_cloudwatch_event_rule.lambda.name}"
  arn       = "${var.lambda_function_arn}"
}
 
resource "aws_lambda_permission" "lambda" {
  statement_id  = "AllowExecutionFromCloudWatch"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_cloudwatch_event_target.lambda.arn}"
  principal     = "events.amazonaws.com"
  source_arn    = "${aws_cloudwatch_event_rule.lambda.arn}"
}
$ cat infrastructure/variables.tf 
variable "apex_function_names" {
    type="map"
}
variable "apex_function_hello" {}

$ cat infrastructure/main.tf
terraform {
  backend "s3" {
    bucket = "sambaiz-terraform"
    key    = "usetf.tfstate"
    region = "ap-northeast-1"
  }
}

module "hello_trigger" {
  source = "./modules/cloudwatch_schedule"
  lambda_function_name = "${var.apex_function_names["hello"]}"
  lambda_function_arn = "${var.apex_function_hello}"
  schedule_expression = "cron(0/5 * * * ? *)"
}

initしてbackendを初期化してmoduleを準備する。

$ apex infra init
$ ls infrastructure/.terraform/modules/*****
main.tf		variables.tf

planするとこんな感じ。ApexによってfunctionのARNが渡っていることが分かる。

$ apex infra plan
+ module.hello_trigger.aws_cloudwatch_event_rule.lambda
    arn:                 "<computed>"
    description:         "invoke lambda usetf_hello"
    is_enabled:          "true"
    name:                "lambda_rule_usetf_hello"
    schedule_expression: "cron(0/5 * * * ? *)"

+ module.hello_trigger.aws_cloudwatch_event_target.lambda
    arn:       "arn:aws:lambda:ap-northeast-1:*****:function:usetf_hello"
    rule:      "lambda_rule_usetf_hello"
    target_id: "lambda_target_usetf_hello"

+ module.hello_trigger.aws_lambda_permission.lambda
    action:        "lambda:InvokeFunction"
    function_name: "arn:aws:lambda:ap-northeast-1:*****:function:usetf_hello"
    principal:     "events.amazonaws.com"
    source_arn:    "${aws_cloudwatch_event_rule.lambda.arn}"
    statement_id:  "AllowExecutionFromCloudWatch"

applyするとトリガーが登録される。

$ apex infra apply
$ apex logs hello
...
/aws/lambda/usetf_hello 2017-11-12T13:20:14.561Z	37e75818-c7ac-11e7-a333-111863808b13	processing event:
...
/aws/lambda/usetf_hello 2017-11-12T13:25:15.182Z	eb178941-c7ac-11e7-bde0-998ea9659640 processing event:

参考

ApexとTerraformでCloudWatch EventsによりInvokeされるLambda関数をデプロイする | Developers.IO