我需要在指定的环境中创建资源。例如,如果我有一个AWS Lambda还没有准备好进行生产,我需要它只存在于开发环境中。有什么好方法吗?我知道可以将count
设置为0,但我不确定如何将此决定级联到其他资源。
例如,我有一个AWS Lambda的资源,并且count
设置为0。
resource "aws_lambda_function" "example_lambda" {
count ? local.is_production ? 0 : 1
}
如何将此决定级联到依赖于上述AWS Lambda的其他资源?
假设我有一个S3 Bucket,它将调用Lambda函数。
resource "aws_s3_bucket" "example_bucket" {
bucket = "bucket_name"
}
resource "aws_lambda_permission" "example_bucket_etl" {
statement_id = "AllowExecutionFromS3Bucket"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.example_lambda.arn
principal = "s3.amazonaws.com"
source_arn = aws_s3_bucket.example_bucket.arn
}
resource "aws_s3_bucket_notification" "bucket_notification" {
bucket = aws_s3_bucket.example_bucket.id
lambda_function {
lambda_function_arn = aws_lambda_function.example_lambda.arn
events = ["s3:ObjectCreated:*"]
filter_prefix = "example_bucket/"
filter_suffix = ".txt"
lambda_function {
lambda_function_arn = aws_lambda_function.another_lambda_function.arn
events = ["s3:ObjectCreated:*"]
filter_prefix = "another_example_bucket/"
filter_suffix = ".txt"
}
}
您可以在多个资源上使用相同的计数变量。如果代码中可能的话,一个更好、更清晰的方法是将所有资源添加到一个模块中。https://www.terraform.io/docs/language/meta-arguments/count.html
当在resource
块中使用count
时,Terraform会将对其他资源的引用视为生成表示该资源的每个实例的对象列表。
由于该值只是一个普通的列表值,您可以取其长度,以便简明地写下本质上是语句"的内容;每个X〃应该有一个Y;,或者在您的具体情况下";对于每个lambda函数应该有一个lambda权限;。
例如:
resource "aws_lambda_function" "example" {
count = local.is_production ? 0 : 1
# ...
}
resource "aws_lambda_permission" "example_bucket_etl" {
count = length(aws_lambda_function.example)
function_name = aws_lambda_function.example[count.index].name
# ...
}
在aws_lambda_permission
配置中,我们首先将计数设置为aws_lambda_function.example
的计数,这告诉Terraform我们希望这些计数始终匹配。这种连接有助于Terraform了解如何解决增加或减少计数的情况,暗示产生的创建/销毁操作需要按照特定顺序进行才能有效。然后,我们使用count.index
来引用其他资源的索引,在这种情况下,它只会为零,但这有助于Terraform在验证过程中理解我们的意图。
aws_s3_bucket_notification
中的lambda_function
嵌套块需要稍微不同的策略,因为在这种情况下,我们不是为每个lambda函数创建单独的资源实例,而是在单个资源实例中生成一些动态配置块。对于这种情况,我们可以使用dynamic
块,它作为一种宏,用于基于集合的元素生成多个块:
resource "aws_s3_bucket_notification" "bucket_notification" {
bucket = aws_s3_bucket.example_bucket.id
dynamic "lambda_function" {
for_each = aws_lambda_function.example
content {
# "lambda_function" in this block is the iterator
# symbol, so lambda_function.value refers to the
# current element of aws_lambda_function.example.
lambda_function_arn = lambda_function.value.arn
# ...
}
}
}
同样,这依赖于aws_lambda_function.example
是一个对象列表,但方式不同:我们要求Terraform为aws_lambda_function.example
的每个元素生成一个lambda_function
块,将lambda_function.value
设置为与每个块对应的整个aws_lambda_function
对象。因此,我们可以访问该对象的.arn
属性,以获得我们需要在块内填充lambda_function_arn
参数的相应ARN。
同样,在这种情况下,只有零个或一个lambda函数对象,因此只有零个或者一个lambda_function
块,但在这两种情况下,这种模式都推广到count
的其他值,确保所有这些都将随着配置的发展而保持一致。