Merge pull request #435 from cloudskiff/test/strictMode
Add a extra test case for the strict modemain
commit
3bbe363071
|
@ -5,7 +5,6 @@ import (
|
|||
"testing"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/r3labs/diff/v2"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
@ -13,7 +12,7 @@ import (
|
|||
"github.com/cloudskiff/driftctl/pkg"
|
||||
"github.com/cloudskiff/driftctl/pkg/alerter"
|
||||
"github.com/cloudskiff/driftctl/pkg/analyser"
|
||||
filter2 "github.com/cloudskiff/driftctl/pkg/filter"
|
||||
"github.com/cloudskiff/driftctl/pkg/filter"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/github"
|
||||
|
@ -32,9 +31,9 @@ type TestCase struct {
|
|||
provider *TestProvider
|
||||
stateResources []resource.Resource
|
||||
remoteResources []resource.Resource
|
||||
filter string
|
||||
mocks func(factory resource.ResourceFactory)
|
||||
assert func(result *test.ScanResult, err error)
|
||||
options *pkg.ScanOptions
|
||||
}
|
||||
|
||||
type TestCases []TestCase
|
||||
|
@ -67,24 +66,13 @@ func runTest(t *testing.T, cases TestCases) {
|
|||
remoteSupplier := &resource.MockSupplier{}
|
||||
remoteSupplier.On("Resources").Return(c.remoteResources, nil)
|
||||
|
||||
var filter *jmespath.JMESPath
|
||||
if c.filter != "" {
|
||||
f, err := filter2.BuildExpression(c.filter)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", c.filter, err)
|
||||
}
|
||||
filter = f
|
||||
}
|
||||
|
||||
resourceFactory := &terraform.MockResourceFactory{}
|
||||
|
||||
if c.mocks != nil {
|
||||
c.mocks(resourceFactory)
|
||||
}
|
||||
|
||||
driftctl := pkg.NewDriftCTL(remoteSupplier, stateSupplier, testAlerter, resourceFactory, &pkg.ScanOptions{
|
||||
Filter: filter,
|
||||
}, repo)
|
||||
driftctl := pkg.NewDriftCTL(remoteSupplier, stateSupplier, testAlerter, resourceFactory, c.options, repo)
|
||||
|
||||
analysis, err := driftctl.Run()
|
||||
|
||||
|
@ -116,6 +104,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertInfrastructureIsInSync()
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have deleted resource",
|
||||
|
@ -126,6 +117,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertDeletedCount(1)
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have unmanaged resource",
|
||||
|
@ -136,6 +130,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertUnmanagedCount(1)
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have changes of field update",
|
||||
|
@ -163,6 +160,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have changes on computed field",
|
||||
|
@ -190,6 +190,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
Computed: true,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have changes of deleted field",
|
||||
|
@ -218,6 +221,9 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should have changes of added field",
|
||||
|
@ -246,6 +252,168 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should ignore default AWS IAM role when strict mode is disabled",
|
||||
stateResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "role-policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
},
|
||||
remoteResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-1",
|
||||
Path: func(p string) *string { return &p }("/aws-service-role/test"),
|
||||
},
|
||||
&aws.AwsIamRolePolicy{
|
||||
Id: "role-policy-test-1",
|
||||
Role: func(p string) *string { return &p }("role-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "role-policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicyAttachment{
|
||||
Id: "policy-attachment-test-1",
|
||||
PolicyArn: func(p string) *string { return &p }("policy-test-1"),
|
||||
Users: func(p []string) *[]string { return &p }([]string{}),
|
||||
Roles: func(p []string) *[]string { return &p }([]string{"role-test-1"}),
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-2",
|
||||
Path: func(p string) *string { return &p }("/not-aws-service-role/test"),
|
||||
},
|
||||
},
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(2)
|
||||
result.AssertUnmanagedCount(1)
|
||||
result.AssertDeletedCount(0)
|
||||
result.AssertDriftCountTotal(0)
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{
|
||||
StrictMode: false,
|
||||
}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should not ignore default AWS IAM role when strict mode is enabled",
|
||||
stateResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
},
|
||||
remoteResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-1",
|
||||
Path: func(p string) *string { return &p }("/aws-service-role/test"),
|
||||
},
|
||||
&aws.AwsIamRolePolicy{
|
||||
Id: "role-policy-test-1",
|
||||
Role: func(p string) *string { return &p }("role-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicyAttachment{
|
||||
Id: "policy-attachment-test-1",
|
||||
PolicyArn: func(p string) *string { return &p }("policy-test-1"),
|
||||
Users: func(p []string) *[]string { return &p }([]string{}),
|
||||
Roles: func(p []string) *[]string { return &p }([]string{"role-test-1"}),
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-2",
|
||||
Path: func(p string) *string { return &p }("/not-aws-service-role/test"),
|
||||
},
|
||||
},
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(2)
|
||||
result.AssertUnmanagedCount(4)
|
||||
result.AssertDeletedCount(0)
|
||||
result.AssertDriftCountTotal(0)
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
return &pkg.ScanOptions{
|
||||
StrictMode: true,
|
||||
}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "we should not ignore default AWS IAM role when strict mode is enabled and a filter is specified",
|
||||
stateResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
},
|
||||
remoteResources: []resource.Resource{
|
||||
testresource.FakeResource{
|
||||
Id: "fake",
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-1",
|
||||
Path: func(p string) *string { return &p }("/aws-service-role/test"),
|
||||
},
|
||||
&aws.AwsIamRolePolicy{
|
||||
Id: "role-policy-test-1",
|
||||
Role: func(p string) *string { return &p }("role-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicy{
|
||||
Id: "policy-test-1",
|
||||
Arn: func(p string) *string { return &p }("policy-test-1"),
|
||||
},
|
||||
&aws.AwsIamPolicyAttachment{
|
||||
Id: "policy-attachment-test-1",
|
||||
PolicyArn: func(p string) *string { return &p }("policy-test-1"),
|
||||
Users: func(p []string) *[]string { return &p }([]string{}),
|
||||
Roles: func(p []string) *[]string { return &p }([]string{"role-test-1"}),
|
||||
},
|
||||
&aws.AwsIamRole{
|
||||
Id: "role-test-2",
|
||||
Path: func(p string) *string { return &p }("/not-aws-service-role/test"),
|
||||
},
|
||||
},
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertCoverage(0)
|
||||
result.AssertInfrastructureIsNotSync()
|
||||
result.AssertManagedCount(0)
|
||||
result.AssertUnmanagedCount(1)
|
||||
result.AssertDeletedCount(0)
|
||||
result.AssertDriftCountTotal(0)
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Id=='role-test-1'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{
|
||||
Filter: f,
|
||||
StrictMode: true,
|
||||
}
|
||||
}(t),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -267,11 +435,19 @@ func TestDriftctlRun_BasicFilter(t *testing.T) {
|
|||
Type: "filtered",
|
||||
},
|
||||
},
|
||||
filter: "Type=='filtered'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertUnmanagedCount(1)
|
||||
result.AssertResourceUnmanaged("res2", "filtered")
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='filtered'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test filtering on Id",
|
||||
|
@ -286,11 +462,19 @@ func TestDriftctlRun_BasicFilter(t *testing.T) {
|
|||
Type: "filtered",
|
||||
},
|
||||
},
|
||||
filter: "Id=='res2'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertUnmanagedCount(1)
|
||||
result.AssertResourceUnmanaged("res2", "filtered")
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Id=='res2'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test filtering on attribute",
|
||||
|
@ -311,11 +495,19 @@ func TestDriftctlRun_BasicFilter(t *testing.T) {
|
|||
Type: "not-filtered",
|
||||
},
|
||||
},
|
||||
filter: "Attr.test_field=='value to filter on'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertUnmanagedCount(1)
|
||||
result.AssertResourceUnmanaged("res1", "filtered")
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Attr.test_field=='value to filter on'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -362,7 +554,6 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_s3_bucket_policy").Times(1).Return(&foo, nil)
|
||||
},
|
||||
filter: "Type=='aws_s3_bucket_policy' && Attr.bucket=='foo'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(1)
|
||||
result.AssertResourceHasDrift("foo", "aws_s3_bucket_policy", analyser.Change{
|
||||
|
@ -375,6 +566,15 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_s3_bucket_policy' && Attr.bucket=='foo'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test instance block device middleware",
|
||||
|
@ -478,7 +678,6 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_ebs_volume").Times(1).Return(&bar, nil)
|
||||
},
|
||||
filter: "Type=='aws_ebs_volume' && Attr.availability_zone=='us-east-1'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(2)
|
||||
result.AssertResourceHasDrift("vol-02862d9b39045a3a4", "aws_ebs_volume", analyser.Change{
|
||||
|
@ -500,6 +699,15 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
Computed: true,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_ebs_volume' && Attr.availability_zone=='us-east-1'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test route table expander middleware",
|
||||
|
@ -613,11 +821,19 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_route").Times(1).Return(&bar, nil)
|
||||
},
|
||||
filter: "Type=='aws_route' && Attr.gateway_id=='igw-07b7844a8fd17a638'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(2)
|
||||
result.AssertInfrastructureIsInSync()
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_route' && Attr.gateway_id=='igw-07b7844a8fd17a638'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test sns topic policy expander middleware",
|
||||
|
@ -657,7 +873,6 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_sns_topic_policy").Times(1).Return(&foo, nil)
|
||||
},
|
||||
filter: "Type=='aws_sns_topic_policy' && Attr.arn=='arn'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(1)
|
||||
result.AssertResourceHasDrift("foo", "aws_sns_topic_policy", analyser.Change{
|
||||
|
@ -670,6 +885,15 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_sns_topic_policy' && Attr.arn=='arn'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test sqs queue policy expander middleware",
|
||||
|
@ -708,7 +932,6 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_sqs_queue_policy").Times(1).Return(&foo, nil)
|
||||
},
|
||||
filter: "Type=='aws_sqs_queue_policy' && Attr.queue_url=='foo'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(1)
|
||||
result.AssertResourceHasDrift("foo", "aws_sqs_queue_policy", analyser.Change{
|
||||
|
@ -721,6 +944,15 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
Computed: false,
|
||||
})
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_sqs_queue_policy' && Attr.queue_url=='foo'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
{
|
||||
name: "test security group rule sanitizer middleware",
|
||||
|
@ -1098,11 +1330,19 @@ func TestDriftctlRun_Middlewares(t *testing.T) {
|
|||
})
|
||||
}), "aws_security_group_rule").Times(1).Return(&rule4, nil)
|
||||
},
|
||||
filter: "Type=='aws_security_group_rule' && Attr.security_group_id=='sg-0254c038e32f25530'",
|
||||
assert: func(result *test.ScanResult, err error) {
|
||||
result.AssertManagedCount(7)
|
||||
result.AssertInfrastructureIsInSync()
|
||||
},
|
||||
options: func(t *testing.T) *pkg.ScanOptions {
|
||||
filterStr := "Type=='aws_security_group_rule' && Attr.security_group_id=='sg-0254c038e32f25530'"
|
||||
f, err := filter.BuildExpression(filterStr)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to build filter expression: %s\n%s", filterStr, err)
|
||||
}
|
||||
|
||||
return &pkg.ScanOptions{Filter: f}
|
||||
}(t),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ func (r *ScanResult) AssertResourceHasNoDrift(id, ty string) {
|
|||
}
|
||||
|
||||
func (r *ScanResult) AssertCoverage(expected int) {
|
||||
r.Equal(expected, r.Coverage)
|
||||
r.Equal(expected, r.Coverage())
|
||||
}
|
||||
|
||||
func (r *ScanResult) AssertDriftCountTotal(count int) {
|
||||
|
@ -110,3 +110,17 @@ func (r ScanResult) AssertInfrastructureIsInSync() {
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (r ScanResult) AssertInfrastructureIsNotSync() {
|
||||
r.Equal(
|
||||
false,
|
||||
r.Analysis.IsSync(),
|
||||
fmt.Sprintf(
|
||||
"Infrastructure is in sync: %+v\nUnmanaged:\n%+v\nDeleted:\n%+v\nDifferences:\n%+v\n",
|
||||
r.Analysis.Summary(),
|
||||
r.Analysis.Unmanaged(),
|
||||
r.Analysis.Deleted(),
|
||||
r.Analysis.Differences(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue