It is correst syntax?

Hello,
I need declare resource, but I don’t know if it correct

resource "xxx" "yyy" {
  storage {
    disks = [
      {
        scsi     =  "",
        selected = 1,
      },
    ]

    nics = [
      {
        mac  = "",
        type = 1,
      },
      {
        mac  = "",
        type = 0,
      },
    ]

    custom_pcis = [
      {
        pci      = "",
        selected = 1,
      },
    ]
  }
}

I have schema for this

rs.Schema["storage"] = &schema.Schema{
		Type:         schema.TypeSet,
		Optional:     true,
		MaxItems:     1,

		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"disks": {
					Type:     schema.TypeList,
					Optional: true,
					Elem: &schema.Resource{
						Schema: map[string]*schema.Schema{
							"scsi": {
								Type:     schema.TypeString,
								Optional: true,
							},
							"selected": {
								Type:     schema.TypeBool,
								Optional: true,
							},
						},
					},
				},

				"nics": {
					Type:     schema.TypeList,
					Optional: true,
					Elem: &schema.Resource{
						Schema: map[string]*schema.Schema{
							"mac": {
								Type:     schema.TypeString,
								Optional: true,
							},
							"type": {
								Type:     schema.TypeInt,
								Optional: true,
							},
						},
					},
				},

				"custom_pcis": {
					Type:     schema.TypeList,
					Optional: true,
					Elem: &schema.Resource{
						Schema: map[string]*schema.Schema{
							"pci": {
								Type:     schema.TypeString,
								Optional: true,
							},
							"selected": {
								Type:     schema.TypeBool,
								Optional: true,
							},
						},
					},
				},
			},
		},
	}

But I get error
Error: Unsupported argument

  on resource_test.tf line 23, in resource "xxx" "yyy":
  23:     disks = [

An argument named "disks" is not expected here. Did you mean to define a block
of type "disks"?

Where I’m wrong?

Hi @skydion,

A schema entry whose Elem is a schema.Resource appears in Terraform configuration as zero or more nested blocks. Therefore we usually use singular names (disk, nic) for these, rather than plural names (disks, nics), and then users will write them with the following syntax:

resource "example" "example" {
  disk {
    scsi     = ""
    selected = true
  }

  nic {
    mac  = ""
    type = 1
  }
  nic {
    mac  = ""
    type = 0
  }
}

This syntax is intended for situations where the blocks represent distinct objects that belong to the containing resource but don’t interact with each other. The syntax of separate blocks is intended to help users think of these as being a set of separate objects, rather than as being collected together into a single list.

When the error message says “Did you mean to define a block … ?” it is hinting to use the block syntax like above, rather than the argument syntax (with an equals sign = to assign a value to an argument.)

Hi, @apparentlymart

Thank you for your answer.
Okay I can describe this as separate blocks, but I need describe this in storage{} object, what I must change in my schema? At this moment I change this to the next schema, but still not work.

	rs.Schema["storage"] = &schema.Schema{
		Type:         schema.TypeSet,
		Optional:     true,
		MaxItems:     1,
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"disk": {
					Type:     schema.TypeMap,
					Optional: true,
					Elem: &schema.Resource{
						Schema: map[string]*schema.Schema{
							"scsi": {
								Type:     schema.TypeString,
								Optional: true,
							},
							"selected": {
								Type:     schema.TypeBool,
								Optional: true,
							},
						},
					},
				},



Error: Unsupported block type

  on resource_test.tf line 23, in resource "yyy" "xxx":
  23:     disk {

Blocks of type "disk" are not expected here. Did you mean to define argument
"disk"? If so, use the equals sign to assign it a value.

Previously I declare block network_interfaces in resource:

"network_interfaces": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"identifiers": {
							Type:     schema.TypeList,
							Optional: true,
							MinItems: 1,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
						},
						"attributes": {
							Type:     schema.TypeSet,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"status": {
										Type:     schema.TypeString,
										Optional: true,
									},
								},
							},
						},
					},
				},

And use it like:

  network_interfaces {
    identifiers = [""]
    attributes {
      status = "assigned_to_san"
    }
  }

But the same schema not work for storage{} object, and I don’t understand why…

It looks like you set your schema for the nested disk to have Type: schema.TypeMap, which is always a map of strings – the Elem field is ignored for schema.TypeMap. To declare a nested block type you must set Type to either schema.TypeList or schema.TypeSet (depending on whether the ordering of the blocks is significant), and then set Elem to *schema.Resource value as you’ve already done here.

Thank you @apparentlymart

I see, in my second example is TypeSet… my bad :slight_smile:
Some time don’t see simple mistake.