2021-04-21 16:51:58 +00:00
|
|
|
package output
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"path"
|
|
|
|
"testing"
|
2021-06-08 15:14:28 +00:00
|
|
|
"time"
|
2021-04-21 16:51:58 +00:00
|
|
|
|
2021-06-07 17:26:39 +00:00
|
|
|
"github.com/r3labs/diff/v2"
|
2021-12-06 13:29:39 +00:00
|
|
|
"github.com/snyk/driftctl/pkg/resource"
|
2021-04-21 16:51:58 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2021-12-06 13:29:39 +00:00
|
|
|
"github.com/snyk/driftctl/pkg/analyser"
|
|
|
|
"github.com/snyk/driftctl/test/goldenfile"
|
2021-04-21 16:51:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestHTML_Write(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
goldenfile string
|
2021-06-07 17:26:39 +00:00
|
|
|
analysis func() *analyser.Analysis
|
2021-04-21 16:51:58 +00:00
|
|
|
err error
|
|
|
|
}{
|
2021-06-08 15:14:28 +00:00
|
|
|
{
|
|
|
|
name: "test html output when there's no resources",
|
|
|
|
goldenfile: "output_empty.html",
|
|
|
|
analysis: func() *analyser.Analysis {
|
|
|
|
a := &analyser.Analysis{}
|
2021-06-10 13:25:54 +00:00
|
|
|
a.Date = time.Date(2021, 06, 10, 0, 0, 0, 0, &time.Location{})
|
2021-07-29 09:50:35 +00:00
|
|
|
a.ProviderName = "AWS"
|
|
|
|
a.ProviderVersion = "3.19.0"
|
2021-06-08 15:14:28 +00:00
|
|
|
return a
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "test html output when infrastructure is in sync",
|
|
|
|
goldenfile: "output_sync.html",
|
|
|
|
analysis: func() *analyser.Analysis {
|
|
|
|
a := &analyser.Analysis{}
|
2021-06-10 13:25:54 +00:00
|
|
|
a.Date = time.Date(2021, 06, 10, 0, 0, 0, 0, &time.Location{})
|
2021-06-08 15:14:28 +00:00
|
|
|
a.Duration = 72 * time.Second
|
|
|
|
a.AddManaged(
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-08 15:14:28 +00:00
|
|
|
Id: "deleted-id-3",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
},
|
|
|
|
)
|
2021-07-29 09:50:35 +00:00
|
|
|
a.ProviderName = "AWS"
|
|
|
|
a.ProviderVersion = "3.19.0"
|
2021-06-08 15:14:28 +00:00
|
|
|
return a
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
2021-04-21 16:51:58 +00:00
|
|
|
{
|
|
|
|
name: "test html output",
|
|
|
|
goldenfile: "output.html",
|
2021-06-07 17:26:39 +00:00
|
|
|
analysis: func() *analyser.Analysis {
|
|
|
|
a := fakeAnalysisWithAlerts()
|
2021-06-10 13:25:54 +00:00
|
|
|
a.Date = time.Date(2021, 06, 10, 0, 0, 0, 0, &time.Location{})
|
2021-06-08 15:14:28 +00:00
|
|
|
a.Duration = 91 * time.Second
|
2021-08-24 13:30:55 +00:00
|
|
|
a.AddManaged(
|
|
|
|
&resource.Resource{
|
|
|
|
Id: "diff-id-2",
|
|
|
|
Type: "aws_diff_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://state.tfstate",
|
|
|
|
Name: "diff-id-2",
|
|
|
|
Module: "module",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&resource.Resource{
|
|
|
|
Id: "diff-id-3",
|
|
|
|
Type: "aws_diff_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate+s3://state2.tfstate",
|
|
|
|
Name: "b",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
2021-06-07 17:26:39 +00:00
|
|
|
a.AddDeleted(
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "deleted-id-3",
|
|
|
|
Type: "aws_deleted_resource",
|
2021-08-25 12:50:32 +00:00
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://deleted/terraform.tfstate",
|
|
|
|
Name: "deleted-id-3",
|
|
|
|
},
|
2021-06-07 17:26:39 +00:00
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "deleted-id-4",
|
|
|
|
Type: "aws_deleted_resource",
|
2021-08-25 12:50:32 +00:00
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://deleted/terraform.tfstate",
|
|
|
|
Name: "deleted-id-3",
|
|
|
|
},
|
2021-06-07 17:26:39 +00:00
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "deleted-id-5",
|
|
|
|
Type: "aws_deleted_resource",
|
2021-08-25 12:50:32 +00:00
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://deleted/terraform.tfstate",
|
|
|
|
Name: "deleted-id-3",
|
|
|
|
Module: "module-1",
|
|
|
|
},
|
2021-06-07 17:26:39 +00:00
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "deleted-id-6",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
a.AddUnmanaged(
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "unmanaged-id-3",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "unmanaged-id-4",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
&resource.Resource{
|
2021-06-07 17:26:39 +00:00
|
|
|
Id: "unmanaged-id-5",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
},
|
|
|
|
)
|
2021-07-30 14:13:36 +00:00
|
|
|
a.AddDifference(analyser.Difference{
|
2021-08-09 14:03:04 +00:00
|
|
|
Res: &resource.Resource{
|
2021-07-30 14:13:36 +00:00
|
|
|
Id: "diff-id-2",
|
|
|
|
Type: "aws_diff_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://state.tfstate",
|
2021-08-24 13:30:55 +00:00
|
|
|
Name: "diff-id-2",
|
2021-07-30 14:13:36 +00:00
|
|
|
Module: "module",
|
2021-06-10 16:35:13 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
}, Changelog: []analyser.Change{
|
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.DELETE,
|
|
|
|
Path: []string{"path", "to", "fields", "0"},
|
|
|
|
From: "value",
|
|
|
|
To: nil,
|
|
|
|
},
|
2021-06-10 16:35:13 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.UPDATE,
|
|
|
|
Path: []string{"path", "to", "fields", "1"},
|
|
|
|
From: 12,
|
|
|
|
To: "12",
|
|
|
|
},
|
2021-06-10 16:35:13 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.DELETE,
|
|
|
|
Path: []string{"group_ids"},
|
|
|
|
From: []string{"a071314398026"},
|
|
|
|
To: nil,
|
|
|
|
},
|
2021-06-11 16:43:51 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
{
|
2021-08-23 14:17:01 +00:00
|
|
|
JsonString: true,
|
2021-07-30 14:13:36 +00:00
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.UPDATE,
|
2021-08-23 14:17:01 +00:00
|
|
|
Path: []string{"policy"},
|
|
|
|
From: `{"Statement":[{"Action":["s3:GetObjectVersion"],"Effect":"Allow","Principal":"*","Resource":"arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/*","Sid":"PublicRead"}],"Version":"2012-10-17"}`,
|
|
|
|
To: `{"Statement":[{"Action":["*"],"Effect":"Deny","Principal":"*","Resource":"arn:aws:s3:::tmxxrn.foobar.driftctl-test.com/b/*","Sid":"PublicReadWrite"},{"Effect":"Deny","Sid":"PublicReadWrite"}],"Version":"2021-10-17","Test":[]}`,
|
2021-07-30 14:13:36 +00:00
|
|
|
},
|
2021-06-10 16:35:13 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.CREATE,
|
|
|
|
Path: []string{"Tags", "0", "Name"},
|
|
|
|
From: nil,
|
|
|
|
To: "test",
|
|
|
|
},
|
2021-06-07 17:26:39 +00:00
|
|
|
},
|
2021-07-30 14:13:36 +00:00
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.UPDATE,
|
|
|
|
Path: []string{"InstanceInitiatedShutdownBehavior"},
|
|
|
|
From: "",
|
|
|
|
To: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}})
|
2021-07-29 09:50:35 +00:00
|
|
|
a.ProviderName = "AWS"
|
|
|
|
a.ProviderVersion = "3.19.0"
|
2021-06-07 17:26:39 +00:00
|
|
|
return a
|
2021-04-21 16:51:58 +00:00
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
2021-08-24 09:41:45 +00:00
|
|
|
{
|
|
|
|
name: "test html output when coverage is 100",
|
|
|
|
goldenfile: "output_coverage_100.html",
|
|
|
|
analysis: func() *analyser.Analysis {
|
|
|
|
a := &analyser.Analysis{}
|
|
|
|
a.Date = time.Date(2021, 06, 10, 0, 0, 0, 0, &time.Location{})
|
|
|
|
a.Duration = 91 * time.Second
|
|
|
|
a.AddManaged(
|
|
|
|
&resource.Resource{
|
|
|
|
Id: "resource-id-1",
|
|
|
|
Type: "aws_resource",
|
2021-08-24 13:30:55 +00:00
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://state.tfstate",
|
|
|
|
Module: "module",
|
|
|
|
Name: "name",
|
|
|
|
},
|
2021-08-24 09:41:45 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
a.AddDifference(analyser.Difference{
|
|
|
|
Res: &resource.Resource{
|
|
|
|
Id: "resource-id-1",
|
|
|
|
Type: "aws_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
State: "tfstate://state.tfstate",
|
|
|
|
Module: "module",
|
|
|
|
Name: "name",
|
|
|
|
},
|
|
|
|
}, Changelog: []analyser.Change{
|
|
|
|
{
|
|
|
|
Change: diff.Change{
|
|
|
|
Type: diff.DELETE,
|
|
|
|
Path: []string{"path", "to", "fields", "0"},
|
|
|
|
From: "value",
|
|
|
|
To: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}})
|
|
|
|
a.ProviderName = "AWS"
|
|
|
|
a.ProviderVersion = "3.19.0"
|
|
|
|
return a
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
2021-04-21 16:51:58 +00:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
tempDir := t.TempDir()
|
|
|
|
tempFile, err := ioutil.TempFile(tempDir, "result")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
c := NewHTML(tempFile.Name())
|
|
|
|
|
2021-06-07 17:26:39 +00:00
|
|
|
err = c.Write(tt.analysis())
|
2021-04-21 16:51:58 +00:00
|
|
|
if tt.err != nil {
|
|
|
|
assert.EqualError(t, err, tt.err.Error())
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2021-04-22 16:21:00 +00:00
|
|
|
got, err := ioutil.ReadFile(tempFile.Name())
|
2021-04-21 16:51:58 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedFilePath := path.Join("./testdata/", tt.goldenfile)
|
|
|
|
if *goldenfile.Update == tt.goldenfile {
|
2021-04-22 16:21:00 +00:00
|
|
|
if err := ioutil.WriteFile(expectedFilePath, got, 0600); err != nil {
|
2021-04-21 16:51:58 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expected, err := ioutil.ReadFile(expectedFilePath)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2021-06-01 09:38:47 +00:00
|
|
|
assert.Equal(t, string(expected), string(got))
|
2021-04-21 16:51:58 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-06-07 13:21:57 +00:00
|
|
|
|
|
|
|
func TestHTML_DistinctResourceTypes(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
2021-08-09 14:03:04 +00:00
|
|
|
resources []*resource.Resource
|
2021-06-07 13:21:57 +00:00
|
|
|
value []string
|
|
|
|
}{
|
|
|
|
{
|
2021-08-26 10:12:29 +00:00
|
|
|
name: "should return empty array",
|
2021-08-09 14:03:04 +00:00
|
|
|
resources: []*resource.Resource{},
|
2021-06-07 13:21:57 +00:00
|
|
|
value: []string{},
|
|
|
|
},
|
|
|
|
{
|
2021-08-26 10:12:29 +00:00
|
|
|
name: "should return distinct list of resource types",
|
2021-08-09 14:03:04 +00:00
|
|
|
resources: []*resource.Resource{
|
|
|
|
{
|
2021-06-07 13:21:57 +00:00
|
|
|
Id: "deleted-id-1",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
{
|
2021-06-07 13:21:57 +00:00
|
|
|
Id: "unmanaged-id-1",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
{
|
2021-06-07 13:21:57 +00:00
|
|
|
Id: "unmanaged-id-2",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
{
|
2021-06-07 13:21:57 +00:00
|
|
|
Id: "diff-id-1",
|
|
|
|
Type: "aws_diff_resource",
|
|
|
|
},
|
2021-08-09 14:03:04 +00:00
|
|
|
{
|
2021-06-07 13:21:57 +00:00
|
|
|
Id: "deleted-id-2",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
value: []string{"aws_deleted_resource", "aws_unmanaged_resource", "aws_diff_resource"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got := distinctResourceTypes(tt.resources)
|
|
|
|
assert.Equal(t, tt.value, got)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-08-24 13:30:55 +00:00
|
|
|
|
|
|
|
func TestHTML_DistinctIaCSources(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
resources []*resource.Resource
|
|
|
|
value []string
|
|
|
|
}{
|
|
|
|
{
|
2021-08-26 10:12:29 +00:00
|
|
|
name: "should return empty array",
|
2021-08-24 13:30:55 +00:00
|
|
|
resources: []*resource.Resource{},
|
|
|
|
value: []string{},
|
|
|
|
},
|
|
|
|
{
|
2021-08-26 10:12:29 +00:00
|
|
|
name: "should return distinct list of iac sources",
|
2021-08-24 13:30:55 +00:00
|
|
|
resources: []*resource.Resource{
|
|
|
|
{
|
|
|
|
Id: "deleted-id-1",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
Module: "module",
|
|
|
|
Name: "test",
|
|
|
|
State: "tfstate://terraform.tfstate",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Id: "unmanaged-id-1",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
Module: "module",
|
|
|
|
Name: "test",
|
|
|
|
State: "tfstate://terraform2.tfstate",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Id: "unmanaged-id-2",
|
|
|
|
Type: "aws_unmanaged_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
Module: "module",
|
|
|
|
Name: "test",
|
|
|
|
State: "tfstate+s3://test/terraform.tfstate",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Id: "diff-id-1",
|
|
|
|
Type: "aws_diff_resource",
|
|
|
|
Source: &resource.TerraformStateSource{
|
|
|
|
Module: "module",
|
|
|
|
Name: "test",
|
|
|
|
State: "tfstate://terraform.tfstate",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Id: "deleted-id-2",
|
|
|
|
Type: "aws_deleted_resource",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
value: []string{"tfstate://terraform.tfstate", "tfstate://terraform2.tfstate", "tfstate+s3://test/terraform.tfstate"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got := distinctIaCSources(tt.resources)
|
|
|
|
assert.Equal(t, tt.value, got)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|