TonyD
November 10, 2021, 3:55pm
1
I have resource:
resource "oci_core_volume" "block" {
for_each = var.instance_params
availability_domain = oci_core_instance.this[each.value.instance_name].availability_domain
compartment_id = var.compartment_id
dynamic "params_disco" {
for_each = each.value.block_volume_params
iterator = bvp
content {
display_name = "${var.prefijo_cliente}-${bvp.value.hostname}-${bvp.value.display_name}"
size_in_gbs = bvp.value.bv_size
}
}
}
I’m getting this error:
│ **Error:** **Unsupported block type**
│ on ../../modules/core-instance/main.tf line 117, in resource "oci_core_volume" "block":
│ 117: dynamic "params_disco" {
│ Blocks of type "params_disco" are not expected here.
I have tried in several ways and I don’t know why. Can you help me?
Thanks in advance.
Hi @TonyD !
Can you share an example of you var.instance_params
and a single instance of the oci_core_volume
you are trying to create?
Dynamic blocks are explained here in the docs , and based on a quick lookup I think you should rename params_disco
to a valid block within a oci_core_volume
, like block_volume_replicas
or use a for_each loop only to create your resources.
TonyD
November 10, 2021, 4:28pm
3
Sure!
variable "instance_params" {
description = "parameters"
type = map(object({
hostname = string
ad = number
shape = string
instance_ocpus = number
instance_ram = number
os = string
boot_volume_size = number
preserve_boot_volume = bool
assign_public_ip = bool
private_ip = string
subnet_name = string
nsg_name = string
vnic_params = list(object({
vnic_name = string
display_name = string
private_ip = string
skip_source_dest_check = bool
subnet_name = string
nsg_name = string
}))
block_volume_params = list(object({
ad = number
display_name = string
bv_size = number
device_name = string
volume_type = string
}))
}))
}
instance_params = {
GATEWAY = {
hostname = "SRV-GATEWAY"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 1
instance_ram = 2
os = "canonical_ubuntu_20_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = true
private_ip = "172.16.23.20"
subnet_name = "DMZ"
nsg_name = "gateway_srv_nsg"
vnic_params = [
{
vnic_name = "NIC"
display_name = "NIC"
private_ip = "172.16.123.2"
skip_source_dest_check = true
subnet_name = "LAN"
nsg_name = "gateway_srv_nsg"
}]
block_volume_params = []
},
BDPRODUCCION = {
hostname = "SRVORACLE19C-1"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 2
instance_ram = 16
os = "oracle_linux_8_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = false
private_ip = "172.16.123.11"
subnet_name = "LAN"
nsg_name = "srvoracle19c_1_nsg"
vnic_params = []
block_volume_params = [
{
ad = 1
display_name = "u01"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "u02"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "DATOS-1"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "FRA-1"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
}
]
}
}
Sorry, but could you please ease reading your config by using ```hcl
before and ```
after your code block and use indentation?
I cannot format it myself, as it seems invalid terraform configuration
variable "instance_params" {
description = "parameters"
type = map(object({
hostname = string
ad = number
shape = string
instance_ocpus = number
instance_ram = number
os = string
boot_volume_size = number
preserve_boot_volume = bool
assign_public_ip = bool
private_ip = string
subnet_name = string
nsg_name = string
vnic_params = list(object({
vnic_name = string
display_name = string
private_ip = string
skip_source_dest_check = bool
subnet_name = string
nsg_name = string
}))
block_volume_params = list(object({
ad = number
display_name = string
bv_size = number
device_name = string
volume_type = string
}))
}))
}
TonyD
November 10, 2021, 4:43pm
5
Sorry…
instance_params = {
GATEWAY = {
hostname = "SRV-GATEWAY"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 1
instance_ram = 2
os = "canonical_ubuntu_20_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = true
private_ip = "172.16.23.20"
subnet_name = "DMZ"
nsg_name = "gateway_srv_nsg"
vnic_params = [
{
vnic_name = "NIC"
display_name = "NIC"
private_ip = "172.16.123.2"
skip_source_dest_check = true
subnet_name = "LAN"
nsg_name = "gateway_srv_nsg"
}]
block_volume_params = []
},
BDPRODUCCION = {
hostname = "SRVORACLE19C-1"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 2
instance_ram = 16
os = "oracle_linux_8_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = false
private_ip = "172.16.123.11"
subnet_name = "LAN"
nsg_name = "srvoracle19c_1_nsg"
vnic_params = []
block_volume_params = [
{
ad = 1
display_name = "u01"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "u02"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "DATOS-1"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "FRA-1"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
}
]
}
variable "instance_params" {
description = "parameters"
type = map(object({
hostname = string
ad = number
shape = string
instance_ocpus = number
instance_ram = number
os = string
boot_volume_size = number
preserve_boot_volume = bool
assign_public_ip = bool
private_ip = string
subnet_name = string
nsg_name = string
vnic_params = list(object({
vnic_name = string
display_name = string
private_ip = string
skip_source_dest_check = bool
subnet_name = string
nsg_name = string
}))
block_volume_params = list(object({
ad = number
display_name = string
bv_size = number
device_name = string
volume_type = string
}))
}))
}
So you’ve multiple vm instances, with each potentially multiple NICs and block volumes.
Is it an option to make it into a module or would you prefer to keep it as is? If the latter is the case, you can take a look at list_of_maps.tf · GitHub , which does the same but in a different context.
You can loop over the output with your for_each
.
TonyD
November 10, 2021, 4:58pm
7
Do you mind to explain “to make it into a module”?
Sure! By making an instance
module, you can loop for_each
per instance over the instances module, and loop over the blocks in the module itself.
Flatten all the blocks to keep it similar to your current setup would look like this:
variable "instance_params" {
description = "parameters"
type = map(object({
hostname = string
ad = number
shape = string
instance_ocpus = number
instance_ram = number
os = string
boot_volume_size = number
preserve_boot_volume = bool
assign_public_ip = bool
private_ip = string
subnet_name = string
nsg_name = string
vnic_params = list(object({
vnic_name = string
display_name = string
private_ip = string
skip_source_dest_check = bool
subnet_name = string
nsg_name = string
}))
block_volume_params = list(object({
ad = number
display_name = string
bv_size = number
device_name = string
volume_type = string
}))
}))
default = {
GATEWAY = {
hostname = "SRV-GATEWAY"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 1
instance_ram = 2
os = "canonical_ubuntu_20_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = true
private_ip = "172.16.23.20"
subnet_name = "DMZ"
nsg_name = "gateway_srv_nsg"
vnic_params = [
{
vnic_name = "NIC"
display_name = "NIC"
private_ip = "172.16.123.2"
skip_source_dest_check = true
subnet_name = "LAN"
nsg_name = "gateway_srv_nsg"
}]
block_volume_params = []
},
BDPRODUCCION = {
hostname = "SRVORACLE19C-1"
ad = 1
shape = "VM.Standard.E4.Flex"
instance_ocpus = 2
instance_ram = 16
os = "oracle_linux_8_4"
boot_volume_size = 50 # gbs
preserve_boot_volume = false
assign_public_ip = false
private_ip = "172.16.123.11"
subnet_name = "LAN"
nsg_name = "srvoracle19c_1_nsg"
vnic_params = []
block_volume_params = [
{
ad = 1
display_name = "u01"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "u02"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "DATOS-1"
bv_size = 200 # gbs
device_name = ""
volume_type = ""
},
{
ad = 1
display_name = "FRA-1"
bv_size = 50 # gbs
device_name = ""
volume_type = ""
}
]
}
}
}
locals {
block_volumes = flatten([for instance, dict in var.instance_params : [
for block_volume, value in toset(dict.block_volume_params) : merge({ "instance" = instance, "hostname" = dict.hostname }, value)
]])
}
output "block_volumes" {
value = local.block_volumes
}
terraform apply
:
Changes to Outputs:
+ block_volumes = [
+ {
+ ad = 1
+ bv_size = 200
+ device_name = ""
+ display_name = "DATOS-1"
+ hostname = "SRVORACLE19C-1"
+ instance = "BDPRODUCCION"
+ volume_type = ""
},
+ {
+ ad = 1
+ bv_size = 200
+ device_name = ""
+ display_name = "u02"
+ hostname = "SRVORACLE19C-1"
+ instance = "BDPRODUCCION"
+ volume_type = ""
},
+ {
+ ad = 1
+ bv_size = 50
+ device_name = ""
+ display_name = "FRA-1"
+ hostname = "SRVORACLE19C-1"
+ instance = "BDPRODUCCION"
+ volume_type = ""
},
+ {
+ ad = 1
+ bv_size = 50
+ device_name = ""
+ display_name = "u01"
+ hostname = "SRVORACLE19C-1"
+ instance = "BDPRODUCCION"
+ volume_type = ""
},
]
You can now loop over the blocks with a for_each
TonyD
November 10, 2021, 8:25pm
9
THANK You! I wasn’t able to do it with a for_each but I was able to do it with a count.
I have to improve my knowledge of TF
1 Like