我有一个包含Terraform代码的Git存储库,它正在部署到AWS中。我将Localstack添加到这个存储库中,这样我就可以在计划之前进行更高级的验证测试,并将其应用到我的实际AWS帐户中。为了使用Localstack,我必须创建一个带有自定义端点的新提供商:
provider "aws" {
alias = "real"
region = "${local.aws_region}"
}
provider "aws" {
alias = "fake"
region = "${local.aws_region}"
access_key = "fake"
secret_key = "fake"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
dynamodb = "http://localhost:4566"
lambda = "http://localhost:4566"
kinesis = "http://localhost:4566"
}
}
如何在不复制代码的情况下,为Localstack使用一个提供商,为AWS使用一个提供商?
不幸的是,由于这两种情况之间的配置结构有很大的不同,因此不可能在不使结果配置看起来相当复杂的情况下实现动态切换,但是可以使用Terraform语言表达式操作符和dynamic
块有条件地设置所有提供程序参数。这样就有了一个带有动态设置的单一提供商配置,而不是两个独立的提供商配置。
首先要决定的是你将如何在这两种可能性之间做出选择。因为你的localstack伪基础结构将不可避免地与"真实的"不同。我希望您希望为它使用单独的状态,因此使用单独的工作空间进行开发/测试可能是一种合理的情况,并且我将编写这个示例,假设无论何时选择工作空间dev
, localstack配置都应该是活动的。如果这不是你想要的,那么希望这应该仍然足以适应你的需求。
locals {
use_localstack = (terraform.workspace == "dev")
aws_settings = (
local.use_localstack ?
{
region = local.aws_region
access_key = "fake"
secret_key = "fake"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
override_endpoint = "http://localhost:4566"
} :
{
region = local.aws_region
access_key = null
secret_key = null
skip_credentials_validation = null
skip_metadata_api_check = null
skip_requesting_account_id = null
override_endpoint = null
}
)
}
provider "aws" {
region = local.aws_settings.region
access_key = local.aws_settings.access_key
secret_key = local.aws_settings.secret_key
skip_credentials_validation = local.aws_settings.skip_credentials_validation
skip_metadata_api_check = local.aws_settings.skip_metadata_api_check
skip_requesting_account_id = local.aws_settings.skip_requesting_account_id
dynamic "endpoints" {
for_each = local.aws_settings.override_endpoint[*]
content {
dynamodb = endpoints.value
lambda = endpoints.value
kinesis = endpoints.value
}
}
}
以上依赖于Terraform语言的两个特定行为:
- 当设置将传递给提供者的参数时,设置
null
总是与省略该参数相同,因为Terraform内部通过隐式设置它们为null
来处理未设置的参数。 - 使用非列表值的
[*]
自动将其转换为零元素列表或单元素列表,具体取决于该值是否为null
。这允许我们动态地声明endpoints
块,只有当override_endpoint
属性是非空的,然后把它的值写入所有三个被覆盖的端点参数。