provider/aws: Add aws_instance data source
Adds the `aws_instance` data source, tests, and documentation. ``` ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/01/18 11:49:09 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSInstanceDataSource -timeout 120m === RUN TestAccAWSInstanceDataSource_basic --- PASS: TestAccAWSInstanceDataSource_basic (106.24s) === RUN TestAccAWSInstanceDataSource_AzUserData --- PASS: TestAccAWSInstanceDataSource_AzUserData (108.52s) === RUN TestAccAWSInstanceDataSource_gp2IopsDevice --- PASS: TestAccAWSInstanceDataSource_gp2IopsDevice (80.71s) === RUN TestAccAWSInstanceDataSource_blockDevices --- PASS: TestAccAWSInstanceDataSource_blockDevices (94.07s) === RUN TestAccAWSInstanceDataSource_rootInstanceStore --- PASS: TestAccAWSInstanceDataSource_rootInstanceStore (95.17s) === RUN TestAccAWSInstanceDataSource_privateIP --- PASS: TestAccAWSInstanceDataSource_privateIP (241.75s) === RUN TestAccAWSInstanceDataSource_keyPair --- PASS: TestAccAWSInstanceDataSource_keyPair (208.77s) === RUN TestAccAWSInstanceDataSource_VPC --- PASS: TestAccAWSInstanceDataSource_VPC (109.89s) === RUN TestAccAWSInstanceDataSource_SecurityGroups --- PASS: TestAccAWSInstanceDataSource_SecurityGroups (118.66s) === RUN TestAccAWSInstanceDataSource_VPCSecurityGroups --- PASS: TestAccAWSInstanceDataSource_VPCSecurityGroups (136.79s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 1300.625s ```
This commit is contained in:
parent
dac527be47
commit
9cbd67dd0b
|
@ -0,0 +1,349 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func dataSourceAwsInstance() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Read: dataSourceAwsInstanceRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"filter": dataSourceFiltersSchema(),
|
||||
"tags": dataSourceTagsSchema(),
|
||||
"instance_id": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"ami": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"instance_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"instance_state": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"availability_zone": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"tenancy": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"key_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"public_dns": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"public_ip": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"private_dns": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"private_ip": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"iam_instance_profile": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"subnet_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"network_interface_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"associate_public_ip_address": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"ebs_optimized": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"source_dest_check": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"monitoring": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"user_data": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"security_groups": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
"vpc_security_group_ids": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
"ephemeral_block_device": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"device_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"virtual_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"no_device": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ebs_block_device": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"delete_on_termination": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"device_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"encrypted": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"iops": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"snapshot_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"volume_size": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"volume_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"root_block_device": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"delete_on_termination": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"iops": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"volume_size": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"volume_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// dataSourceAwsInstanceRead performs the instanceID lookup
|
||||
func dataSourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).ec2conn
|
||||
|
||||
filters, filtersOk := d.GetOk("filter")
|
||||
instanceID, instanceIDOk := d.GetOk("instance_id")
|
||||
|
||||
if filtersOk == false && instanceIDOk == false {
|
||||
return fmt.Errorf("One of filters, or instance_id must be assigned")
|
||||
}
|
||||
|
||||
// Build up search parameters
|
||||
params := &ec2.DescribeInstancesInput{}
|
||||
if filtersOk {
|
||||
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
|
||||
}
|
||||
if instanceIDOk {
|
||||
params.InstanceIds = []*string{aws.String(instanceID.(string))}
|
||||
}
|
||||
|
||||
// Perform the lookup
|
||||
resp, err := conn.DescribeInstances(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If no instances were returned, return
|
||||
if len(resp.Reservations) == 0 {
|
||||
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
|
||||
}
|
||||
|
||||
var filteredInstances []*ec2.Instance
|
||||
|
||||
// loop through reservations, and remove terminated instances, populate instance slice
|
||||
for _, res := range resp.Reservations {
|
||||
for _, instance := range res.Instances {
|
||||
if instance.State != nil && *instance.State.Name != "terminated" {
|
||||
filteredInstances = append(filteredInstances, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var instance *ec2.Instance
|
||||
if len(filteredInstances) < 1 {
|
||||
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
|
||||
}
|
||||
|
||||
// (TODO: Support a list of instances to be returned)
|
||||
// Possibly with a different data source that returns a list of individual instance data sources
|
||||
if len(filteredInstances) > 1 {
|
||||
return fmt.Errorf("Your query returned more than one result. Please try a more " +
|
||||
"specific search criteria.")
|
||||
} else {
|
||||
instance = filteredInstances[0]
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] aws_instance - Single Instance ID found: %s", *instance.InstanceId)
|
||||
return instanceDescriptionAttributes(d, instance, conn)
|
||||
}
|
||||
|
||||
// Populate instance attribute fields with the returned instance
|
||||
func instanceDescriptionAttributes(d *schema.ResourceData, instance *ec2.Instance, conn *ec2.EC2) error {
|
||||
d.SetId(*instance.InstanceId)
|
||||
// Set the easy attributes
|
||||
d.Set("instance_state", instance.State.Name)
|
||||
if instance.Placement != nil {
|
||||
d.Set("availability_zone", instance.Placement.AvailabilityZone)
|
||||
}
|
||||
if instance.Placement.Tenancy != nil {
|
||||
d.Set("tenancy", instance.Placement.Tenancy)
|
||||
}
|
||||
d.Set("ami", instance.ImageId)
|
||||
d.Set("instance_type", instance.InstanceType)
|
||||
d.Set("key_name", instance.KeyName)
|
||||
d.Set("public_dns", instance.PublicDnsName)
|
||||
d.Set("public_ip", instance.PublicIpAddress)
|
||||
d.Set("private_dns", instance.PrivateDnsName)
|
||||
d.Set("private_ip", instance.PrivateIpAddress)
|
||||
d.Set("iam_instance_profile", iamInstanceProfileArnToName(instance.IamInstanceProfile))
|
||||
|
||||
// iterate through network interfaces, and set subnet, network_interface, public_addr
|
||||
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)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
d.Set("subnet_id", instance.SubnetId)
|
||||
d.Set("network_interface_id", "")
|
||||
}
|
||||
|
||||
d.Set("ebs_optimized", instance.EbsOptimized)
|
||||
if instance.SubnetId != nil && *instance.SubnetId != "" {
|
||||
d.Set("source_dest_check", instance.SourceDestCheck)
|
||||
}
|
||||
|
||||
if instance.Monitoring != nil && instance.Monitoring.State != nil {
|
||||
monitoringState := *instance.Monitoring.State
|
||||
d.Set("monitoring", monitoringState == "enabled" || monitoringState == "pending")
|
||||
}
|
||||
|
||||
d.Set("tags", dataSourceTags(instance.Tags))
|
||||
|
||||
// Security Groups
|
||||
if err := readSecurityGroups(d, instance); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Block devices
|
||||
if err := readBlockDevices(d, instance, conn); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := d.GetOk("ephemeral_block_device"); !ok {
|
||||
d.Set("ephemeral_block_device", []interface{}{})
|
||||
}
|
||||
|
||||
// Lookup and Set Instance Attributes
|
||||
{
|
||||
attr, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{
|
||||
Attribute: aws.String("disableApiTermination"),
|
||||
InstanceId: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("disable_api_termination", attr.DisableApiTermination.Value)
|
||||
}
|
||||
{
|
||||
attr, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{
|
||||
Attribute: aws.String(ec2.InstanceAttributeNameUserData),
|
||||
InstanceId: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if attr.UserData.Value != nil {
|
||||
d.Set("user_data", userDataHashSum(*attr.UserData.Value))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,498 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccAWSInstanceDataSource_basic(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.web-instance", "ami", "ami-4fccb37f"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.web-instance", "tags.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.web-instance", "instance_type", "m1.small"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_AzUserData(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_AzUserData,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-4fccb37f"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "tags.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m1.small"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "availability_zone", "us-west-2a"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "user_data", "3dc39dda39be1205215e776bad998da361a5955d"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_gp2IopsDevice(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_gp2IopsDevice,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-55a7ea65"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m3.medium"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.0.volume_size", "11"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.0.volume_type", "gp2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.0.iops", "100"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_blockDevices(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_blockDevices,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-55a7ea65"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m3.medium"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.0.volume_size", "11"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.0.volume_type", "gp2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "ebs_block_device.#", "3"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "ephemeral_block_device.#", "1"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_rootInstanceStore(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_rootInstanceStore,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-44c36524"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m3.medium"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "ebs_block_device.#", "0"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "ebs_optimized", "false"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.#", "0"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_privateIP(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_privateIP,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-c5eabbf5"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "t2.micro"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "private_ip", "10.1.1.42"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_keyPair(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_keyPair,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-408c7f28"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "t1.micro"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "tags.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "key_name", "tmp-key"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_VPC(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_VPC,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-4fccb37f"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m1.small"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "user_data", "562a3e32810edf6ff09994f050f12e799452379d"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "associate_public_ip_address", "true"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "tenancy", "dedicated"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_SecurityGroups(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_SecurityGroups,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-408c7f28"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "m1.small"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "vpc_security_group_ids.#", "0"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "security_groups.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "user_data", "3dc39dda39be1205215e776bad998da361a5955d"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSInstanceDataSource_VPCSecurityGroups(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceDataSourceConfig_VPCSecurityGroups,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "ami", "ami-21f78e11"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "instance_type", "t1.micro"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "security_groups.#", "0"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"data.aws_instance.foo", "vpc_security_group_ids.#", "1"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Lookup based on InstanceID
|
||||
const testAccInstanceDataSourceConfig = `
|
||||
resource "aws_instance" "web" {
|
||||
# us-west-2
|
||||
ami = "ami-4fccb37f"
|
||||
instance_type = "m1.small"
|
||||
tags {
|
||||
Name = "HelloWorld"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_instance" "web-instance" {
|
||||
filter {
|
||||
name = "instance-id"
|
||||
values = ["${aws_instance.web.id}"]
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// filter on tag, populate more attributes
|
||||
const testAccInstanceDataSourceConfig_AzUserData = `
|
||||
resource "aws_instance" "foo" {
|
||||
# us-west-2
|
||||
ami = "ami-4fccb37f"
|
||||
availability_zone = "us-west-2a"
|
||||
|
||||
instance_type = "m1.small"
|
||||
user_data = "foo:-with-character's"
|
||||
tags {
|
||||
TFAccTest = "YesThisIsATest"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
// GP2IopsDevice
|
||||
const testAccInstanceDataSourceConfig_gp2IopsDevice = `
|
||||
resource "aws_instance" "foo" {
|
||||
# us-west-2
|
||||
ami = "ami-55a7ea65"
|
||||
instance_type = "m3.medium"
|
||||
root_block_device {
|
||||
volume_type = "gp2"
|
||||
volume_size = 11
|
||||
iops = 330
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
// Block Device
|
||||
const testAccInstanceDataSourceConfig_blockDevices = `
|
||||
resource "aws_instance" "foo" {
|
||||
# us-west-2
|
||||
ami = "ami-55a7ea65"
|
||||
instance_type = "m3.medium"
|
||||
|
||||
root_block_device {
|
||||
volume_type = "gp2"
|
||||
volume_size = 11
|
||||
}
|
||||
ebs_block_device {
|
||||
device_name = "/dev/sdb"
|
||||
volume_size = 9
|
||||
}
|
||||
ebs_block_device {
|
||||
device_name = "/dev/sdc"
|
||||
volume_size = 10
|
||||
volume_type = "io1"
|
||||
iops = 100
|
||||
}
|
||||
|
||||
# Encrypted ebs block device
|
||||
ebs_block_device {
|
||||
device_name = "/dev/sdd"
|
||||
volume_size = 12
|
||||
encrypted = true
|
||||
}
|
||||
|
||||
ephemeral_block_device {
|
||||
device_name = "/dev/sde"
|
||||
virtual_name = "ephemeral0"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_rootInstanceStore = `
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-44c36524"
|
||||
instance_type = "m3.medium"
|
||||
}
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_privateIP = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-c5eabbf5"
|
||||
instance_type = "t2.micro"
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
private_ip = "10.1.1.42"
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_keyPair = `
|
||||
provider "aws" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_key_pair" "debugging" {
|
||||
key_name = "tmp-key"
|
||||
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 phodgson@thoughtworks.com"
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-408c7f28"
|
||||
instance_type = "t1.micro"
|
||||
key_name = "${aws_key_pair.debugging.key_name}"
|
||||
tags {
|
||||
Name = "testAccInstanceDataSourceConfigKeyPair_TestAMI"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
filter {
|
||||
name = "tag:Name"
|
||||
values = ["testAccInstanceDataSourceConfigKeyPair_TestAMI"]
|
||||
}
|
||||
filter {
|
||||
name = "key-name"
|
||||
values = ["${aws_instance.foo.key_name}"]
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_VPC = `
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
# us-west-2
|
||||
ami = "ami-4fccb37f"
|
||||
instance_type = "m1.small"
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
associate_public_ip_address = true
|
||||
tenancy = "dedicated"
|
||||
# pre-encoded base64 data
|
||||
user_data = "3dc39dda39be1205215e776bad998da361a5955d"
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_SecurityGroups = `
|
||||
provider "aws" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_security_group" "tf_test_foo" {
|
||||
name = "tf_test_foo"
|
||||
description = "foo"
|
||||
|
||||
ingress {
|
||||
protocol = "icmp"
|
||||
from_port = -1
|
||||
to_port = -1
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "ami-408c7f28"
|
||||
instance_type = "m1.small"
|
||||
security_groups = ["${aws_security_group.tf_test_foo.name}"]
|
||||
user_data = "foo:-with-character's"
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo.id}"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceDataSourceConfig_VPCSecurityGroups = `
|
||||
resource "aws_internet_gateway" "gw" {
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_vpc" "foo" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
tags {
|
||||
Name = "tf-network-test"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "tf_test_foo" {
|
||||
name = "tf_test_foo"
|
||||
description = "foo"
|
||||
vpc_id="${aws_vpc.foo.id}"
|
||||
|
||||
ingress {
|
||||
protocol = "icmp"
|
||||
from_port = -1
|
||||
to_port = -1
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_subnet" "foo" {
|
||||
cidr_block = "10.1.1.0/24"
|
||||
vpc_id = "${aws_vpc.foo.id}"
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo_instance" {
|
||||
ami = "ami-21f78e11"
|
||||
instance_type = "t1.micro"
|
||||
vpc_security_group_ids = ["${aws_security_group.tf_test_foo.id}"]
|
||||
subnet_id = "${aws_subnet.foo.id}"
|
||||
depends_on = ["aws_internet_gateway.gw"]
|
||||
}
|
||||
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "${aws_instance.foo_instance.id}"
|
||||
}
|
||||
`
|
|
@ -161,6 +161,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_iam_account_alias": dataSourceAwsIamAccountAlias(),
|
||||
"aws_iam_policy_document": dataSourceAwsIamPolicyDocument(),
|
||||
"aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(),
|
||||
"aws_instance": dataSourceAwsInstance(),
|
||||
"aws_ip_ranges": dataSourceAwsIPRanges(),
|
||||
"aws_prefix_list": dataSourceAwsPrefixList(),
|
||||
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
|
||||
|
|
|
@ -526,53 +526,9 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
|||
|
||||
d.Set("tags", tagsToMap(instance.Tags))
|
||||
|
||||
// Determine whether we're referring to security groups with
|
||||
// IDs or names. We use a heuristic to figure this out. By default,
|
||||
// we use IDs if we're in a VPC. However, if we previously had an
|
||||
// all-name list of security groups, we use names. Or, if we had any
|
||||
// IDs, we use IDs.
|
||||
useID := instance.SubnetId != nil && *instance.SubnetId != ""
|
||||
if v := d.Get("security_groups"); v != nil {
|
||||
match := useID
|
||||
sgs := v.(*schema.Set).List()
|
||||
if len(sgs) > 0 {
|
||||
match = false
|
||||
for _, v := range v.(*schema.Set).List() {
|
||||
if strings.HasPrefix(v.(string), "sg-") {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useID = match
|
||||
}
|
||||
|
||||
// Build up the security groups
|
||||
sgs := make([]string, 0, len(instance.SecurityGroups))
|
||||
if useID {
|
||||
for _, sg := range instance.SecurityGroups {
|
||||
sgs = append(sgs, *sg.GroupId)
|
||||
}
|
||||
log.Printf("[DEBUG] Setting Security Group IDs: %#v", sgs)
|
||||
if err := d.Set("vpc_security_group_ids", sgs); err != nil {
|
||||
if err := readSecurityGroups(d, instance); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set("security_groups", []string{}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for _, sg := range instance.SecurityGroups {
|
||||
sgs = append(sgs, *sg.GroupName)
|
||||
}
|
||||
log.Printf("[DEBUG] Setting Security Group Names: %#v", sgs)
|
||||
if err := d.Set("security_groups", sgs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set("vpc_security_group_ids", []string{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := readBlockDevices(d, instance, conn); err != nil {
|
||||
return err
|
||||
|
@ -1013,6 +969,57 @@ func readBlockDeviceMappingsFromConfig(
|
|||
return blockDevices, nil
|
||||
}
|
||||
|
||||
// Determine whether we're referring to security groups with
|
||||
// IDs or names. We use a heuristic to figure this out. By default,
|
||||
// we use IDs if we're in a VPC. However, if we previously had an
|
||||
// all-name list of security groups, we use names. Or, if we had any
|
||||
// IDs, we use IDs.
|
||||
func readSecurityGroups(d *schema.ResourceData, instance *ec2.Instance) error {
|
||||
useID := instance.SubnetId != nil && *instance.SubnetId != ""
|
||||
if v := d.Get("security_groups"); v != nil {
|
||||
match := useID
|
||||
sgs := v.(*schema.Set).List()
|
||||
if len(sgs) > 0 {
|
||||
match = false
|
||||
for _, v := range v.(*schema.Set).List() {
|
||||
if strings.HasPrefix(v.(string), "sg-") {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useID = match
|
||||
}
|
||||
|
||||
// Build up the security groups
|
||||
sgs := make([]string, 0, len(instance.SecurityGroups))
|
||||
if useID {
|
||||
for _, sg := range instance.SecurityGroups {
|
||||
sgs = append(sgs, *sg.GroupId)
|
||||
}
|
||||
log.Printf("[DEBUG] Setting Security Group IDs: %#v", sgs)
|
||||
if err := d.Set("vpc_security_group_ids", sgs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set("security_groups", []string{}); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for _, sg := range instance.SecurityGroups {
|
||||
sgs = append(sgs, *sg.GroupName)
|
||||
}
|
||||
log.Printf("[DEBUG] Setting Security Group Names: %#v", sgs)
|
||||
if err := d.Set("security_groups", sgs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set("vpc_security_group_ids", []string{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type awsInstanceOpts struct {
|
||||
BlockDeviceMappings []*ec2.BlockDeviceMapping
|
||||
DisableAPITermination *bool
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_instance"
|
||||
sidebar_current: "docs-aws-datasource-instance"
|
||||
description: |-
|
||||
Get information on a Amazon EC2 Instance.
|
||||
---
|
||||
|
||||
# aws\_instance
|
||||
|
||||
Use this data source to get the ID of an EC2 Instance for use in other
|
||||
resources.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
data "aws_instance" "foo" {
|
||||
instance_id = "i-instanceid"
|
||||
filter {
|
||||
name = "image-id"
|
||||
values = ["ami-xxxxxxxx"]
|
||||
}
|
||||
filter {
|
||||
name = "tag:Name"
|
||||
values = ["instance-name-tag"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
* `instance_id` - (Optional) Specify the exact Instance ID to populate the data source with.
|
||||
|
||||
* `filter` - (Optional) One or more name/value pairs to filter off of. There are
|
||||
several valid keys, for a full reference, check out
|
||||
[describe-instances in the AWS CLI reference][1].
|
||||
|
||||
~> **NOTE:** At least one of `filter` or `instance_id` must be specified.
|
||||
|
||||
~> **NOTE:** If more or less than a single match is returned by the search,
|
||||
Terraform will fail. Ensure that your search is specific enough to return
|
||||
a single Instance ID only.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
`id` is set to the ID of the found Instance. In addition, the following attributes
|
||||
are exported:
|
||||
|
||||
~> **NOTE:** Some values are not always set and may not be available for
|
||||
interpolation.
|
||||
|
||||
* `associate_public_ip_address` - Whether or not the instance is associated with a public ip address or not (Boolean).
|
||||
* `availability_zone` - The availability zone of the instance.
|
||||
* `ebs_block_device` - The EBS block device mappings of the instance.
|
||||
* `delete_on_termination` - If the EBS volume will be deleted on termination.
|
||||
* `device_name` - The physical name of the device.
|
||||
* `encrypted` - If the EBS volume is encrypted.
|
||||
* `iops` - `0` If the EBS volume is not a provisioned IOPS image, otherwise the supported IOPS count.
|
||||
* `snapshot_id` - The ID of the snapshot.
|
||||
* `volume_size` - The size of the volume, in GiB.
|
||||
* `volume_type` - The volume type.
|
||||
* `ebs_optimized` - Whether the instance is ebs optimized or not (Boolean).
|
||||
* `ephemeral_block_device` - The ephemeral block device mappings of the instance.
|
||||
* `device_name` - The physical name of the device.
|
||||
* `no_device` - Whether the specified device included in the device mapping was suppressed or not (Boolean).
|
||||
* `virtual_name` - The virtual device name
|
||||
* `iam_instance_profile` - The instance profile associated with the instance. Specified as an ARN.
|
||||
* `instance_type` - The type of the instance.
|
||||
* `key_name` - The key name of the instance.
|
||||
* `monitoring` - Whether detailed monitoring is enabled or disabled for the instance (Boolean).
|
||||
* `network_interface_id` - The ID of the network interface that was created with the instance.
|
||||
* `placement_group` - The placement group of the instance.
|
||||
* `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.
|
||||
* `private_ip` - The private IP address assigned to the instance.
|
||||
* `public_dns` - The public DNS name assigned to the instance. For EC2-VPC, this
|
||||
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.
|
||||
* `root_block_device` - The root block device mappings of the instance
|
||||
* `delete_on_termination` - If the root block device will be deleted on termination.
|
||||
* `iops` - `0` If the volume is not a provisioned IOPS image, otherwise the supported IOPS count.
|
||||
* `volume_size` - The size of the volume, in GiB.
|
||||
* `volume_type` - The type of the volume.
|
||||
* `security_groups` - The associated security groups.
|
||||
* `source_dest_check` - Whether the network interface performs source/destination checking (Boolean).
|
||||
* `subnet_id` - The VPC subnet ID.
|
||||
* `user_data` - The User Data supplied to the instance.
|
||||
* `tags` - A mapping of tags assigned to the instance.
|
||||
* `tenancy` - The tenancy of the instance (dedicated | default | host ).
|
||||
* `vpc_security_group_ids` - The associated security groups in non-default VPC.
|
||||
|
||||
[1]: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html
|
Loading…
Reference in New Issue