diff --git a/Makefile b/Makefile index 294928b1..06b7eb62 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ coverage: test .PHONY: acc acc: - DRIFTCTL_ACC=true $(GOTEST) --format testname --junitfile unit-tests-acc.xml -- -coverprofile=cover-acc.out -test.timeout 1h -coverpkg=./pkg/... -run=$(ACC_PATTERN) ./pkg/resource/... + DRIFTCTL_ACC=true $(GOTEST) --format testname --junitfile unit-tests-acc.xml -- -coverprofile=cover-acc.out -test.timeout 1h -coverpkg=./pkg/... -run=$(ACC_PATTERN) ./pkg/... .PHONY: mocks mocks: deps diff --git a/pkg/iac/terraform/state/terraform_state_reader_acc_test.go b/pkg/iac/terraform/state/terraform_state_reader_acc_test.go new file mode 100644 index 00000000..d7de05d3 --- /dev/null +++ b/pkg/iac/terraform/state/terraform_state_reader_acc_test.go @@ -0,0 +1,84 @@ +package state_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/s3" + "github.com/cloudskiff/driftctl/test/acceptance" + "github.com/cloudskiff/driftctl/test/acceptance/awsutils" +) + +func TestAcc_StateReader_WithMultiplesStatesInS3(t *testing.T) { + stateBucketName := "driftctl-acc-test-only" + acceptance.Run(t, acceptance.AccTestCase{ + OnStart: func() { + err := createBucket(stateBucketName) + if err != nil { + t.Fatal(err) + } + }, + Paths: []string{"./testdata/acc/multiples_states/s3", "./testdata/acc/multiples_states/route53"}, + Args: []string{ + "scan", + "--from", fmt.Sprintf("tfstate+s3://%s/states", stateBucketName), + "--filter", "Type=='aws_s3_bucket' || Type=='aws_route53_zone'", + }, + Checks: []acceptance.AccCheck{ + { + Check: func(result *acceptance.ScanResult, stdout string, err error) { + if err != nil { + t.Fatal(err) + } + result.AssertUnmanagedCount(1) + result.AssertDeletedCount(0) + result.AssertResourceUnmanaged("driftctl-acc-test-only", "aws_s3_bucket") + result.AssertManagedCount(2) + result.Equal("aws_route53_zone", result.Managed()[0].TerraformType()) + result.Equal("aws_s3_bucket", result.Managed()[1].TerraformType()) + }, + }, + }, + OnEnd: func() { + err := removeStateBucket(stateBucketName) + if err != nil { + t.Fatal(err) + } + }, + }) +} + +func createBucket(bucket string) error { + client := s3.New(awsutils.Session()) + _, err := client.CreateBucket(&s3.CreateBucketInput{ + Bucket: &bucket, + }) + if err != nil { + return err + } + return nil +} + +func removeStateBucket(bucket string) error { + client := s3.New(awsutils.Session()) + objects, err := client.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: &bucket}) + if err != nil { + return err + } + for _, object := range objects.Contents { + _, err := client.DeleteObject(&s3.DeleteObjectInput{ + Bucket: &bucket, + Key: object.Key, + }) + if err != nil { + return err + } + } + _, err = client.DeleteBucket(&s3.DeleteBucketInput{ + Bucket: &bucket, + }) + if err != nil { + return err + } + return nil +} diff --git a/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/.terraform.lock.hcl b/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/.terraform.lock.hcl new file mode 100755 index 00000000..1045bc9c --- /dev/null +++ b/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/.terraform.lock.hcl @@ -0,0 +1,38 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "3.19.0" + constraints = "~> 3.19.0" + hashes = [ + "h1:+7Vi7p13+cnrxjXbfJiTimGSFR97xCaQwkkvWcreLns=", + "zh:185a5259153eb9ee4699d4be43b3d509386b473683392034319beee97d470c3b", + "zh:2d9a0a01f93e8d16539d835c02b8b6e1927b7685f4076e96cb07f7dd6944bc6c", + "zh:703f6da36b1b5f3497baa38fccaa7765fb8a2b6440344e4c97172516b49437dd", + "zh:770855565462abadbbddd98cb357d2f1a8f30f68a358cb37cbd5c072cb15b377", + "zh:8008db43149fe4345301f81e15e6d9ddb47aa5e7a31648f9b290af96ad86e92a", + "zh:8cdd27d375da6dcb7687f1fed126b7c04efce1671066802ee876dbbc9c66ec79", + "zh:be22ae185005690d1a017c1b909e0d80ab567e239b4f06ecacdba85080667c1c", + "zh:d2d02e72dbd80f607636cd6237a6c862897caabc635c7b50c0cb243d11246723", + "zh:d8f125b66a1eda2555c0f9bbdf12036a5f8d073499a22ca9e4812b68067fea31", + "zh:f5a98024c64d5d2973ff15b093725a074c0cb4afde07ef32c542e69f17ac90bc", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.1.0" + hashes = [ + "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", + "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", + "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", + "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", + "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", + "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", + "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", + "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", + "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", + "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", + "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", + "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + ] +} diff --git a/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/terraform.tf b/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/terraform.tf new file mode 100644 index 00000000..238a1825 --- /dev/null +++ b/pkg/iac/terraform/state/testdata/acc/multiples_states/route53/terraform.tf @@ -0,0 +1,27 @@ +provider "aws" { + region = "us-east-1" +} + +terraform { + required_providers { + aws = { + version = "~> 3.19.0" + } + } + + backend "s3" { + bucket = "driftctl-acc-test-only" + key = "states/route53/state1" + region = "us-east-1" + } +} + +resource "random_string" "prefix" { + length = 6 + upper = false + special = false +} + +resource "aws_route53_zone" "foobar" { + name = "${random_string.prefix.result}-example.com" +} diff --git a/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/.terraform.lock.hcl b/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/.terraform.lock.hcl new file mode 100755 index 00000000..1045bc9c --- /dev/null +++ b/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/.terraform.lock.hcl @@ -0,0 +1,38 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "3.19.0" + constraints = "~> 3.19.0" + hashes = [ + "h1:+7Vi7p13+cnrxjXbfJiTimGSFR97xCaQwkkvWcreLns=", + "zh:185a5259153eb9ee4699d4be43b3d509386b473683392034319beee97d470c3b", + "zh:2d9a0a01f93e8d16539d835c02b8b6e1927b7685f4076e96cb07f7dd6944bc6c", + "zh:703f6da36b1b5f3497baa38fccaa7765fb8a2b6440344e4c97172516b49437dd", + "zh:770855565462abadbbddd98cb357d2f1a8f30f68a358cb37cbd5c072cb15b377", + "zh:8008db43149fe4345301f81e15e6d9ddb47aa5e7a31648f9b290af96ad86e92a", + "zh:8cdd27d375da6dcb7687f1fed126b7c04efce1671066802ee876dbbc9c66ec79", + "zh:be22ae185005690d1a017c1b909e0d80ab567e239b4f06ecacdba85080667c1c", + "zh:d2d02e72dbd80f607636cd6237a6c862897caabc635c7b50c0cb243d11246723", + "zh:d8f125b66a1eda2555c0f9bbdf12036a5f8d073499a22ca9e4812b68067fea31", + "zh:f5a98024c64d5d2973ff15b093725a074c0cb4afde07ef32c542e69f17ac90bc", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.1.0" + hashes = [ + "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", + "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", + "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", + "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", + "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", + "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", + "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", + "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", + "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", + "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", + "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", + "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + ] +} diff --git a/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/terraform.tf b/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/terraform.tf new file mode 100644 index 00000000..82507ef2 --- /dev/null +++ b/pkg/iac/terraform/state/testdata/acc/multiples_states/s3/terraform.tf @@ -0,0 +1,27 @@ +provider "aws" { + region = "us-east-1" +} + +terraform { + required_providers { + aws = { + version = "~> 3.19.0" + } + } + + backend "s3" { + bucket = "driftctl-acc-test-only" + key = "states/s3/state1" + region = "us-east-1" + } +} + +resource "random_string" "prefix" { + length = 6 + upper = false + special = false +} + +resource "aws_s3_bucket" "foobar" { + bucket = "${random_string.prefix.result}.driftctl-test.com" +} diff --git a/pkg/resource/aws/aws_cloudfront_distribution_test.go b/pkg/resource/aws/aws_cloudfront_distribution_test.go index 80c432a3..b5749d0f 100644 --- a/pkg/resource/aws/aws_cloudfront_distribution_test.go +++ b/pkg/resource/aws/aws_cloudfront_distribution_test.go @@ -18,7 +18,7 @@ import ( func TestAcc_Aws_CloudfrontDistribution(t *testing.T) { var mutatedDistribution string acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_cloudfront_distribution", + Paths: []string{"./testdata/acc/aws_cloudfront_distribution"}, Args: []string{"scan", "--filter", "Type=='aws_cloudfront_distribution'"}, ShouldRefreshBeforeDestroy: true, Checks: []acceptance.AccCheck{ diff --git a/pkg/resource/aws/aws_dynamodb_table_test.go b/pkg/resource/aws/aws_dynamodb_table_test.go index 2dd78370..65ee02a0 100644 --- a/pkg/resource/aws/aws_dynamodb_table_test.go +++ b/pkg/resource/aws/aws_dynamodb_table_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsDynamoDBTable(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_dynamodb_table", - Args: []string{"scan", "--filter", "Type=='aws_dynamodb_table'"}, + Paths: []string{"./testdata/acc/aws_dynamodb_table"}, + Args: []string{"scan", "--filter", "Type=='aws_dynamodb_table'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_instance_test.go b/pkg/resource/aws/aws_instance_test.go index 179c513c..73e8ed2c 100644 --- a/pkg/resource/aws/aws_instance_test.go +++ b/pkg/resource/aws/aws_instance_test.go @@ -16,8 +16,8 @@ import ( func TestAcc_AwsInstance_WithBlockDevices(t *testing.T) { var mutatedInstanceId string acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_instance", - Args: []string{"scan", "--filter", "Type=='aws_instance'"}, + Paths: []string{"./testdata/acc/aws_instance"}, + Args: []string{"scan", "--filter", "Type=='aws_instance'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_internet_gateway_test.go b/pkg/resource/aws/aws_internet_gateway_test.go index 5cdd1ccd..bb5f6e81 100644 --- a/pkg/resource/aws/aws_internet_gateway_test.go +++ b/pkg/resource/aws/aws_internet_gateway_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsInternetGateway(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_internet_gateway", - Args: []string{"scan", "--filter", "Type=='aws_internet_gateway'"}, + Paths: []string{"./testdata/acc/aws_internet_gateway"}, + Args: []string{"scan", "--filter", "Type=='aws_internet_gateway'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_nat_gateway_test.go b/pkg/resource/aws/aws_nat_gateway_test.go index 1aa44c62..b575154f 100644 --- a/pkg/resource/aws/aws_nat_gateway_test.go +++ b/pkg/resource/aws/aws_nat_gateway_test.go @@ -8,7 +8,7 @@ import ( func TestAcc_AwsNATGateway(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_nat_gateway", + Paths: []string{"./testdata/acc/aws_nat_gateway"}, // We filter on aws_eip_association too to test the middleware behavior Args: []string{"scan", "--filter", "Type=='aws_nat_gateway' || Type=='aws_eip_association'"}, Checks: []acceptance.AccCheck{ diff --git a/pkg/resource/aws/aws_route53_health_check_test.go b/pkg/resource/aws/aws_route53_health_check_test.go index a79f069d..77591055 100644 --- a/pkg/resource/aws/aws_route53_health_check_test.go +++ b/pkg/resource/aws/aws_route53_health_check_test.go @@ -16,8 +16,8 @@ import ( func TestAcc_AwsRoute53HealthCheck(t *testing.T) { var mutatedHealthCheckID string acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_route53_health_check", - Args: []string{"scan", "--filter", "Type=='aws_route53_health_check'"}, + Paths: []string{"./testdata/acc/aws_route53_health_check"}, + Args: []string{"scan", "--filter", "Type=='aws_route53_health_check'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_route53_record_test.go b/pkg/resource/aws/aws_route53_record_test.go index 4c4176f8..57debfce 100644 --- a/pkg/resource/aws/aws_route53_record_test.go +++ b/pkg/resource/aws/aws_route53_record_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsRoute53Record_WithFQDNAsId(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_route53_record", - Args: []string{"scan", "--filter", "Type=='aws_route53_record'"}, + Paths: []string{"./testdata/acc/aws_route53_record"}, + Args: []string{"scan", "--filter", "Type=='aws_route53_record'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_route_table_association_test.go b/pkg/resource/aws/aws_route_table_association_test.go index 27a7aae3..0c9ba849 100644 --- a/pkg/resource/aws/aws_route_table_association_test.go +++ b/pkg/resource/aws/aws_route_table_association_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsRouteTableAssociation(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_route_table_association", - Args: []string{"scan", "--filter", "Type=='aws_route_table_association'"}, + Paths: []string{"./testdata/acc/aws_route_table_association"}, + Args: []string{"scan", "--filter", "Type=='aws_route_table_association'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_route_table_test.go b/pkg/resource/aws/aws_route_table_test.go index 0ca2a122..ffdd93c5 100644 --- a/pkg/resource/aws/aws_route_table_test.go +++ b/pkg/resource/aws/aws_route_table_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsRouteTable(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_route_table", - Args: []string{"scan", "--filter", "Type=='aws_route_table' || Type=='aws_default_route_table'"}, + Paths: []string{"./testdata/acc/aws_route_table"}, + Args: []string{"scan", "--filter", "Type=='aws_route_table' || Type=='aws_default_route_table'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_route_test.go b/pkg/resource/aws/aws_route_test.go index f5905150..dfd911d1 100644 --- a/pkg/resource/aws/aws_route_test.go +++ b/pkg/resource/aws/aws_route_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsRoute(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_route", - Args: []string{"scan", "--filter", "Type=='aws_route'"}, + Paths: []string{"./testdata/acc/aws_route"}, + Args: []string{"scan", "--filter", "Type=='aws_route'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_s3_bucket_test.go b/pkg/resource/aws/aws_s3_bucket_test.go index 767b9f4f..79430f6d 100644 --- a/pkg/resource/aws/aws_s3_bucket_test.go +++ b/pkg/resource/aws/aws_s3_bucket_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsS3Bucket_BucketInUsEast1(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_s3_bucket", - Args: []string{"scan", "--filter", "Type=='aws_s3_bucket'"}, + Paths: []string{"./testdata/acc/aws_s3_bucket"}, + Args: []string{"scan", "--filter", "Type=='aws_s3_bucket'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_security_group_test.go b/pkg/resource/aws/aws_security_group_test.go index f5f1193e..4d8437db 100644 --- a/pkg/resource/aws/aws_security_group_test.go +++ b/pkg/resource/aws/aws_security_group_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsSecurityGroup(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_security_group", - Args: []string{"scan", "--filter", "Type=='aws_security_group' || Type=='aws_default_security_group'"}, + Paths: []string{"./testdata/acc/aws_security_group"}, + Args: []string{"scan", "--filter", "Type=='aws_security_group' || Type=='aws_default_security_group'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_sns_topic_policy_test.go b/pkg/resource/aws/aws_sns_topic_policy_test.go index f6cf9d11..d71739c1 100644 --- a/pkg/resource/aws/aws_sns_topic_policy_test.go +++ b/pkg/resource/aws/aws_sns_topic_policy_test.go @@ -12,8 +12,8 @@ import ( func TestAcc_AwsSNSTopicPolicy(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_sns_topic_policy", - Args: []string{"scan", "--filter", "Type=='aws_sns_topic' || Type=='aws_sns_topic_policy'"}, + Paths: []string{"./testdata/acc/aws_sns_topic_policy"}, + Args: []string{"scan", "--filter", "Type=='aws_sns_topic' || Type=='aws_sns_topic_policy'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_sns_topic_subscription_test.go b/pkg/resource/aws/aws_sns_topic_subscription_test.go index b3656e79..fcbfefb5 100644 --- a/pkg/resource/aws/aws_sns_topic_subscription_test.go +++ b/pkg/resource/aws/aws_sns_topic_subscription_test.go @@ -12,8 +12,8 @@ import ( func TestAcc_AwsSNSTopicSubscription(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_sns_topic_subscription", - Args: []string{"scan", "--filter", "Type=='aws_sns_topic_subscription'"}, + Paths: []string{"./testdata/acc/aws_sns_topic_subscription"}, + Args: []string{"scan", "--filter", "Type=='aws_sns_topic_subscription'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_sns_topic_test.go b/pkg/resource/aws/aws_sns_topic_test.go index 7050316a..e182a0d6 100644 --- a/pkg/resource/aws/aws_sns_topic_test.go +++ b/pkg/resource/aws/aws_sns_topic_test.go @@ -22,8 +22,8 @@ import ( func TestAcc_AwsSNSTopic(t *testing.T) { var mutatedTopicArn string acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_sns_topic", - Args: []string{"scan", "--filter", "Type=='aws_sns_topic'"}, + Paths: []string{"./testdata/acc/aws_sns_topic"}, + Args: []string{"scan", "--filter", "Type=='aws_sns_topic'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_sqs_queue_policy_test.go b/pkg/resource/aws/aws_sqs_queue_policy_test.go index a2239793..9e059d6b 100644 --- a/pkg/resource/aws/aws_sqs_queue_policy_test.go +++ b/pkg/resource/aws/aws_sqs_queue_policy_test.go @@ -13,8 +13,8 @@ import ( func TestAcc_AwsSqsQueuePolicy(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_sqs_queue_policy", - Args: []string{"scan", "--filter", "Type=='aws_sqs_queue_policy'"}, + Paths: []string{"./testdata/acc/aws_sqs_queue_policy"}, + Args: []string{"scan", "--filter", "Type=='aws_sqs_queue_policy'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_sqs_queue_test.go b/pkg/resource/aws/aws_sqs_queue_test.go index 1cca2894..7a09458a 100644 --- a/pkg/resource/aws/aws_sqs_queue_test.go +++ b/pkg/resource/aws/aws_sqs_queue_test.go @@ -20,8 +20,8 @@ import ( func TestAcc_AwsSqsQueue(t *testing.T) { var mutatedQueue string acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_sqs_queue", - Args: []string{"scan", "--filter", "Type=='aws_sqs_queue'"}, + Paths: []string{"./testdata/acc/aws_sqs_queue"}, + Args: []string{"scan", "--filter", "Type=='aws_sqs_queue'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/aws/aws_subnet_test.go b/pkg/resource/aws/aws_subnet_test.go index 706b4c62..cb07d805 100644 --- a/pkg/resource/aws/aws_subnet_test.go +++ b/pkg/resource/aws/aws_subnet_test.go @@ -8,8 +8,8 @@ import ( func TestAcc_AwsSubnet(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/aws_subnet", - Args: []string{"scan", "--filter", "Type=='aws_subnet' || Type=='aws_default_subnet'"}, + Paths: []string{"./testdata/acc/aws_subnet"}, + Args: []string{"scan", "--filter", "Type=='aws_subnet' || Type=='aws_default_subnet'"}, Checks: []acceptance.AccCheck{ { Env: map[string]string{ diff --git a/pkg/resource/github/github_repository_test.go b/pkg/resource/github/github_repository_test.go index d4d6f203..18985e1a 100644 --- a/pkg/resource/github/github_repository_test.go +++ b/pkg/resource/github/github_repository_test.go @@ -8,7 +8,7 @@ import ( func TestAcc_Github_Repository(t *testing.T) { acceptance.Run(t, acceptance.AccTestCase{ - Path: "./testdata/acc/github_repository", + Paths: []string{"./testdata/acc/github_repository"}, Args: []string{ "scan", "--to", "github+tf", diff --git a/test/acceptance/result.go b/test/acceptance/result.go index af526ff6..82e87179 100644 --- a/test/acceptance/result.go +++ b/test/acceptance/result.go @@ -93,6 +93,10 @@ func (r *ScanResult) AssertManagedCount(count int) { r.Equal(count, len(r.Managed())) } +func (r *ScanResult) AssertUnmanagedCount(count int) { + r.Equal(count, len(r.Unmanaged())) +} + func (r ScanResult) AssertInfrastructureIsInSync() { r.Equal( true, diff --git a/test/acceptance/testing.go b/test/acceptance/testing.go index 1fae5fd6..c3adbf6e 100644 --- a/test/acceptance/testing.go +++ b/test/acceptance/testing.go @@ -38,29 +38,32 @@ type AccCheck struct { } type AccTestCase struct { - Path string + Paths []string Args []string OnStart func() OnEnd func() Checks []AccCheck tmpResultFilePath string originalEnv []string - tf *tfexec.Terraform + tf map[string]*tfexec.Terraform ShouldRefreshBeforeDestroy bool } func (c *AccTestCase) initTerraformExecutor() error { - execPath, err := tfinstall.LookPath().ExecPath(context.Background()) - if err != nil { - return err - } - c.tf, err = tfexec.NewTerraform(c.Path, execPath) - if err != nil { - return err - } - env := c.resolveTerraformEnv() - if err := c.tf.SetEnv(env); err != nil { - return err + c.tf = make(map[string]*tfexec.Terraform, 1) + for _, path := range c.Paths { + execPath, err := tfinstall.LookPath().ExecPath(context.Background()) + if err != nil { + return err + } + c.tf[path], err = tfexec.NewTerraform(path, execPath) + if err != nil { + return err + } + env := c.resolveTerraformEnv() + if err := c.tf[path].SetEnv(env); err != nil { + return err + } } return nil } @@ -81,8 +84,8 @@ func (c *AccTestCase) validate() error { return fmt.Errorf("checks attribute must be defined") } - if c.Path == "" { - return fmt.Errorf("path attribute must be defined") + if len(c.Paths) < 1 { + return fmt.Errorf("Paths attribute must be defined") } for _, arg := range c.Args { @@ -141,28 +144,40 @@ func (c *AccTestCase) terraformInit() error { if err := c.initTerraformExecutor(); err != nil { return err } - _, err := os.Stat(path.Join(c.Path, ".terraform")) - if os.IsNotExist(err) { - logrus.Debug("Running terraform init ...") - stderr := new(bytes.Buffer) - c.tf.SetStderr(stderr) - if err := c.tf.Init(context.Background()); err != nil { - return errors.Wrap(err, stderr.String()) + for _, p := range c.Paths { + _, err := os.Stat(path.Join(p, ".terraform")) + if os.IsNotExist(err) { + logrus.WithFields(logrus.Fields{ + "path": p, + }).Debug("Running terraform init ...") + stderr := new(bytes.Buffer) + c.tf[p].SetStderr(stderr) + if err := c.tf[p].Init(context.Background()); err != nil { + return errors.Wrap(err, stderr.String()) + } + logrus.WithFields(logrus.Fields{ + "path": p, + }).Debug("Terraform init done") } - logrus.Debug("Terraform init done") } return nil } func (c *AccTestCase) terraformApply() error { - logrus.Debug("Running terraform apply ...") - stderr := new(bytes.Buffer) - c.tf.SetStderr(stderr) - if err := c.tf.Apply(context.Background()); err != nil { - return errors.Wrap(err, stderr.String()) + for _, p := range c.Paths { + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Running terraform apply ...") + stderr := new(bytes.Buffer) + c.tf[p].SetStderr(stderr) + if err := c.tf[p].Apply(context.Background()); err != nil { + return errors.Wrap(err, stderr.String()) + } + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Terraform apply done") } - logrus.Debug("Terraform apply done") return nil } @@ -174,25 +189,37 @@ func (c *AccTestCase) terraformDestroy() error { } } - logrus.Debug("Running terraform destroy ...") - stderr := new(bytes.Buffer) - c.tf.SetStderr(stderr) - if err := c.tf.Destroy(context.Background()); err != nil { - return errors.Wrap(err, stderr.String()) + for _, p := range c.Paths { + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Running terraform destroy ...") + stderr := new(bytes.Buffer) + c.tf[p].SetStderr(stderr) + if err := c.tf[p].Destroy(context.Background()); err != nil { + return errors.Wrap(err, stderr.String()) + } + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Terraform destroy done") } - logrus.Debug("Terraform destroy done") return nil } func (c *AccTestCase) terraformRefresh() error { - logrus.Debug("Running terraform refresh ...") - stderr := new(bytes.Buffer) - c.tf.SetStderr(stderr) - if err := c.tf.Refresh(context.Background()); err != nil { - return errors.Wrap(err, stderr.String()) + for _, p := range c.Paths { + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Running terraform refresh ...") + stderr := new(bytes.Buffer) + c.tf[p].SetStderr(stderr) + if err := c.tf[p].Refresh(context.Background()); err != nil { + return errors.Wrap(err, stderr.String()) + } + logrus.WithFields(logrus.Fields{ + "p": p, + }).Debug("Terraform refresh done") } - logrus.Debug("Terraform refresh done") return nil } @@ -259,7 +286,16 @@ func Run(t *testing.T, c AccTestCase) { } if c.OnStart != nil { + c.useTerraformEnv() c.OnStart() + if c.OnEnd != nil { + defer func() { + c.useTerraformEnv() + c.OnEnd() + c.restoreEnv() + }() + } + c.restoreEnv() } // Disable terraform version checks @@ -295,8 +331,21 @@ func Run(t *testing.T, c AccTestCase) { } if c.Args != nil { c.Args = append([]string{""}, c.Args...) + isFromSet := false + for _, arg := range c.Args { + if arg == "--from" || arg == "-f" { + isFromSet = true + break + } + } + if !isFromSet { + for _, p := range c.Paths { + c.Args = append(c.Args, + "--from", fmt.Sprintf("tfstate://%s", path.Join(p, "terraform.tfstate")), + ) + } + } c.Args = append(c.Args, - "--from", fmt.Sprintf("tfstate://%s", path.Join(c.Path, "terraform.tfstate")), "--output", fmt.Sprintf("json://%s", c.getResultFilePath()), ) } @@ -328,9 +377,6 @@ func Run(t *testing.T, c AccTestCase) { check.PostExec() } } - if c.OnEnd != nil { - c.OnEnd() - } } func RetryFor(timeout time.Duration, f func(c chan struct{}) error) error {