When I try to add a PTR record in DNS, I get this error with Invalid index. I am uncertain how to remove the error.
resource "openstack_compute_instance_v2" "app-stage" {
count = length(var.datacenter)
name = "app-stage-${var.datacenter[count.index]}.example.com"
flavor_name = var.flavor["app-stage"]
availability_zone = element(var.datacenter, count.index)
key_pair = var.key_pair
image_id = var.os_image
config_drive = true
user_data = data.template_file.app-stage[count.index].rendered
scheduler_hints {
group = openstack_compute_servergroup_v2.app_sg.id
}
network {
port = openstack_networking_port_v2.app-stage[count.index].id
}
}
resource "dns_aaaa_record_set" "app-stage-dns" {
count = length(var.datacenter)
zone = format("%s.", var.dns_zone)
name = "app-stage-${var.datacenter[count.index]}.example"
addresses = [replace(openstack_compute_instance_v2.app-stage[count.index].access_ip_v6, "/\\[|\\]/", "")]
ttl = 300
}
resource "dns_ptr_record" "app-stage-dns-ptr" {
count = length(var.datacenter)
zone = format("%s.", var.dns_ptr_zone)
ptr = "app-stage-${var.datacenter[count.index]}.example"
name = tolist(dns_aaaa_record_set.app-stage-dns)[count.index].addresses[0]
ttl = 300
This is the error-messages i get when running terraform apply,:
Error: Invalid index
on app-stage.tf line 94, in resource "dns_ptr_record" "app-stage-dns-ptr":
94: name = tolist(dns_aaaa_record_set.app-stage-dns)[count.index].addresses[0]
|----------------
| count.index is 1
| dns_aaaa_record_set.app-stage-dns is tuple with 2 elements
This value does not have any indices.
This is repeated 2 times, since I try to create 2 machines/2records.
Based on the comments.
It should be:
name = tolist(dns_aaaa_record_set.app-stage-dns[count.index].addresses)[0]
not (closing parenthesis in different place)
name = tolist(dns_aaaa_record_set.app-stage-dns)[count.index].addresses[0]
Related
I am having child module for Windows virtual machine.
Then I have root module (main.tf file), where I am using that child module
module "vm-win-resource" {
source = "./Modules/ServerWindows"
count = 2
vm-name = "vm-win-${random_string.rnd.result}" #OR "vm-win-${module.rnd-num.rnd-result}"
vm-rg = module.rg-resouce.rg-name
vm-location = module.rg-resouce.rg-location
nic-name = "vm-win-${random_string.rnd.result}-nic1" #OR "vm-win-${module.rnd-num.rnd-result}-nic1"
nic-rg = module.rg-resouce.rg-name
nic-location = module.rg-resouce.rg-location
nic-ip-subnet = "HERE IS SUBNET ID"
}
In same main.tf file, if I use random_string provider directly
resource "random_string" "rnd" {
length = 4
min_numeric = 4
special = false
lower = true
}
or if I create module, for random number and use it in module for virtual machine, result is same.
module "rnd-num" {
source = "./Modules/RandomNumber"
}
I get same name (generated number for both)
+ vm-win-name = [
+ [
+ "vm-win-6286",
+ "vm-win-6286",
],
]
So in both cases, value is generated only once.
Question is how can I generate random number for every loop in module for virtual machine?
Thank you for any help!
UPDATE
As workaround, I have placed provider to generate random number into virtual machine resource/module specification
resource "azurerm_windows_virtual_machine" "vm-resource" {
name = "${var.vm-name}-${random_string.rnd.result}"
resource_group_name = var.vm-rg
location = var.vm-location
size = var.vm-size
admin_username = var.vm-admin
admin_password = var.vm-adminpwd
network_interface_ids = [
azurerm_network_interface.nic-resource.id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = var.vm-os-disk-type
}
source_image_reference {
publisher = var.vm-os-image.publisher
offer = var.vm-os-image.offer
sku = var.vm-os-image.sku
version = var.vm-os-image.version
}
tags = var.resource-tags
}
resource "random_string" "rnd" {
length = 4
min_numeric = 4
special = false
lower = true
}
it does the job but I would prefer to use it in main.tf file and not directly in resource/module specification, if it is possible.
A few words about how Terraform random_string works:
random_string generates a random string from specific characters. This string is generated once. Referencing its result attribute in multiple places will provide you the same output. Using it as random_string.rnd.result will not act as a function call, this means that it will provide the same value in every place.
The result value of a random_string will not change after consecutive applies. This is obvious, if we think about it. If it would change, the usage of random_string would be dangerous, since it would result in re-provisioning the resources which are referencing it.
If we want to have multiple different random strings, we have to define multiple random_string resources. For example:
resource "random_string" "rnd" {
count = 2
length = 4
min_numeric = 4
special = false
lower = true
}
module "vm-win-resource" {
source = "./Modules/ServerWindows"
count = 2
vm-name = "vm-win-${random_string.rnd[count.index].result}"
vm-rg = module.rg-resouce.rg-name
vm-location = module.rg-resouce.rg-location
nic-name = "vm-win-${random_string.rnd[count.index].result}-nic1"
nic-rg = module.rg-resouce.rg-name
nic-location = module.rg-resouce.rg-location
nic-ip-subnet = "HERE IS SUBNET ID"
}
Please note, we are using a count for the random_string resource as well.
Error: Unbalanced parentheses
on .terraform\modules\nics\main.tf line 19, in resource "azurerm_network_interface" "NIC1":
19: subnet_id = "${element(var.subnetwork-subnetid.*.id, (0,1))}"
output values of subnets:
output "subnetwork-subnetid" {
value = concat(azurerm_subnet.subnetwork.*.id, azurerm_subnet.subnetwork6.*.id)
}
nic.tf
resource "azurerm_network_interface" "NIC1" {
#count = "${length(var.subnetwork-subnetid)}"
#for_each= toset(var.subipv4)
count = "${length(var.subipv4)}"
name = "${lookup(element(var.subipv4, count.index), "name")}"
#name = var.nic-name
location = var.rg-location
resource_group_name = var.rg-name
enable_ip_forwarding = true
enable_accelerated_networking = true
ip_configuration {
name = "ipconfig"
subnet_id = "${element(var.subnetwork-subnetid.*.id, (0,1))}"
private_ip_address_allocation = "Dynamic"
#public_ip_address_id = azurerm_public_ip.pubip.id
#public_ip_address_id = azurerm_public_ip.pubip.*.id
primary = true
}
tags = {
name = "${lookup(element(var.subipv4, count.index), "name")}"
}
}```
Please someone help me in this issue.Thanks!
Second argument in element is index:
index finds the index for a particular element value.
Thus to get few elements from the list based on indices, you can do:
subnet_id = [ for idx in [0, 1]: element(var.subnetwork-subnetid.*.id, idx) ]
If you want a range of indies, you can use slice:
subnet_id = slice(var.subnetwork-subnetid.*.id, 0, 2)
I am trying examples from this module
https://registry.terraform.io/modules/terraform-aws-modules/security-group/aws/3.10.0
The main.tf:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "${var.environment}-project-vpc"
cidr = "10.0.0.0/16"
#
# Important!
# https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/403
# Only append or delete from the end of the list
#
azs = ["us-east-2a", "us-east-2b", "us-east-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
one_nat_gateway_per_az = false
enable_dns_hostnames = true
enable_dns_support = true
tags = module.project_config.tags
}
module "bastion_sg" {
source = "terraform-aws-modules/security-group/aws"
name = "bastion-service"
description = "Security group for bastion-service"
vpc_id = module.vpc.default_vpc_id
ingress_rules = ["https-443-tcp", "http-80-tcp", "ssh", "all-icmp"]
egress_rules = ["all-all"]
}
resource "aws_instance" "bastion" {
# name = "bastion"
# description = "bastion ssh host to access internals of the infrastructure by SSH"
ami = "ami-08ee2516c7709ea48"
instance_type = "t2.micro"
security_groups = [
module.bastion_sg.this_security_group_id
]
subnet_id = module.vpc.public_subnets[0]
}
and terraform apply fails with
Error: Invalid index
on .terraform/modules/bastion_sg/terraform-aws-security-group-3.10.0/main.tf line 65, in resource "aws_security_group_rule" "ingress_rules":
65: description = var.rules[var.ingress_rules[count.index]][3]
|----------------
| count.index is 2
| var.ingress_rules is list of string with 4 elements
| var.rules is map of list of string with 115 elements
The given key does not identify an element in this collection value.
Error: Invalid index
on .terraform/modules/bastion_sg/terraform-aws-security-group-3.10.0/main.tf line 67, in resource "aws_security_group_rule" "ingress_rules":
67: from_port = var.rules[var.ingress_rules[count.index]][0]
|----------------
| count.index is 2
| var.ingress_rules is list of string with 4 elements
| var.rules is map of list of string with 115 elements
The given key does not identify an element in this collection value.
Error: Invalid index
on .terraform/modules/bastion_sg/terraform-aws-security-group-3.10.0/main.tf line 68, in resource "aws_security_group_rule" "ingress_rules":
68: to_port = var.rules[var.ingress_rules[count.index]][1]
|----------------
| count.index is 2
| var.ingress_rules is list of string with 4 elements
| var.rules is map of list of string with 115 elements
The given key does not identify an element in this collection value.
Error: Invalid index
on .terraform/modules/bastion_sg/terraform-aws-security-group-3.10.0/main.tf line 69, in resource "aws_security_group_rule" "ingress_rules":
69: protocol = var.rules[var.ingress_rules[count.index]][2]
|----------------
| count.index is 2
| var.ingress_rules is list of string with 4 elements
| var.rules is map of list of string with 115 elements
The given key does not identify an element in this collection value.
What am I doing wrong?
Ok, figured this out
module "bastion_sg" {
source = "terraform-aws-modules/security-group/aws"
name = "bastion-service"
description = "Security group for bastion-service"
vpc_id = module.vpc.vpc_id
ingress_cidr_blocks = ["0.0.0.0/0", module.vpc.vpc_cidr_block]
ingress_rules = ["https-443-tcp", "http-80-tcp", "ssh-tcp", "all-icmp"]
egress_rules = ["all-all"]
}
Correct name of the rule is "ssh-tcp", not "ssh"
### variable
variable "vm-subnets" {
type = list(string)
default = ["7.0.1.0/24","7.0.2.0/24","7.0.3.0/24"]
}
### subnet
resource "azurerm_subnet" "task_subnet" {
name = "subnet-${format("%02d",count.index)}"
resource_group_name = azurerm_resource_group.task.name
virtual_network_name = azurerm_virtual_network.task_vnet.name
network_security_group_id = azurerm_network_security_group.task_nsg.id
address_prefix = var.vm-subnets[count.index]
count = length(var.vm-subnets)
}
### NIC
resource "azurerm_network_interface" "vm_nic" {
name = "nic--${format("%02d",count.index)}"
location = var.region
resource_group_name = azurerm_resource_group.task.name
count = var.vm-count
ip_configuration {
name = "${var.resource_prefix}-${format("%02d",count.index)}-ip"
subnet_id = azurerm_subnet.task_subnet.*.id[count.index]
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.task_public_ip.*.id[count.index]
}<br>
}
I need to 7 VM into 3 subnet for like subnet-A = 2VMs ,subnet-B=2VMs, subnet-C = 3VMs or randomly
``
ERROR:
Error: Invalid index
on vm-network.tf line 11, in resource "azurerm_network_interface" "vm_nic":
11: subnet_id = azurerm_subnet.task_subnet.*.id[count.index]
|----------------
| azurerm_subnet.task_subnet is tuple with 3 elements
| count.index is 4
The given key does not identify an element in this collection value.
Error: Invalid index
on vm-network.tf line 11, in resource "azurerm_network_interface" "vm_nic":
11: subnet_id = azurerm_subnet.task_subnet.*.id[count.index]
|----------------
| azurerm_subnet.task_subnet is tuple with 3 elements
| count.index is 3
The given key does not identify an element in this collection value.
What modification can be done to resolve it and how can I assign different/random subnet on each vm rather then count loop.
I also try to do it using random_shuffle and set-product function but not get the desired output .. please Help
After 2 days of logical struggle i finally able to find a solution or the questions that I create : USING element function https://www.terraform.io/docs/configuration/functions/element.html
NIC
resource "azurerm_network_interface" "vm_nic" {
name = "nic--${format("%02d",count.index)}"
location = var.region
resource_group_name = azurerm_resource_group.task.name
count = var.vm-count
ip_configuration {
name = "${var.resource_prefix}-${format("%02d",count.index)}-ip"
subnet_id = element(azurerm_subnet.task_subnet.*.id, count.index)
private_ip_address_allocation = "dynamic"
public_ip_address_id = azurerm_public_ip.task_public_ip.*.id[count.index]
}
}
subnet_id = element(azurerm_subnet.task_subnet.*.id, count.index)
using element function ["7.0.1.0/24","7.0.2.0/24","7.0.3.0/24"] at vm count.index = 3 it goes back to subnet index = 0 so that how it works and tested it at vm.count = 5, 7 , 10. ✌🏻
I am trying to make a Terraform playbook that creates Azure routes through a loop.
The end-goal is the user will type in their destinations in a comma separated list. For example:
Enter route destinations: 0.0.0.0/0,192.168.0.0/16
From this variable, the azurerm_route will run through this function and create the routes.
variable "destinations" {
default = "0.0.0.0/0,192.168.0.0/16"
}
resource "azurerm_route" "route" {
name = "route-${count.index}"
resource_group_name = "resourcegroup"
route_table_name = "table"
address_prefix = "${split(",", var.destinations)}[count.index]"
next_hop_type = "Internet"
count = "${length(split(",", var.destinations))}"
}
However, I am having an issue with counting through the prefix list and I am receiving the following error:
* azurerm_route.route[1]: At column 1, line 1: output of an HIL
expression must be a string, or a single list (argument 1 is
TypeList) in:
${split(",", var.destinations)}[count.index]
* azurerm_route.route[0]: At column 1, line 1: output of an HIL
expression must be a string, or a single list (argument 1 is
TypeList) in:
${split(",", var.destinations)}[count.index]
Figured it out. You have to use the element interpolation.
resource "azurerm_route" "route" {
name = "route-${count.index}"
resource_group_name = "resourcegroup"
route_table_name = "table"
address_prefix = "${element(split(",",var.destinations),count.index)}"
next_hop_type = "Internet"
count = "${length(split(",",var.destinations))}"
}