github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/data_source_aws_instance.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/service/ec2" 9 "github.com/hashicorp/terraform/helper/schema" 10 ) 11 12 func dataSourceAwsInstance() *schema.Resource { 13 return &schema.Resource{ 14 Read: dataSourceAwsInstanceRead, 15 16 Schema: map[string]*schema.Schema{ 17 "filter": dataSourceFiltersSchema(), 18 "tags": dataSourceTagsSchema(), 19 "instance_tags": tagsSchemaComputed(), 20 "instance_id": { 21 Type: schema.TypeString, 22 Optional: true, 23 ForceNew: true, 24 }, 25 "ami": { 26 Type: schema.TypeString, 27 Computed: true, 28 }, 29 "instance_type": { 30 Type: schema.TypeString, 31 Computed: true, 32 }, 33 "instance_state": { 34 Type: schema.TypeString, 35 Computed: true, 36 }, 37 "availability_zone": { 38 Type: schema.TypeString, 39 Computed: true, 40 }, 41 "tenancy": { 42 Type: schema.TypeString, 43 Computed: true, 44 }, 45 "key_name": { 46 Type: schema.TypeString, 47 Computed: true, 48 }, 49 "public_dns": { 50 Type: schema.TypeString, 51 Computed: true, 52 }, 53 "public_ip": { 54 Type: schema.TypeString, 55 Computed: true, 56 }, 57 "private_dns": { 58 Type: schema.TypeString, 59 Computed: true, 60 }, 61 "private_ip": { 62 Type: schema.TypeString, 63 Computed: true, 64 }, 65 "iam_instance_profile": { 66 Type: schema.TypeString, 67 Computed: true, 68 }, 69 "subnet_id": { 70 Type: schema.TypeString, 71 Computed: true, 72 }, 73 "network_interface_id": { 74 Type: schema.TypeString, 75 Computed: true, 76 }, 77 "associate_public_ip_address": { 78 Type: schema.TypeBool, 79 Computed: true, 80 }, 81 "ebs_optimized": { 82 Type: schema.TypeBool, 83 Computed: true, 84 }, 85 "source_dest_check": { 86 Type: schema.TypeBool, 87 Computed: true, 88 }, 89 "monitoring": { 90 Type: schema.TypeBool, 91 Computed: true, 92 }, 93 "user_data": { 94 Type: schema.TypeString, 95 Computed: true, 96 }, 97 "security_groups": { 98 Type: schema.TypeSet, 99 Computed: true, 100 Elem: &schema.Schema{ 101 Type: schema.TypeString, 102 }, 103 }, 104 "vpc_security_group_ids": { 105 Type: schema.TypeSet, 106 Computed: true, 107 Elem: &schema.Schema{ 108 Type: schema.TypeString, 109 }, 110 }, 111 "ephemeral_block_device": { 112 Type: schema.TypeSet, 113 Computed: true, 114 Elem: &schema.Resource{ 115 Schema: map[string]*schema.Schema{ 116 "device_name": { 117 Type: schema.TypeString, 118 Required: true, 119 }, 120 121 "virtual_name": { 122 Type: schema.TypeString, 123 Optional: true, 124 }, 125 126 "no_device": { 127 Type: schema.TypeBool, 128 Optional: true, 129 }, 130 }, 131 }, 132 }, 133 "ebs_block_device": { 134 Type: schema.TypeSet, 135 Computed: true, 136 Elem: &schema.Resource{ 137 Schema: map[string]*schema.Schema{ 138 "delete_on_termination": { 139 Type: schema.TypeBool, 140 Computed: true, 141 }, 142 143 "device_name": { 144 Type: schema.TypeString, 145 Computed: true, 146 }, 147 148 "encrypted": { 149 Type: schema.TypeBool, 150 Computed: true, 151 }, 152 153 "iops": { 154 Type: schema.TypeInt, 155 Computed: true, 156 }, 157 158 "snapshot_id": { 159 Type: schema.TypeString, 160 Computed: true, 161 }, 162 163 "volume_size": { 164 Type: schema.TypeInt, 165 Computed: true, 166 }, 167 168 "volume_type": { 169 Type: schema.TypeString, 170 Computed: true, 171 }, 172 }, 173 }, 174 }, 175 "root_block_device": { 176 Type: schema.TypeSet, 177 Computed: true, 178 Elem: &schema.Resource{ 179 Schema: map[string]*schema.Schema{ 180 "delete_on_termination": { 181 Type: schema.TypeBool, 182 Computed: true, 183 }, 184 185 "iops": { 186 Type: schema.TypeInt, 187 Computed: true, 188 }, 189 190 "volume_size": { 191 Type: schema.TypeInt, 192 Computed: true, 193 }, 194 195 "volume_type": { 196 Type: schema.TypeString, 197 Computed: true, 198 }, 199 }, 200 }, 201 }, 202 }, 203 } 204 } 205 206 // dataSourceAwsInstanceRead performs the instanceID lookup 207 func dataSourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { 208 conn := meta.(*AWSClient).ec2conn 209 210 filters, filtersOk := d.GetOk("filter") 211 instanceID, instanceIDOk := d.GetOk("instance_id") 212 tags, tagsOk := d.GetOk("instance_tags") 213 214 if filtersOk == false && instanceIDOk == false && tagsOk == false { 215 return fmt.Errorf("One of filters, instance_tags, or instance_id must be assigned") 216 } 217 218 // Build up search parameters 219 params := &ec2.DescribeInstancesInput{} 220 if filtersOk { 221 params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set)) 222 } 223 if instanceIDOk { 224 params.InstanceIds = []*string{aws.String(instanceID.(string))} 225 } 226 if tagsOk { 227 params.Filters = append(params.Filters, buildEC2TagFilterList( 228 tagsFromMap(tags.(map[string]interface{})), 229 )...) 230 } 231 232 // Perform the lookup 233 resp, err := conn.DescribeInstances(params) 234 if err != nil { 235 return err 236 } 237 238 // If no instances were returned, return 239 if len(resp.Reservations) == 0 { 240 return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.") 241 } 242 243 var filteredInstances []*ec2.Instance 244 245 // loop through reservations, and remove terminated instances, populate instance slice 246 for _, res := range resp.Reservations { 247 for _, instance := range res.Instances { 248 if instance.State != nil && *instance.State.Name != "terminated" { 249 filteredInstances = append(filteredInstances, instance) 250 } 251 } 252 } 253 254 var instance *ec2.Instance 255 if len(filteredInstances) < 1 { 256 return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.") 257 } 258 259 // (TODO: Support a list of instances to be returned) 260 // Possibly with a different data source that returns a list of individual instance data sources 261 if len(filteredInstances) > 1 { 262 return fmt.Errorf("Your query returned more than one result. Please try a more " + 263 "specific search criteria.") 264 } else { 265 instance = filteredInstances[0] 266 } 267 268 log.Printf("[DEBUG] aws_instance - Single Instance ID found: %s", *instance.InstanceId) 269 return instanceDescriptionAttributes(d, instance, conn) 270 } 271 272 // Populate instance attribute fields with the returned instance 273 func instanceDescriptionAttributes(d *schema.ResourceData, instance *ec2.Instance, conn *ec2.EC2) error { 274 d.SetId(*instance.InstanceId) 275 // Set the easy attributes 276 d.Set("instance_state", instance.State.Name) 277 if instance.Placement != nil { 278 d.Set("availability_zone", instance.Placement.AvailabilityZone) 279 } 280 if instance.Placement.Tenancy != nil { 281 d.Set("tenancy", instance.Placement.Tenancy) 282 } 283 d.Set("ami", instance.ImageId) 284 d.Set("instance_type", instance.InstanceType) 285 d.Set("key_name", instance.KeyName) 286 d.Set("public_dns", instance.PublicDnsName) 287 d.Set("public_ip", instance.PublicIpAddress) 288 d.Set("private_dns", instance.PrivateDnsName) 289 d.Set("private_ip", instance.PrivateIpAddress) 290 d.Set("iam_instance_profile", iamInstanceProfileArnToName(instance.IamInstanceProfile)) 291 292 // iterate through network interfaces, and set subnet, network_interface, public_addr 293 if len(instance.NetworkInterfaces) > 0 { 294 for _, ni := range instance.NetworkInterfaces { 295 if *ni.Attachment.DeviceIndex == 0 { 296 d.Set("subnet_id", ni.SubnetId) 297 d.Set("network_interface_id", ni.NetworkInterfaceId) 298 d.Set("associate_public_ip_address", ni.Association != nil) 299 } 300 } 301 } else { 302 d.Set("subnet_id", instance.SubnetId) 303 d.Set("network_interface_id", "") 304 } 305 306 d.Set("ebs_optimized", instance.EbsOptimized) 307 if instance.SubnetId != nil && *instance.SubnetId != "" { 308 d.Set("source_dest_check", instance.SourceDestCheck) 309 } 310 311 if instance.Monitoring != nil && instance.Monitoring.State != nil { 312 monitoringState := *instance.Monitoring.State 313 d.Set("monitoring", monitoringState == "enabled" || monitoringState == "pending") 314 } 315 316 d.Set("tags", dataSourceTags(instance.Tags)) 317 318 // Security Groups 319 if err := readSecurityGroups(d, instance); err != nil { 320 return err 321 } 322 323 // Block devices 324 if err := readBlockDevices(d, instance, conn); err != nil { 325 return err 326 } 327 if _, ok := d.GetOk("ephemeral_block_device"); !ok { 328 d.Set("ephemeral_block_device", []interface{}{}) 329 } 330 331 // Lookup and Set Instance Attributes 332 { 333 attr, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{ 334 Attribute: aws.String("disableApiTermination"), 335 InstanceId: aws.String(d.Id()), 336 }) 337 if err != nil { 338 return err 339 } 340 d.Set("disable_api_termination", attr.DisableApiTermination.Value) 341 } 342 { 343 attr, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{ 344 Attribute: aws.String(ec2.InstanceAttributeNameUserData), 345 InstanceId: aws.String(d.Id()), 346 }) 347 if err != nil { 348 return err 349 } 350 if attr.UserData.Value != nil { 351 d.Set("user_data", userDataHashSum(*attr.UserData.Value)) 352 } 353 } 354 355 return nil 356 }