127 lines
4.8 KiB
Go
127 lines
4.8 KiB
Go
package middlewares
|
|
|
|
import (
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/snyk/driftctl/pkg/resource"
|
|
"github.com/snyk/driftctl/pkg/resource/aws"
|
|
)
|
|
|
|
// Remove root_block_device from aws_instance resources and create dedicated aws_ebs_volume resources
|
|
type AwsInstanceBlockDeviceResourceMapper struct {
|
|
resourceFactory resource.ResourceFactory
|
|
}
|
|
|
|
func NewAwsInstanceBlockDeviceResourceMapper(resourceFactory resource.ResourceFactory) AwsInstanceBlockDeviceResourceMapper {
|
|
return AwsInstanceBlockDeviceResourceMapper{
|
|
resourceFactory: resourceFactory,
|
|
}
|
|
}
|
|
|
|
func (a AwsInstanceBlockDeviceResourceMapper) Execute(remoteResources, resourcesFromState *[]*resource.Resource) error {
|
|
|
|
newStateResources := make([]*resource.Resource, 0)
|
|
for _, stateRes := range *resourcesFromState {
|
|
|
|
// Ignore all resources other than aws_instance
|
|
if stateRes.ResourceType() != aws.AwsInstanceResourceType {
|
|
newStateResources = append(newStateResources, stateRes)
|
|
continue
|
|
}
|
|
|
|
if rootBlockDevice, exist := stateRes.Attrs.Get("root_block_device"); exist {
|
|
for _, rootBlock := range rootBlockDevice.([]interface{}) {
|
|
rootBlock := rootBlock.(map[string]interface{})
|
|
logrus.WithFields(logrus.Fields{
|
|
"volume": rootBlock["volume_id"],
|
|
"instance": stateRes.ResourceId(),
|
|
}).Debug("Creating aws_ebs_volume from aws_instance.root_block_device")
|
|
data := map[string]interface{}{
|
|
"availability_zone": (*stateRes.Attrs)["availability_zone"],
|
|
"encrypted": rootBlock["encrypted"],
|
|
"id": rootBlock["volume_id"],
|
|
"iops": rootBlock["iops"],
|
|
"kms_key_id": rootBlock["kms_key_id"],
|
|
"size": rootBlock["volume_size"],
|
|
"type": rootBlock["volume_type"],
|
|
"multi_attach_enabled": false,
|
|
"tags": a.volumeTags(stateRes, rootBlock),
|
|
}
|
|
if throughput, exist := rootBlock["throughput"]; exist {
|
|
data["throughput"] = throughput
|
|
}
|
|
newRes := a.resourceFactory.CreateAbstractResource("aws_ebs_volume", rootBlock["volume_id"].(string), data)
|
|
newStateResources = append(newStateResources, newRes)
|
|
}
|
|
stateRes.Attrs.SafeDelete([]string{"root_block_device"})
|
|
stateRes.Attrs.SafeDelete([]string{"volume_tags"})
|
|
}
|
|
|
|
if ebsBlockDevice, exist := stateRes.Attrs.Get("ebs_block_device"); exist {
|
|
for _, blockDevice := range ebsBlockDevice.([]interface{}) {
|
|
blockDevice := blockDevice.(map[string]interface{})
|
|
if a.hasBlockDevice(blockDevice, resourcesFromState) {
|
|
continue
|
|
}
|
|
logrus.WithFields(logrus.Fields{
|
|
"volume": blockDevice["volume_id"],
|
|
"instance": stateRes.ResourceId(),
|
|
}).Debug("Creating aws_ebs_volume from aws_instance.ebs_block_device")
|
|
data := map[string]interface{}{
|
|
"availability_zone": (*stateRes.Attrs)["availability_zone"],
|
|
"encrypted": blockDevice["encrypted"],
|
|
"id": blockDevice["volume_id"],
|
|
"iops": blockDevice["iops"],
|
|
"kms_key_id": blockDevice["kms_key_id"],
|
|
"size": blockDevice["volume_size"],
|
|
"type": blockDevice["volume_type"],
|
|
"multi_attach_enabled": false,
|
|
"tags": a.volumeTags(stateRes, blockDevice),
|
|
}
|
|
if throughput, exist := blockDevice["throughput"]; exist {
|
|
data["throughput"] = throughput
|
|
}
|
|
newRes := a.resourceFactory.CreateAbstractResource("aws_ebs_volume", blockDevice["volume_id"].(string), data)
|
|
newStateResources = append(newStateResources, newRes)
|
|
}
|
|
stateRes.Attrs.SafeDelete([]string{"ebs_block_device"})
|
|
stateRes.Attrs.SafeDelete([]string{"volume_tags"})
|
|
}
|
|
newStateResources = append(newStateResources, stateRes)
|
|
}
|
|
|
|
newRemoteResources := make([]*resource.Resource, 0)
|
|
for _, remoteRes := range *remoteResources {
|
|
if remoteRes.ResourceType() != aws.AwsInstanceResourceType {
|
|
newRemoteResources = append(newRemoteResources, remoteRes)
|
|
continue
|
|
}
|
|
remoteRes.Attrs.SafeDelete([]string{"root_block_device"})
|
|
remoteRes.Attrs.SafeDelete([]string{"ebs_block_device"})
|
|
remoteRes.Attrs.SafeDelete([]string{"volume_tags"})
|
|
newRemoteResources = append(newRemoteResources, remoteRes)
|
|
}
|
|
|
|
*resourcesFromState = newStateResources
|
|
*remoteResources = newRemoteResources
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a AwsInstanceBlockDeviceResourceMapper) volumeTags(instance *resource.Resource, blockDevice map[string]interface{}) interface{} {
|
|
if tags, exist := instance.Attrs.Get("volume_tags"); exist {
|
|
return tags
|
|
}
|
|
return blockDevice["tags"]
|
|
}
|
|
|
|
func (a AwsInstanceBlockDeviceResourceMapper) hasBlockDevice(blockDevice map[string]interface{}, resourcesFromState *[]*resource.Resource) bool {
|
|
for _, stateRes := range *resourcesFromState {
|
|
if stateRes.ResourceType() == aws.AwsEbsVolumeResourceType &&
|
|
stateRes.ResourceId() == blockDevice["volume_id"] {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|