Я пишу Terraform для развертывания корзины S3 и лямбды. Необходима корзина S3, так как именно здесь будет храниться zip-объект, готовый к развертыванию в лямбда-выражении.
У меня есть два модуля в моем файле main.tf верхнего уровня:
module "s3" {
count = var.enable_s3 ? 1 : 0
source = "./modules/s3"
}
module "lambdas" {
count = var.enable_lambdas ? 1 : 0
source = "./modules/lambdas"
bucket_id = module.s3.lambda_bucket_id
}
модуль s3:
main.tf
resource "aws_s3_bucket" "lambda_bucket" {
bucket = "lunchboxd-lambdas"
tags = {
Owner = "Terraform",
Description = "A bucket to hold the lambdas zip"
}
}
выходы.tf
output "lambda_bucket_id" {
value = aws_s3_bucket.lambda_bucket.id
description = "ID of the bucket holding the lambda functions."
}
лямбда-модуль:
переменные.tf
variable "bucket_id" {}
main.tf
data "archive_file" "lambda_hello_world" {
type = "zip"
source_dir = "${path.module}/hello-world"
output_path = "${path.module}/hello-world.zip"
}
resource "aws_s3_object" "lambda_hello_world" {
bucket = var.bucket_id
key = "hello-world.zip"
source = data.archive_file.lambda_hello_world.output_path
etag = filemd5(data.archive_file.lambda_hello_world.output_path)
}
resource "aws_lambda_function" "hello_world" {
function_name = "HelloWorld"
s3_bucket = var.bucket_id
s3_key = aws_s3_object.lambda_hello_world.key
runtime = "nodejs12.x"
handler = "hello.handler"
source_code_hash = data.archive_file.lambda_hello_world.output_base64sha256
role = aws_iam_role.lambda_exec.arn
}
resource "aws_cloudwatch_log_group" "hello_world" {
name = "/aws/lambda/${aws_lambda_function.hello_world.function_name}"
retention_in_days = 30
}
resource "aws_iam_role" "lambda_exec" {
name = "serverless_lambda"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
Когда я пытаюсь проверить свою терраформу, я получаю следующую ошибку:
╷
│ Error: Unsupported attribute
│
│ on main.tf line 36, in module "lambdas":
│ 36: bucket_id = module.s3.aws_s3_bucket.lambda_bucket.id
│ ├────────────────
│ │ module.s3 is a list of object, known only after apply
│
│ Can't access attributes on a list of objects. Did you mean to access an attribute for a specific element of the list, or across all elements of the list?
╵
Я следил за документацией по выходным данным и композиции модулей, но я не уверен, что делаю неправильно. Вся помощь приветствуется.
Ваш блок module "s3"
имеет мета-аргумент count
, поэтому здесь применяется документация Ссылаясь на экземпляры.
В частности, module.s3
— это список объектов, а не просто один объект (как указано в сообщении об ошибке), поэтому, когда вы ссылаетесь на него, вам нужно указать, на какой из элементов этого списка вы хотите ссылаться.
В вашем случае у вас есть только ноль или один экземпляр модуля, поэтому module.s3
будет списком из нуля или одного элемента. Поэтому вам нужно будет объяснить Terraform, что должно произойти, если элементов module.s3
нет, но есть один экземпляр module.lambdas
.
Если допустимо, чтобы переменная bucket_id
в module "lambdas"
была нулевой, когда нет ведра, один из способов написать это — использовать функция one
для преобразования списка либо в одно значение, если он имеет один элемент, либо в null
, если в нем нет элементов. :
bucket_id = one(module.s3.aws_s3_bucket[*].lambda_bucket.id)
В этом выражении сначала используется оператор знака [*]
для перевода из списка объектов в список только значений id
, а затем используется one
для перевода либо в одну строку, либо в нулевое значение.
Если вам нужно, чтобы bucket_id
имел какое-то другое значение в случае, когда нет экземпляров module.s3
, вам нужно указать здесь некоторую другую логику, чтобы описать, как заполнить эту переменную в этом случае. Что именно делать, будет зависеть от нужного вам правила перевода; вы можете использовать любое выражение или функцию языка Terraform, чтобы принять здесь динамическое решение.