Merge pull request #12933 from hashicorp/f-network-interfaces
provider/aws: Add network_interface to aws_instance
This commit is contained in:
commit
64134418a5
|
@ -128,11 +128,45 @@ func resourceAwsInstance() *schema.Resource {
|
|||
Computed: true,
|
||||
},
|
||||
|
||||
// TODO: Deprecate me v0.10.0
|
||||
"network_interface_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Deprecated: "Please use `primary_network_interface_id` instead",
|
||||
},
|
||||
|
||||
"primary_network_interface_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"network_interface": {
|
||||
ConflictsWith: []string{"associate_public_ip_address", "subnet_id", "private_ip", "vpc_security_group_ids", "security_groups", "ipv6_addresses", "ipv6_address_count", "source_dest_check"},
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"delete_on_termination": {
|
||||
Type: schema.TypeBool,
|
||||
Default: false,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"network_interface_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"device_index": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"public_ip": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
|
@ -558,23 +592,62 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
|||
d.Set("private_ip", instance.PrivateIpAddress)
|
||||
d.Set("iam_instance_profile", iamInstanceProfileArnToName(instance.IamInstanceProfile))
|
||||
|
||||
// Set configured Network Interface Device Index Slice
|
||||
// We only want to read, and populate state for the configured network_interface attachments. Otherwise, other
|
||||
// resources have the potential to attach network interfaces to the instance, and cause a perpetual create/destroy
|
||||
// diff. We should only read on changes configured for this specific resource because of this.
|
||||
var configuredDeviceIndexes []int
|
||||
if v, ok := d.GetOk("network_interface"); ok {
|
||||
vL := v.(*schema.Set).List()
|
||||
for _, vi := range vL {
|
||||
mVi := vi.(map[string]interface{})
|
||||
configuredDeviceIndexes = append(configuredDeviceIndexes, mVi["device_index"].(int))
|
||||
}
|
||||
}
|
||||
|
||||
var ipv6Addresses []string
|
||||
if len(instance.NetworkInterfaces) > 0 {
|
||||
for _, ni := range instance.NetworkInterfaces {
|
||||
if *ni.Attachment.DeviceIndex == 0 {
|
||||
d.Set("subnet_id", ni.SubnetId)
|
||||
d.Set("network_interface_id", ni.NetworkInterfaceId)
|
||||
d.Set("associate_public_ip_address", ni.Association != nil)
|
||||
d.Set("ipv6_address_count", len(ni.Ipv6Addresses))
|
||||
|
||||
for _, address := range ni.Ipv6Addresses {
|
||||
ipv6Addresses = append(ipv6Addresses, *address.Ipv6Address)
|
||||
var primaryNetworkInterface ec2.InstanceNetworkInterface
|
||||
var networkInterfaces []map[string]interface{}
|
||||
for _, iNi := range instance.NetworkInterfaces {
|
||||
ni := make(map[string]interface{})
|
||||
if *iNi.Attachment.DeviceIndex == 0 {
|
||||
primaryNetworkInterface = *iNi
|
||||
}
|
||||
// If the attached network device is inside our configuration, refresh state with values found.
|
||||
// Otherwise, assume the network device was attached via an outside resource.
|
||||
for _, index := range configuredDeviceIndexes {
|
||||
if index == int(*iNi.Attachment.DeviceIndex) {
|
||||
ni["device_index"] = *iNi.Attachment.DeviceIndex
|
||||
ni["network_interface_id"] = *iNi.NetworkInterfaceId
|
||||
ni["delete_on_termination"] = *iNi.Attachment.DeleteOnTermination
|
||||
}
|
||||
}
|
||||
// Don't add empty network interfaces to schema
|
||||
if len(ni) == 0 {
|
||||
continue
|
||||
}
|
||||
networkInterfaces = append(networkInterfaces, ni)
|
||||
}
|
||||
if err := d.Set("network_interface", networkInterfaces); err != nil {
|
||||
return fmt.Errorf("Error setting network_interfaces: %v", err)
|
||||
}
|
||||
|
||||
// Set primary network interface details
|
||||
d.Set("subnet_id", primaryNetworkInterface.SubnetId)
|
||||
d.Set("network_interface_id", primaryNetworkInterface.NetworkInterfaceId) // TODO: Deprecate me v0.10.0
|
||||
d.Set("primary_network_interface_id", primaryNetworkInterface.NetworkInterfaceId)
|
||||
d.Set("associate_public_ip_address", primaryNetworkInterface.Association != nil)
|
||||
d.Set("ipv6_address_count", len(primaryNetworkInterface.Ipv6Addresses))
|
||||
|
||||
for _, address := range primaryNetworkInterface.Ipv6Addresses {
|
||||
ipv6Addresses = append(ipv6Addresses, *address.Ipv6Address)
|
||||
}
|
||||
|
||||
} else {
|
||||
d.Set("subnet_id", instance.SubnetId)
|
||||
d.Set("network_interface_id", "")
|
||||
d.Set("network_interface_id", "") // TODO: Deprecate me v0.10.0
|
||||
d.Set("primary_network_interface_id", "")
|
||||
}
|
||||
|
||||
if err := d.Set("ipv6_addresses", ipv6Addresses); err != nil {
|
||||
|
@ -716,24 +789,28 @@ func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
if d.HasChange("source_dest_check") || d.IsNewResource() {
|
||||
// SourceDestCheck can only be set on VPC instances // AWS will return an error of InvalidParameterCombination if we attempt
|
||||
// to modify the source_dest_check of an instance in EC2 Classic
|
||||
log.Printf("[INFO] Modifying `source_dest_check` on Instance %s", d.Id())
|
||||
_, err := conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
|
||||
InstanceId: aws.String(d.Id()),
|
||||
SourceDestCheck: &ec2.AttributeBooleanValue{
|
||||
Value: aws.Bool(d.Get("source_dest_check").(bool)),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if ec2err, ok := err.(awserr.Error); ok {
|
||||
// Toloerate InvalidParameterCombination error in Classic, otherwise
|
||||
// return the error
|
||||
if "InvalidParameterCombination" != ec2err.Code() {
|
||||
return err
|
||||
// SourceDestCheck can only be modified on an instance without manually specified network interfaces.
|
||||
// SourceDestCheck, in that case, is configured at the network interface level
|
||||
if _, ok := d.GetOk("network_interface"); !ok {
|
||||
if d.HasChange("source_dest_check") || d.IsNewResource() {
|
||||
// SourceDestCheck can only be set on VPC instances // AWS will return an error of InvalidParameterCombination if we attempt
|
||||
// to modify the source_dest_check of an instance in EC2 Classic
|
||||
log.Printf("[INFO] Modifying `source_dest_check` on Instance %s", d.Id())
|
||||
_, err := conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
|
||||
InstanceId: aws.String(d.Id()),
|
||||
SourceDestCheck: &ec2.AttributeBooleanValue{
|
||||
Value: aws.Bool(d.Get("source_dest_check").(bool)),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
if ec2err, ok := err.(awserr.Error); ok {
|
||||
// Tolerate InvalidParameterCombination error in Classic, otherwise
|
||||
// return the error
|
||||
if "InvalidParameterCombination" != ec2err.Code() {
|
||||
return err
|
||||
}
|
||||
log.Printf("[WARN] Attempted to modify SourceDestCheck on non VPC instance: %s", ec2err.Message())
|
||||
}
|
||||
log.Printf("[WARN] Attempted to modify SourceDestCheck on non VPC instance: %s", ec2err.Message())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1053,6 +1130,55 @@ func fetchRootDeviceName(ami string, conn *ec2.EC2) (*string, error) {
|
|||
return rootDeviceName, nil
|
||||
}
|
||||
|
||||
func buildNetworkInterfaceOpts(d *schema.ResourceData, groups []*string, nInterfaces interface{}) []*ec2.InstanceNetworkInterfaceSpecification {
|
||||
networkInterfaces := []*ec2.InstanceNetworkInterfaceSpecification{}
|
||||
// Get necessary items
|
||||
associatePublicIPAddress := d.Get("associate_public_ip_address").(bool)
|
||||
subnet, hasSubnet := d.GetOk("subnet_id")
|
||||
|
||||
if hasSubnet && associatePublicIPAddress {
|
||||
// If we have a non-default VPC / Subnet specified, we can flag
|
||||
// AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided.
|
||||
// You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise
|
||||
// you get: Network interfaces and an instance-level subnet ID may not be specified on the same request
|
||||
// You also need to attach Security Groups to the NetworkInterface instead of the instance,
|
||||
// to avoid: Network interfaces and an instance-level security groups may not be specified on
|
||||
// the same request
|
||||
ni := &ec2.InstanceNetworkInterfaceSpecification{
|
||||
AssociatePublicIpAddress: aws.Bool(associatePublicIPAddress),
|
||||
DeviceIndex: aws.Int64(int64(0)),
|
||||
SubnetId: aws.String(subnet.(string)),
|
||||
Groups: groups,
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("private_ip"); ok {
|
||||
ni.PrivateIpAddress = aws.String(v.(string))
|
||||
}
|
||||
|
||||
if v := d.Get("vpc_security_group_ids").(*schema.Set); v.Len() > 0 {
|
||||
for _, v := range v.List() {
|
||||
ni.Groups = append(ni.Groups, aws.String(v.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
networkInterfaces = append(networkInterfaces, ni)
|
||||
} else {
|
||||
// If we have manually specified network interfaces, build and attach those here.
|
||||
vL := nInterfaces.(*schema.Set).List()
|
||||
for _, v := range vL {
|
||||
ini := v.(map[string]interface{})
|
||||
ni := &ec2.InstanceNetworkInterfaceSpecification{
|
||||
DeviceIndex: aws.Int64(int64(ini["device_index"].(int))),
|
||||
NetworkInterfaceId: aws.String(ini["network_interface_id"].(string)),
|
||||
DeleteOnTermination: aws.Bool(ini["delete_on_termination"].(bool)),
|
||||
}
|
||||
networkInterfaces = append(networkInterfaces, ni)
|
||||
}
|
||||
}
|
||||
|
||||
return networkInterfaces
|
||||
}
|
||||
|
||||
func readBlockDeviceMappingsFromConfig(
|
||||
d *schema.ResourceData, conn *ec2.EC2) ([]*ec2.BlockDeviceMapping, error) {
|
||||
blockDevices := make([]*ec2.BlockDeviceMapping, 0)
|
||||
|
@ -1338,33 +1464,14 @@ func buildAwsInstanceOpts(
|
|||
}
|
||||
}
|
||||
|
||||
if hasSubnet && associatePublicIPAddress {
|
||||
// If we have a non-default VPC / Subnet specified, we can flag
|
||||
// AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided.
|
||||
// You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise
|
||||
// you get: Network interfaces and an instance-level subnet ID may not be specified on the same request
|
||||
// You also need to attach Security Groups to the NetworkInterface instead of the instance,
|
||||
// to avoid: Network interfaces and an instance-level security groups may not be specified on
|
||||
// the same request
|
||||
ni := &ec2.InstanceNetworkInterfaceSpecification{
|
||||
AssociatePublicIpAddress: aws.Bool(associatePublicIPAddress),
|
||||
DeviceIndex: aws.Int64(int64(0)),
|
||||
SubnetId: aws.String(subnetID),
|
||||
Groups: groups,
|
||||
}
|
||||
networkInterfaces, interfacesOk := d.GetOk("network_interface")
|
||||
|
||||
if v, ok := d.GetOk("private_ip"); ok {
|
||||
ni.PrivateIpAddress = aws.String(v.(string))
|
||||
}
|
||||
|
||||
if v := d.Get("vpc_security_group_ids").(*schema.Set); v.Len() > 0 {
|
||||
for _, v := range v.List() {
|
||||
ni.Groups = append(ni.Groups, aws.String(v.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
opts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ni}
|
||||
// If setting subnet and public address, OR manual network interfaces, populate those now.
|
||||
if hasSubnet && associatePublicIPAddress || interfacesOk {
|
||||
// Otherwise we're attaching (a) network interface(s)
|
||||
opts.NetworkInterfaces = buildNetworkInterfaceOpts(d, groups, networkInterfaces)
|
||||
} else {
|
||||
// If simply specifying a subnetID, privateIP, Security Groups, or VPC Security Groups, build these now
|
||||
if subnetID != "" {
|
||||
opts.SubnetID = aws.String(subnetID)
|
||||
}
|
||||
|
@ -1397,7 +1504,6 @@ func buildAwsInstanceOpts(
|
|||
if len(blockDevices) > 0 {
|
||||
opts.BlockDeviceMappings = blockDevices
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -926,6 +926,58 @@ func TestAccAWSInstance_changeInstanceType(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstance_primaryNetworkInterface(t *testing.T) {
|
||||
var instance ec2.Instance
|
||||
var ini ec2.NetworkInterface
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceConfigPrimaryNetworkInterface,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckInstanceExists("aws_instance.foo", &instance),
|
||||
testAccCheckAWSENIExists("aws_network_interface.bar", &ini),
|
||||
resource.TestCheckResourceAttr("aws_instance.foo", "network_interface.#", "1"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstance_addSecondaryInterface(t *testing.T) {
|
||||
var before ec2.Instance
|
||||
var after ec2.Instance
|
||||
var iniPrimary ec2.NetworkInterface
|
||||
var iniSecondary ec2.NetworkInterface
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceConfigAddSecondaryNetworkInterfaceBefore,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckInstanceExists("aws_instance.foo", &before),
|
||||
testAccCheckAWSENIExists("aws_network_interface.primary", &iniPrimary),
|
||||
resource.TestCheckResourceAttr("aws_instance.foo", "network_interface.#", "1"),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: testAccInstanceConfigAddSecondaryNetworkInterfaceAfter,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckInstanceExists("aws_instance.foo", &after),
|
||||
testAccCheckAWSENIExists("aws_network_interface.secondary", &iniSecondary),
|
||||
resource.TestCheckResourceAttr("aws_instance.foo", "network_interface.#", "1"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckInstanceNotRecreated(t *testing.T,
|
||||
before, after *ec2.Instance) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
|
@ -1696,3 +1748,129 @@ resource "aws_instance" "foo" {
|
|||
subnet_id = "${aws_subnet.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceConfigPrimaryNetworkInterface = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "172.16.0.0/16"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
cidr_block = "172.16.10.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_network_interface" "bar" {
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ips = ["172.16.10.100"]
|
||||
tags {
|
||||
Name = "primary_network_interface"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-22b9a343"
|
||||
instance_type = "t2.micro"
|
||||
network_interface {
|
||||
network_interface_id = "${aws_network_interface.bar.id}"
|
||||
device_index = 0
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceConfigAddSecondaryNetworkInterfaceBefore = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "172.16.0.0/16"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
cidr_block = "172.16.10.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_network_interface" "primary" {
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ips = ["172.16.10.100"]
|
||||
tags {
|
||||
Name = "primary_network_interface"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_network_interface" "secondary" {
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ips = ["172.16.10.101"]
|
||||
tags {
|
||||
Name = "secondary_network_interface"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-22b9a343"
|
||||
instance_type = "t2.micro"
|
||||
network_interface {
|
||||
network_interface_id = "${aws_network_interface.primary.id}"
|
||||
device_index = 0
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceConfigAddSecondaryNetworkInterfaceAfter = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "172.16.0.0/16"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
cidr_block = "172.16.10.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
tags {
|
||||
Name = "tf-instance-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_network_interface" "primary" {
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ips = ["172.16.10.100"]
|
||||
tags {
|
||||
Name = "primary_network_interface"
|
||||
}
|
||||
}
|
||||
|
||||
// Attach previously created network interface, observe no state diff on instance resource
|
||||
resource "aws_network_interface" "secondary" {
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ips = ["172.16.10.101"]
|
||||
tags {
|
||||
Name = "secondary_network_interface"
|
||||
}
|
||||
attachment {
|
||||
instance = "${aws_instance.foo.id}"
|
||||
device_index = 1
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-22b9a343"
|
||||
instance_type = "t2.micro"
|
||||
network_interface {
|
||||
network_interface_id = "${aws_network_interface.primary.id}"
|
||||
device_index = 0
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -87,6 +87,7 @@ instances. See [Shutdown Behavior](https://docs.aws.amazon.com/AWSEC2/latest/Use
|
|||
instance. See [Block Devices](#block-devices) below for details.
|
||||
* `ephemeral_block_device` - (Optional) Customize Ephemeral (also known as
|
||||
"Instance Store") volumes on the instance. See [Block Devices](#block-devices) below for details.
|
||||
* `network_interface` - (Optional) Customize network interfaces to be attached at instance boot time. See [Network Interfaces](#network-interfaces) below for more details.
|
||||
|
||||
|
||||
## Block devices
|
||||
|
@ -150,6 +151,59 @@ resources cannot be automatically detected by Terraform. After making updates
|
|||
to block device configuration, resource recreation can be manually triggered by
|
||||
using the [`taint` command](/docs/commands/taint.html).
|
||||
|
||||
## Network Interfaces
|
||||
|
||||
Each of the `network_interface` blocks attach a network interface to an EC2 Instance during boot time. However, because
|
||||
the network interface is attached at boot-time, replacing/modifying the network interface **WILL** trigger a recreation
|
||||
of the EC2 Instance. If you should need at any point to detach/modify/re-attach a network interface to the instance, use
|
||||
the `aws_network_interface` or `aws_network_interface_attachment` resources instead.
|
||||
|
||||
The `network_interface` configuration block _does_, however, allow users to supply their own network interface to be used
|
||||
as the default network interface on an EC2 Instance, attached at `eth0`.
|
||||
|
||||
Each `network_interface` block supports the following:
|
||||
|
||||
* `device_index` - (Required) The integer index of the network interface attachment. Limited by instance type.
|
||||
* `network_interface_id` - (Required) The ID of the network interface to attach.
|
||||
* `delete_on_termination` - (Optional) Whether or not to delete the network interface on instance termination. Defaults to `false`.
|
||||
|
||||
### Example
|
||||
|
||||
```hcl
|
||||
resource "aws_vpc" "my_vpc" {
|
||||
cidr_block = "172.16.0.0/16"
|
||||
tags {
|
||||
Name = "tf-example"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "my_subnet" {
|
||||
vpc_id = "${aws_vpc.my_vpc.id}"
|
||||
cidr_block = "172.16.10.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
tags {
|
||||
Name = "tf-example"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_network_interface" "foo" {
|
||||
subnet_id = "${aws_subnet.my_subnet.id}"
|
||||
private_ips = ["172.16.10.100"]
|
||||
tags {
|
||||
Name = "primary_network_interface"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-22b9a343" // us-west-2
|
||||
instance_type = "t2.micro"
|
||||
network_interface {
|
||||
network_interface_id = "${aws_network_interface.foo.id}"
|
||||
device_index = 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
@ -162,6 +216,7 @@ The following attributes are exported:
|
|||
is only available if you've enabled DNS hostnames for your VPC
|
||||
* `public_ip` - The public IP address assigned to the instance, if applicable. **NOTE**: If you are using an [`aws_eip`](/docs/providers/aws/r/eip.html) with your instance, you should refer to the EIP's address directly and not use `public_ip`, as this field will change after the EIP is attached.
|
||||
* `network_interface_id` - The ID of the network interface that was created with the instance.
|
||||
* `primary_network_interface_id` - The ID of the instance's primary network interface.
|
||||
* `private_dns` - The private DNS name assigned to the instance. Can only be
|
||||
used inside the Amazon EC2, and only available if you've enabled DNS hostnames
|
||||
for your VPC
|
||||
|
|
Loading…
Reference in New Issue