github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/ebs.go (about) 1 // Copyright 2019 The Terraformer Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aws 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 22 "github.com/GoogleCloudPlatform/terraformer/terraformutils" 23 "github.com/aws/aws-sdk-go-v2/aws" 24 "github.com/hashicorp/terraform/helper/hashcode" 25 26 "github.com/aws/aws-sdk-go-v2/service/ec2" 27 "github.com/aws/aws-sdk-go-v2/service/ec2/types" 28 ) 29 30 var ebsAllowEmptyValues = []string{"tags."} 31 32 type EbsGenerator struct { 33 AWSService 34 } 35 36 func (g *EbsGenerator) volumeAttachmentID(device, volumeID, instanceID string) string { 37 return fmt.Sprintf("vai-%d", hashcode.String(fmt.Sprintf("%s-%s-%s-", device, instanceID, volumeID))) 38 } 39 40 func (g *EbsGenerator) InitResources() error { 41 config, e := g.generateConfig() 42 if e != nil { 43 return e 44 } 45 svc := ec2.NewFromConfig(config) 46 var filters []types.Filter 47 for _, filter := range g.Filter { 48 if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("ebs_volume") { 49 filters = append(filters, types.Filter{ 50 Name: aws.String("tag:" + strings.TrimPrefix(filter.FieldPath, "tags.")), 51 Values: filter.AcceptableValues, 52 }) 53 } 54 } 55 p := ec2.NewDescribeVolumesPaginator(svc, &ec2.DescribeVolumesInput{ 56 Filters: filters, 57 }) 58 for p.HasMorePages() { 59 page, e := p.NextPage(context.TODO()) 60 if e != nil { 61 return e 62 } 63 for _, volume := range page.Volumes { 64 isRootDevice := false // Let's leave root device configuration to be done in ec2_instance resources 65 66 for _, attachment := range volume.Attachments { 67 instances, _ := svc.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{ 68 InstanceIds: []string{StringValue(attachment.InstanceId)}, 69 }) 70 for _, reservation := range instances.Reservations { 71 for _, instance := range reservation.Instances { 72 if StringValue(instance.RootDeviceName) == StringValue(attachment.Device) { 73 isRootDevice = true 74 } 75 } 76 } 77 } 78 79 if !isRootDevice { 80 g.Resources = append(g.Resources, terraformutils.NewSimpleResource( 81 StringValue(volume.VolumeId), 82 StringValue(volume.VolumeId), 83 "aws_ebs_volume", 84 "aws", 85 ebsAllowEmptyValues, 86 )) 87 88 for _, attachment := range volume.Attachments { 89 if attachment.State == types.VolumeAttachmentStateAttached { 90 attachmentID := g.volumeAttachmentID( 91 StringValue(attachment.Device), 92 StringValue(attachment.VolumeId), 93 StringValue(attachment.InstanceId)) 94 g.Resources = append(g.Resources, terraformutils.NewResource( 95 attachmentID, 96 StringValue(attachment.InstanceId)+":"+StringValue(attachment.Device), 97 "aws_volume_attachment", 98 "aws", 99 map[string]string{ 100 "device_name": StringValue(attachment.Device), 101 "volume_id": StringValue(attachment.VolumeId), 102 "instance_id": StringValue(attachment.InstanceId), 103 }, 104 []string{}, 105 map[string]interface{}{}, 106 )) 107 } 108 } 109 } 110 } 111 } 112 return nil 113 }