使用 for_each 时从 Terraform 创建清单文件
Create Inventory File from Terraform when for_each is used
我有以下结构:
PreProd > Variables.tf 有:
variable "vms" {
default = [
{
"hostname" : "Monitor01",
"size" : "Standard_D2as_v4"
"managed_disk_type" : "Premium_LRS"
"extra_tag" : {
"name" : "monitoring1",
"env" : "dev",
"role" : "test1"
}
},
{
"hostname" : "Monitor02",
"size" : "Standard_D2as_v4"
"managed_disk_type" : "Premium_LRS"
"extra_tag" : {
"name" : "monitoring2",
"env" : "dev",
"role" : "test2"
}
},
模块 > main.tf 有:
# Create public IP's
resource "azurerm_public_ip" "publicip" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-PublicIP"
location = var.vm_location
resource_group_name = var.vm_resource_group
allocation_method = "Static"
}
# Create network interface for Public IP's
resource "azurerm_network_interface" "publicnic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.publicip[each.key].id
}
tags = each.value.extra_tag
}
# Create Linux virtual machines
resource "azurerm_virtual_machine" "vm" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = each.value.hostname
location = var.vm_location
resource_group_name = var.vm_resource_group
network_interface_ids = [azurerm_network_interface.nic[each.key].id]
vm_size = each.value.size
delete_data_disks_on_termination = true
delete_os_disk_on_termination = true
我想为所有 VM 及其 public 和私有 Ip 创建一个清单文件。
模块 > Outputs.tf 有:
output "vm_names" {
description = "Name of VMs"
value = [for k, vm in azurerm_virtual_machine.vm: vm.name]
}
data "template_file" "inventory" {
template = "${file("${path.module}/inventory.tmpl")}"
vars = {
#k8s_master_name = azurerm_network_security_group.toolservernsg.id
k8s_master_name = [for k, p in azurerm_virtual_machine.vm: p.name]
}
}
resource "local_file" "save_inventory" {
content = "${data.template_file.inventory.rendered}"
filename = "./myhosts.cfg"
}
模块 > inventory.tmpl 文件有:
[servers]
${k8s_master_name}
我正在努力获取使用以下结构创建的 myhosts.cfg 文件:
[servers]
Monitor01 privateip="x.x.x.x" publicip="x.x.x.x."
Monitor02 privateip="x.x.x.x" publicip="x.x.x.x."
[nsg]
我在应用 terraform 时收到以下错误:
当我进行 terraform 输出时,我得到以下信息:
我浏览了很多论坛并尝试了所有这些输出变体,但我无法得到想要的结果:
output "vm_name" {
description = "Name of VMs"
value = values(azurerm_virtual_machine.vm)[*].name
}
output "vm_name2" {
description = "Name of VMs as a map"
value = {for k, vm in azurerm_virtual_machine.vm : k => vm.name}
}
output "vm_name3" {
description = "Name of VMs as a map"
value = azurerm_virtual_machine.vm[*].name
}
output "vm_names" {
description = "Name of VMs as a map"
value = [for p in azurerm_virtual_machine.vm:p.name]
}
template_file
只能 接受字符串 ,但您正在向它传递一个值列表。所以它失败了。
你可以试试 jsonencode
:
data "template_file" "inventory" {
template = "${file("${path.module}/inventory.tmpl")}"
vars = {
k8s_master_name = jsonencode([for k, p in azurerm_virtual_machine.vm: p.name])
}
}
或者,您可以查看可以接受值列表的 templatefile,而不是 template_file
。
谢谢 Marcin,我最终使用了 templatefile。对于其他寻找答案的人,这就是我所做的。
Outputs.tf 文件:
### The Ansible inventory file
resource "local_file" "AnsibleInventory" {
content = templatefile("${path.module}/inventory.tmpl",
{
vm-names = [for k, p in azurerm_virtual_machine.vm: p.name],
private-ip = [for k, p in azurerm_network_interface.nic: p.private_ip_address],
publicvm-names = [for k, p in azurerm_virtual_machine.publicvm: p.name],
publicvm-private-ip = [for k, p in azurerm_network_interface.publicnic: p.private_ip_address],
public-ip = [for k, p in azurerm_public_ip.publicip: p.ip_address],
public-dns = [for k, p in azurerm_public_ip.publicip: p.fqdn],
}
)
filename = "hosts.cfg"
}
Inventory.tmpl 文件:
[servers]
%{ for index, vms in vm-names ~}
${vms} ansible_host=${private-ip[index]}
%{ endfor ~}
%{ for index, vms in publicvm-names ~}
${vms} ansible_host=${publicvm-private-ip[index]} public_ip=${public-ip[index]}
%{ endfor ~}
这最终给了我一个 hosts.cfg 文件:
[servers]
Monitor01 ansible_host=x.x.x.x
Monitor02 ansible_host=x.x.x.x
MonitorPublic01 ansible_host=x.x.x.x public_ip=x.x.x.x
MonitorPublic02 ansible_host=x.x.x.x public_ip=x.x.x.x
我有以下结构:
PreProd > Variables.tf 有:
variable "vms" {
default = [
{
"hostname" : "Monitor01",
"size" : "Standard_D2as_v4"
"managed_disk_type" : "Premium_LRS"
"extra_tag" : {
"name" : "monitoring1",
"env" : "dev",
"role" : "test1"
}
},
{
"hostname" : "Monitor02",
"size" : "Standard_D2as_v4"
"managed_disk_type" : "Premium_LRS"
"extra_tag" : {
"name" : "monitoring2",
"env" : "dev",
"role" : "test2"
}
},
模块 > main.tf 有:
# Create public IP's
resource "azurerm_public_ip" "publicip" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-PublicIP"
location = var.vm_location
resource_group_name = var.vm_resource_group
allocation_method = "Static"
}
# Create network interface for Public IP's
resource "azurerm_network_interface" "publicnic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.publicip[each.key].id
}
tags = each.value.extra_tag
}
# Create Linux virtual machines
resource "azurerm_virtual_machine" "vm" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = each.value.hostname
location = var.vm_location
resource_group_name = var.vm_resource_group
network_interface_ids = [azurerm_network_interface.nic[each.key].id]
vm_size = each.value.size
delete_data_disks_on_termination = true
delete_os_disk_on_termination = true
我想为所有 VM 及其 public 和私有 Ip 创建一个清单文件。
模块 > Outputs.tf 有:
output "vm_names" {
description = "Name of VMs"
value = [for k, vm in azurerm_virtual_machine.vm: vm.name]
}
data "template_file" "inventory" {
template = "${file("${path.module}/inventory.tmpl")}"
vars = {
#k8s_master_name = azurerm_network_security_group.toolservernsg.id
k8s_master_name = [for k, p in azurerm_virtual_machine.vm: p.name]
}
}
resource "local_file" "save_inventory" {
content = "${data.template_file.inventory.rendered}"
filename = "./myhosts.cfg"
}
模块 > inventory.tmpl 文件有:
[servers]
${k8s_master_name}
我正在努力获取使用以下结构创建的 myhosts.cfg 文件:
[servers]
Monitor01 privateip="x.x.x.x" publicip="x.x.x.x."
Monitor02 privateip="x.x.x.x" publicip="x.x.x.x."
[nsg]
我在应用 terraform 时收到以下错误:
当我进行 terraform 输出时,我得到以下信息:
我浏览了很多论坛并尝试了所有这些输出变体,但我无法得到想要的结果:
output "vm_name" {
description = "Name of VMs"
value = values(azurerm_virtual_machine.vm)[*].name
}
output "vm_name2" {
description = "Name of VMs as a map"
value = {for k, vm in azurerm_virtual_machine.vm : k => vm.name}
}
output "vm_name3" {
description = "Name of VMs as a map"
value = azurerm_virtual_machine.vm[*].name
}
output "vm_names" {
description = "Name of VMs as a map"
value = [for p in azurerm_virtual_machine.vm:p.name]
}
template_file
只能 接受字符串 ,但您正在向它传递一个值列表。所以它失败了。
你可以试试 jsonencode
:
data "template_file" "inventory" {
template = "${file("${path.module}/inventory.tmpl")}"
vars = {
k8s_master_name = jsonencode([for k, p in azurerm_virtual_machine.vm: p.name])
}
}
或者,您可以查看可以接受值列表的 templatefile,而不是 template_file
。
谢谢 Marcin,我最终使用了 templatefile。对于其他寻找答案的人,这就是我所做的。
Outputs.tf 文件:
### The Ansible inventory file
resource "local_file" "AnsibleInventory" {
content = templatefile("${path.module}/inventory.tmpl",
{
vm-names = [for k, p in azurerm_virtual_machine.vm: p.name],
private-ip = [for k, p in azurerm_network_interface.nic: p.private_ip_address],
publicvm-names = [for k, p in azurerm_virtual_machine.publicvm: p.name],
publicvm-private-ip = [for k, p in azurerm_network_interface.publicnic: p.private_ip_address],
public-ip = [for k, p in azurerm_public_ip.publicip: p.ip_address],
public-dns = [for k, p in azurerm_public_ip.publicip: p.fqdn],
}
)
filename = "hosts.cfg"
}
Inventory.tmpl 文件:
[servers]
%{ for index, vms in vm-names ~}
${vms} ansible_host=${private-ip[index]}
%{ endfor ~}
%{ for index, vms in publicvm-names ~}
${vms} ansible_host=${publicvm-private-ip[index]} public_ip=${public-ip[index]}
%{ endfor ~}
这最终给了我一个 hosts.cfg 文件:
[servers]
Monitor01 ansible_host=x.x.x.x
Monitor02 ansible_host=x.x.x.x
MonitorPublic01 ansible_host=x.x.x.x public_ip=x.x.x.x
MonitorPublic02 ansible_host=x.x.x.x public_ip=x.x.x.x