-
Notifications
You must be signed in to change notification settings - Fork 161
/
Copy pathtest_diff.go
156 lines (137 loc) · 4 KB
/
test_diff.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package test
import (
"encoding/json"
"strings"
"testing"
"github.com/snyk/driftctl/enumeration/terraform"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/r3labs/diff/v2"
"github.com/snyk/driftctl/enumeration/resource"
"github.com/snyk/driftctl/test/goldenfile"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
ctyjson "github.com/zclconf/go-cty/cty/json"
)
// That method is used to compare the result of the enumeration with the golden file.
// That method does not use cty and types from the terraform provider to deserialize resources.
// Some resources returned by the enumeration may have missing fields, and if we use cty deserialization we're
// gonna recreate those missing fields to respect the schema.
func TestAgainstGoldenFileNoCty(
got []*resource.Resource,
ty string,
dirName string,
_ terraform.TerraformProvider,
_ *resource.Deserializer,
shouldUpdate bool,
tt *testing.T) {
var expectedResources []*resource.Resource
// update golden file
if shouldUpdate {
attributes := make([]*resource.Attributes, 0, len(got))
for _, res := range got {
attributes = append(attributes, res.Attributes())
}
fileContent, err := json.MarshalIndent(attributes, "", " ")
if err != nil {
panic(err)
}
goldenfile.WriteFile(dirName, fileContent, goldenfile.ResultsFilename)
}
// read golden file
file := goldenfile.ReadFile(dirName, goldenfile.ResultsFilename)
rawResources := make([]map[string]interface{}, 0)
err := json.Unmarshal(file, &rawResources)
if err != nil {
panic(err)
}
for _, res := range rawResources {
res := res
expectedResources = append(expectedResources, &resource.Resource{
Id: res["id"].(string),
Type: ty,
Attrs: (*resource.Attributes)(&res),
})
}
// diff
differ, err := diff.NewDiffer(diff.SliceOrdering(true))
if err != nil {
panic(err)
}
got = resource.Sort(got)
expectedResources = resource.Sort(expectedResources)
changelog, err := differ.Diff(got, expectedResources)
if err != nil {
panic(err)
}
if len(changelog) > 0 {
for _, change := range changelog {
tt.Errorf("%s got = %v, want %v", strings.Join(change.Path, "."), awsutil.Prettify(change.From), awsutil.Prettify(change.To))
}
}
}
func testAgainstGoldenFileCty(
got []*resource.Resource,
ty string,
dirName string,
provider terraform.TerraformProvider,
deserializer *resource.Deserializer,
shouldUpdate bool,
tt *testing.T,
) {
var expectedResources []*resource.Resource
ctyType := cty.List(provider.Schema()[ty].Block.ImpliedType())
// update golden file
if shouldUpdate {
attributes := make([]*resource.Attributes, 0, len(got))
for _, res := range got {
attributes = append(attributes, res.Attributes())
}
ctVal, err := gocty.ToCtyValue(attributes, ctyType)
if err != nil {
panic(err)
}
unm, err := ctyjson.Marshal(ctVal, ctyType)
if err != nil {
panic(err)
}
goldenfile.WriteFile(dirName, unm, goldenfile.ResultsFilename)
}
// read golden file
file := goldenfile.ReadFile(dirName, goldenfile.ResultsFilename)
decodedJson, err := ctyjson.Unmarshal(file, ctyType)
if err != nil {
panic(err)
}
decodedResources, err := deserializer.Deserialize(ty, decodedJson.AsValueSlice())
if err != nil {
panic(err)
}
expectedResources = append(expectedResources, decodedResources...)
// diff
differ, err := diff.NewDiffer(diff.SliceOrdering(true))
if err != nil {
panic(err)
}
got = resource.Sort(got)
expectedResources = resource.Sort(expectedResources)
changelog, err := differ.Diff(got, expectedResources)
if err != nil {
panic(err)
}
if len(changelog) > 0 {
for _, change := range changelog {
tt.Errorf("%s got = %v, want %v", strings.Join(change.Path, "."), awsutil.Prettify(change.From), awsutil.Prettify(change.To))
}
}
}
func TestAgainstGoldenFile(
got []*resource.Resource,
ty string,
dirName string,
provider terraform.TerraformProvider,
deserializer *resource.Deserializer,
shouldUpdate bool,
tt *testing.T,
) {
testAgainstGoldenFileCty(got, ty, dirName, provider, deserializer, shouldUpdate, tt)
}