azure 使用for_each时从Terraform创建库存文件

jw5wzhpr  于 2023-05-01  发布在  其他
关注(0)|答案(3)|浏览(135)

我有以下结构:

PreProd〉 www.example.com具有:

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"
      }
    },

TheModules〉 www.example.com具有:

# 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

我想为所有的虚拟机及其公共和私有IP创建一个清单文件。
TheModules〉 www.example.com具有:

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"
 }

Modules〉inventory。tmpl文件具有:

[servers]
${k8s_master_name}

我正在努力得到一个我的主机。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]
}
eeq64g8w

eeq64g8w1#

谢谢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"
}

库存。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 ~}

最后,他们给了我一个**。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
2uluyalo

2uluyalo2#

这个简单的示例使用local_file,因此它显示了概念,而无需访问Azure或任何其他外部资源。整个module.web对象被传递给local_file.ansible_inventory,而不是传递一个Map或一组字符串,这使得选择所需的输出变得不那么麻烦。

main.tf:

module "web" {
  source     = "./stack"
  for_each   = toset(["192.168.54.42", "192.168.1.137"])
  input_name = "web-${replace(each.value, ".", "-")}"
  input_ip   = each.value
}

resource "local_file" "ansible_inventory" {
  content = templatefile("ansible/inventory.tmpl",
    {
      webs = module.web,
    }
  )
  filename = "ansible/inventory"
}

stack/ www.example.com

resource "local_file" "for_each_loop" {
  content  = var.input_ip
  filename = var.input_name
}

variable "input_name" {
  description = "Name of the stack"
  type        = string
}

variable "input_ip" {
  description = "IP address of the stack"
  type        = string
}

output "output_name" {
  description = "Name of instance"
  value       = local_file.for_each_loop.filename
}

output "output_ip" {
  description = "IP address of instance"
  value       = local_file.for_each_loop.content
}

ansible/inventory。tmpl:

[all:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new'
ansible_user=root

[webs]
%{ for index, obj in webs ~}
${obj.output_name} ansible_host=${obj.output_ip}
%{ endfor ~}

其结果如下

ansible/inventory:

[all:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=accept-new'
ansible_user=root

[webs]
web-192-168-1-137 ansible_host=192.168.1.137
web-192-168-54-42 ansible_host=192.168.54.42
jdzmm42g

jdzmm42g3#

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

相关问题