diff --git a/pkg/driftctl.go b/pkg/driftctl.go index 524f1b61..c8e7e07e 100644 --- a/pkg/driftctl.go +++ b/pkg/driftctl.go @@ -36,6 +36,7 @@ func (d DriftCTL) Run() *analyser.Analysis { middlewares.NewVPCDefaultSecurityGroupSanitizer(), middlewares.NewVPCSecurityGroupRuleSanitizer(), middlewares.NewIamPolicyAttachmentSanitizer(), + middlewares.AwsInstanceEIP{}, ) logrus.Debug("Ready to run middlewares") diff --git a/pkg/middlewares/aws_instance_eip.go b/pkg/middlewares/aws_instance_eip.go new file mode 100644 index 00000000..73734a37 --- /dev/null +++ b/pkg/middlewares/aws_instance_eip.go @@ -0,0 +1,61 @@ +package middlewares + +import ( + "github.com/cloudskiff/driftctl/pkg/resource" + "github.com/cloudskiff/driftctl/pkg/resource/aws" + "github.com/sirupsen/logrus" +) + +type AwsInstanceEIP struct{} + +func (a AwsInstanceEIP) Execute(remoteResources, resourcesFromState *[]resource.Resource) error { + for _, remoteResource := range *remoteResources { + // Ignore all resources other than aws_instance + if remoteResource.TerraformType() != aws.AwsInstanceResourceType { + continue + } + + instance, _ := remoteResource.(*aws.AwsInstance) + + if a.hasEIP(instance, resourcesFromState) { + logrus.WithFields(logrus.Fields{ + "instance": instance.TerraformId(), + }).Debug("Ignore instance public ip and dns as it has an eip attached") + a.ignorePublicIpAndDns(instance, remoteResources, resourcesFromState) + } + } + + return nil +} + +func (a AwsInstanceEIP) hasEIP(instance *aws.AwsInstance, resources *[]resource.Resource) bool { + for _, res := range *resources { + if res.TerraformType() == aws.AwsEipResourceType { + eip, _ := res.(*aws.AwsEip) + if *eip.Instance == instance.Id { + return true + } + } + if res.TerraformType() == aws.AwsEipAssociationResourceType { + eip, _ := res.(*aws.AwsEipAssociation) + if *eip.InstanceId == instance.Id { + return true + } + } + } + + return false +} + +func (a AwsInstanceEIP) ignorePublicIpAndDns(instance *aws.AwsInstance, resourcesSet ...*[]resource.Resource) { + for _, resources := range resourcesSet { + for _, res := range *resources { + if res.TerraformType() == instance.TerraformType() && + res.TerraformId() == instance.TerraformId() { + instance, _ := res.(*aws.AwsInstance) + instance.PublicDns = nil + instance.PublicIp = nil + } + } + } +} diff --git a/pkg/middlewares/aws_instance_eip_test.go b/pkg/middlewares/aws_instance_eip_test.go new file mode 100644 index 00000000..4687848a --- /dev/null +++ b/pkg/middlewares/aws_instance_eip_test.go @@ -0,0 +1,128 @@ +package middlewares + +import ( + "reflect" + "testing" + + awssdk "github.com/aws/aws-sdk-go/aws" + "github.com/cloudskiff/driftctl/pkg/resource" + "github.com/cloudskiff/driftctl/pkg/resource/aws" +) + +func TestAwsInstanceEIP_Execute(t *testing.T) { + type args struct { + remoteResources *[]resource.Resource + resourcesFromState *[]resource.Resource + } + tests := []struct { + name string + args args + expected args + }{ + { + name: "test that public ip and dns are nulled whith eip", + args: args{ + remoteResources: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + &aws.AwsInstance{ + Id: "instance2", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + }, + resourcesFromState: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + PublicIp: awssdk.String("5.6.7.8"), + PublicDns: awssdk.String("example.com"), + }, + &aws.AwsEip{ + Instance: awssdk.String("instance1"), + }, + }, + }, + expected: args{ + remoteResources: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + }, + &aws.AwsInstance{ + Id: "instance2", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + }, + resourcesFromState: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + }, + &aws.AwsEip{ + Instance: awssdk.String("instance1"), + }, + }, + }, + }, + { + name: "test that public ip and dns are nulled when eip association", + args: args{ + remoteResources: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + &aws.AwsInstance{ + Id: "instance2", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + }, + resourcesFromState: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + PublicIp: awssdk.String("5.6.7.8"), + PublicDns: awssdk.String("example.com"), + }, + &aws.AwsEipAssociation{ + InstanceId: awssdk.String("instance1"), + }, + }, + }, + expected: args{ + remoteResources: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + }, + &aws.AwsInstance{ + Id: "instance2", + PublicIp: awssdk.String("1.2.3.4"), + PublicDns: awssdk.String("dns-of-eip.com"), + }, + }, + resourcesFromState: &[]resource.Resource{ + &aws.AwsInstance{ + Id: "instance1", + }, + &aws.AwsEipAssociation{ + InstanceId: awssdk.String("instance1"), + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := AwsInstanceEIP{} + if err := a.Execute(tt.args.remoteResources, tt.args.resourcesFromState); err != nil { + t.Fatal(err) + } + if ! reflect.DeepEqual(tt.args, tt.expected) { + t.Fatalf("Expected results mismatch") + } + }) + } +}