我正在尝试通过使用 locals 和 local-exec 将虚拟机的公共 IP 地址写入文本文件,请参阅下面的代码。
问题是 locals 变量似乎不起作用:
my_ip=data.azurerm_public_ip.vm-publicip.ip_address
我也尝试在环境中的 local-exec 中传递“data.azurerm_public_ip.vm-publicip.ip_address”,但这也不起作用。
完整代码:
resource "azurerm_public_ip" "public"{
name = "vm_public_ip"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
allocation_method = "Dynamic"
}
data "azurerm_public_ip" "vm-publicip"{
name = azurerm_public_ip.public.name
resource_group_name = azurerm_resource_group.main.name
}
locals {
my_ip=data.azurerm_public_ip.vm-publicip.ip_address
my_vm="[azure_vm]"
}
resource "terraform_data" "ansible" {
provisioner "local-exec" {
environment = {
VM=local.my_vm
IP=data.azurerm_public_ip.vm-publicip.ip_address
}
command = "echo %VM% %IP% > ansible_inventory"
}
}
当我尝试运行它时,%VM% 工作正常,但 %IP% 无法正常工作。
使用 terraform 将值传递给 local-exec 中的环境变量
您似乎正在尝试使用
local-exec
配置程序将虚拟机的公共 IP 地址写入文本文件。但是,您的代码中有几个问题需要解决。
首先,在您的
locals
块中,您直接分配值,而不使用 local-exec
配置器。 local-exec
用于在运行 Terraform 的计算机上本地执行命令,而不是在 Terraform 配置本身内执行命令。
其次,正如 Rui Jarimba 在您的
terraform_data
资源中建议的那样,您尝试直接引用 data.azurerm_public_ip.vm-publicip.ip_address
,但您应该通过您定义的 local
变量来引用它。
我根据要求对代码进行了必要的更改
我的演示配置:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "main" {
name = "testrg-vk"
location = "East US2"
}
resource "azurerm_public_ip" "public" {
name = "vm_public_ip"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
allocation_method = "Dynamic"
}
data "azurerm_public_ip" "vm_publicip" {
name = azurerm_public_ip.public.name
resource_group_name = azurerm_resource_group.main.name
}
locals {
my_ip = data.azurerm_public_ip.vm_publicip.ip_address
my_vm = "[azure_vm]"
}
resource "null_resource" "ansible_inventory" {
provisioner "local-exec" {
interpreter = ["pwsh", "-Command"]
command = "echo '${local.my_vm} ${local.my_ip}' > ansible_inventory"
}
}
部署成功:
现在运行命令
type ansible_inventory
Terraform 文档指出,provisioner 是最后的手段,您应该在使用它们之前寻求其他替代方案。因此,此评论是关于解决此问题的不同方法根本不使用
local-exec
,因为没有必要使用用另一种语言编写的外部程序来创建包含 Terraform 生成的一些数据的文件。
Terraform 提供程序 包含资源类型 local_file
,它以与 azurerm_public_ip
在 Azure API 中管理远程对象类似的方式管理本地磁盘上的文件。您可以使用该资源类型指示 Terraform 根据 Terraform 配置中可用的其他数据创建或更新文件。例如:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
}
local = {
source = "hashicorp/local"
}
}
}
resource "azurerm_public_ip" "public" {
name = "vm_public_ip"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
allocation_method = "Dynamic"
}
data "azurerm_public_ip" "vm-publicip" {
name = azurerm_public_ip.public.name
resource_group_name = azurerm_resource_group.main.name
}
locals {
my_ip = data.azurerm_public_ip.vm-publicip.ip_address
my_vm = "[azure_vm]"
}
resource "local_file" "ansible_inventory" {
file = "${path.module}/ansible_inventory"
content = "${local.my_vm} ${data.azurerm_public_ip.vm-publicip.ip_address}"
}
当创建local_file.ansible_inventory
资源时,它将创建
ansible_inventory
文件并将
content
值写入其中。如果您随后更改
local.my_vm
或
data.azurerm_public_ip.vm-publicip.ip_address
的值,提供商将建议使用新信息重写文件。
local_file
文档有以下警告,但类似的情况也适用于
local-exec
方法,所以我认为这与您的情况无关:
使用本地文件时,每次在不存在该文件的新计算机上应用配置时,Terraform 都会检测到该资源已被删除,并将生成一个差异以重新创建该文件。在许多不同用户经常应用配置的环境中或在自动化系统中,这可能会导致差异中的“噪音”。