I am unable to attach network interface to ec2 instances

Hi ALL,
I am planning to create network interface and attach to ec2 instace primary IP, but i am getting below error,Please help me.

on main.tf line 25, in resource “aws_instance” “ec2_instance”:
25: network_interface = [for nic_idx in range(aws_network_interface.test):

An argument named “network_interface” is not expected here. Did you mean to
define a block of type “network_interface”?


provider "aws" {
  shared_credentials_file = "/c/Users/test/.aws/credentials"
  profile                 = "sandbox"
  region                  = "us-east-1"

}
resource "aws_network_interface" "test" {
  subnet_id       = "subnet-*"
  security_groups =  ["sg*"]
  count           = "${var.number_of_instances}"
}



// EC2 Instance Resource for Module
    resource "aws_instance" "ec2_instance" {
    ami = "${var.ami_id}"
    count = "${var.number_of_instances}"
    instance_type = "${var.instance_type}"
    subnet_id = "${var.subnet_id}"
    vpc_security_group_ids = ["${aws_security_group.apigee-instance.id}"]
    key_name = "java"

    network_interface      = [for nic_idx in range(aws_network_interface.test):
      {
      device_index          = nic_idx
      network_interface_id  = aws_network_interface.test[nic_idx].id
      delete_on_termination = false
    }
  ]
    ebs_block_device {
    device_name           = "/dev/sdg"
    volume_type           = "gp2"
    volume_size           = 200
    delete_on_termination = true
  }
  ebs_block_device {
    device_name           = "/dev/sdf"
    volume_type           = "gp2"
    volume_size           = 20
    delete_on_termination = true
  }
  ebs_block_device {
    device_name           = "/dev/sdh"
    volume_type           = "gp2"
    volume_size           = 10
    delete_on_termination = true
  }

}

The issue here is that your configuration is assigning an argument (using network_interface = [ … ], but it should be using a block (no x = y assignment, just x {…}).

To use for_each with blocks, please refer to the dynamic blocks documentation. In this case, I think the below configuration should do what you’re trying to do:

resource "aws_instance" "ec2_instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
  count         = var.number_of_instances

  dynamic "network_interface" {
    for_each = aws_network_interface.test
    content {
      device_index          = network_interface.key
      network_interface_id  = network_interface.value.id
      delete_on_termination = false
    }
  }
}

Please note that I have never actually tried creating and assigning AWS network interfaces in this way, so it may not be a best practice—I’m just trying to help with the Terraform language semantics where I can. Hopefully someone with more practical experience can chime in if there’s a better way to do this!

Hi @alisdair,
Sill i ma getting error like below

Error: Incorrect attribute value type

  on main.tf line 28, in resource "aws_instance" "ec2_instance":
  28:       network_interface_id  =aws_network_interface.test[*].id
    |----------------
    | aws_network_interface.test is tuple with 2 elements

Inappropriate value for attribute "network_interface_id": string required.


Error: Incorrect attribute value type

  on main.tf line 28, in resource "aws_instance" "ec2_instance":
  28:       network_interface_id  =aws_network_interface.test[*].id
    |----------------
    | aws_network_interface.test is tuple with 2 elements

Inappropriate value for attribute "network_interface_id": string required.


Error: Incorrect attribute value type

  on main.tf line 28, in resource "aws_instance" "ec2_instance":
  28:       network_interface_id  =aws_network_interface.test[*].id
    |----------------
    | aws_network_interface.test is tuple with 2 elements

Inappropriate value for attribute "network_interface_id": string required.


Error: Incorrect attribute value type

  on main.tf line 28, in resource "aws_instance" "ec2_instance":
  28:       network_interface_id  =aws_network_interface.test[*].id
    |----------------
    | aws_network_interface.test is tuple with 2 elements

Inappropriate value for attribute "network_interface_id": string required.
// Provider specific configs

provider "aws" {
  shared_credentials_file = "/c/Users/ag64160/.aws/credentials"
  profile                 = "sandbox"
  region                  = "us-east-1"

}
resource "aws_network_interface" "test" {
  subnet_id       = "subnet-06de28df4461194be"
  security_groups =  ["sg-0de4b3a45f739ee0f"]
  count           = "${var.number_of_instances}"
}


// EC2 Instance Resource for Module
    resource "aws_instance" "ec2_instance" {
    ami = "${var.ami_id}"
    count = "${var.number_of_instances}"
    instance_type = "${var.instance_type}"
    subnet_id = "${var.subnet_id}"
    vpc_security_group_ids = ["${aws_security_group.apigee-instance.id}"]
    key_name = "psdev"
    dynamic "network_interface" {
    for_each =  aws_network_interface.test
    content {
      device_index          = 1
      network_interface_id  =aws_network_interface.test[*].id
      delete_on_termination = false
    }
}
    ebs_block_device {
    device_name           = "/dev/sdg"
    volume_type           = "gp2"
    volume_size           = 200
    delete_on_termination = true
  }
  ebs_block_device {
    device_name           = "/dev/sdf"
    volume_type           = "gp2"
    volume_size           = 20
    delete_on_termination = true
  }
  ebs_block_device {
    device_name           = "/dev/sdh"
    volume_type           = "gp2"
    volume_size           = 10
    delete_on_termination = true
  }

}

Did you try the configuration as I suggested? Quoted again:

Did this not work?

HI @alisdair,
Yes its working, but when am creating instances it creating 2 network interfaces,
i need only one network interface.
how to get that,Please help me.

FYR i am updating plan state

Terraform will perform the following actions:

  # aws_instance.ec2_instance[0] will be created
  + resource "aws_instance" "ec2_instance" {
      + ami                          = "ami-0e8f1415d9ba49d82"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = "psdev"
      + network_interface_id         = (known after apply)
      + outpost_arn                  = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdf"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 20
          + volume_type           = "gp2"
        }
      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdg"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 200
          + volume_type           = "gp2"
        }
      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdh"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 10
          + volume_type           = "gp2"
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
        }

      + network_interface {
          + delete_on_termination = false
          + device_index          = 0
          + network_interface_id  = (known after apply)
        }
      + network_interface {
          + delete_on_termination = false
          + device_index          = 1
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_instance.ec2_instance[1] will be created
  + resource "aws_instance" "ec2_instance" {
      + ami                          = "ami-0e8f1415d9ba49d82"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = "psdev"
      + network_interface_id         = (known after apply)
      + outpost_arn                  = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdf"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 20
          + volume_type           = "gp2"
        }
      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdg"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 200
          + volume_type           = "gp2"
        }
      + ebs_block_device {
          + delete_on_termination = true
          + device_name           = "/dev/sdh"
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 10
          + volume_type           = "gp2"
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
        }

      + network_interface {
          + delete_on_termination = false
          + device_index          = 0
          + network_interface_id  = (known after apply)
        }
      + network_interface {
          + delete_on_termination = false
          + device_index          = 1
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_network_interface.test[0] will be created
  + resource "aws_network_interface" "test" {
      + id                = (known after apply)
      + mac_address       = (known after apply)
      + outpost_arn       = (known after apply)
      + private_dns_name  = (known after apply)
      + private_ip        = (known after apply)
      + private_ips       = (known after apply)
      + private_ips_count = (known after apply)
      + security_groups   = [
          + "sg-0de4b3a45f739ee0f",
        ]
      + source_dest_check = true
      + subnet_id         = "subnet-06de28df4461194be"

      + attachment {
          + attachment_id = (known after apply)
          + device_index  = (known after apply)
          + instance      = (known after apply)
        }
    }

  # aws_network_interface.test[1] will be created
  + resource "aws_network_interface" "test" {
      + id                = (known after apply)
      + mac_address       = (known after apply)
      + outpost_arn       = (known after apply)
      + private_dns_name  = (known after apply)
      + private_ip        = (known after apply)
      + private_ips       = (known after apply)
      + private_ips_count = (known after apply)
      + security_groups   = [
          + "sg-0de4b3a45f739ee0f",
        ]
      + source_dest_check = true
      + subnet_id         = "subnet-06de28df4461194be"

      + attachment {
          + attachment_id = (known after apply)
          + device_index  = (known after apply)
          + instance      = (known after apply)
        }

Oh, I see! I completely misunderstood what you’re trying to do. I thought you wanted all network interfaces to be bound to each AWS instance.

I now think you’re trying to create, say, 5 aws_network_interface resources and 5 aws_instance resources, and assign them one-to-one. That does make more sense :sweat_smile:

In that case, I think you want to bind the network interface using an address with count.index, like this:

resource "aws_instance" "ec2_instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
  count         = var.number_of_instances

  network_interface {
    device_index          = 0
    network_interface_id  = aws_network_interface.test[count.index].id
    delete_on_termination = false
  }
}

I hope that’s clearer. Again, I haven’t used this configuration with AWS, so if anyone would care to offer corrections or recommend best practices, that would be great!

Hi @alisdair,
Its working, Thanks.
I have one more question
How to assign tag to specific node (eg count= 5) in terraform.
usecase:
creating 5 nodes using count =5, but i need a specific tag to 2nd and 5th node,
is it possible via terraform.