Skip to content

Commit

Permalink
Merge branch 'main' into fix/progressBarResume
Browse files Browse the repository at this point in the history
  • Loading branch information
sundowndev authored Apr 26, 2021
2 parents b38063d + 44d1a8e commit 30bc979
Show file tree
Hide file tree
Showing 29 changed files with 175,389 additions and 254 deletions.
3 changes: 2 additions & 1 deletion pkg/analyser/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import (

type Change struct {
diff.Change
Computed bool `json:"computed"`
Computed bool `json:"computed"`
JsonString bool `json:"-"`
}

type Changelog []Change
Expand Down
37 changes: 31 additions & 6 deletions pkg/analyser/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"reflect"

resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"

"github.com/r3labs/diff/v2"

"github.com/cloudskiff/driftctl/pkg/alerter"
Expand Down Expand Up @@ -40,16 +39,17 @@ func (c *ComputedDiffAlert) ShouldIgnoreResource() bool {
}

type Analyzer struct {
alerter *alerter.Alerter
alerter *alerter.Alerter
resourceSchemaRepository resource.SchemaRepositoryInterface
}

type Filter interface {
IsResourceIgnored(res resource.Resource) bool
IsFieldIgnored(res resource.Resource, path []string) bool
}

func NewAnalyzer(alerter *alerter.Alerter) Analyzer {
return Analyzer{alerter}
func NewAnalyzer(alerter *alerter.Alerter, resourceSchemaRepository resource.SchemaRepositoryInterface) Analyzer {
return Analyzer{alerter, resourceSchemaRepository}
}

func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resource, filter Filter) (Analysis, error) {
Expand Down Expand Up @@ -81,7 +81,14 @@ func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resourc
filteredRemoteResource = removeResourceByIndex(i, filteredRemoteResource)
analysis.AddManaged(stateRes)

delta, _ := diff.Diff(stateRes, remoteRes)
var delta diff.Changelog
if resource.IsRefactoredResource(stateRes.TerraformType()) {
stateRes, _ := stateRes.(*resource.AbstractResource)
remoteRes, _ := remoteRes.(*resource.AbstractResource)
delta, _ = diff.Diff(stateRes.Attrs, remoteRes.Attrs)
} else {
delta, _ = diff.Diff(stateRes, remoteRes)
}

if len(delta) == 0 {
continue
Expand All @@ -93,7 +100,16 @@ func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resourc
continue
}
c := Change{Change: change}
c.Computed = a.isComputedField(stateRes, c)
if resource.IsRefactoredResource(stateRes.TerraformType()) {
resSchema, exist := a.resourceSchemaRepository.GetSchema(stateRes.TerraformType())
if exist {
c.Computed = resSchema.IsComputedField(c.Path)
c.JsonString = resSchema.IsJsonStringField(c.Path)
}
} else {
c.Computed = a.isComputedField(stateRes, c)
c.JsonString = a.isJsonStringField(stateRes, c)
}
if c.Computed {
haveComputedDiff = true
}
Expand Down Expand Up @@ -152,6 +168,15 @@ func (a Analyzer) isComputedField(stateRes resource.Resource, change Change) boo
return false
}

// isJsonStringField returns true if the field that generated the diff of a resource
// has a jsonfield tag
func (a Analyzer) isJsonStringField(stateRes resource.Resource, change Change) bool {
if field, ok := a.getField(reflect.TypeOf(stateRes), change.Path); ok {
return field.Tag.Get("jsonfield") == "true"
}
return false
}

// getField recursively finds the deepest field inside a resource depending on
// its path and its type
func (a Analyzer) getField(t reflect.Type, path []string) (reflect.StructField, bool) {
Expand Down
5 changes: 4 additions & 1 deletion pkg/analyser/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,10 @@ func TestAnalyze(t *testing.T) {
al.SetAlerts(c.alerts)
}

analyzer := NewAnalyzer(al)
repo := testresource.InitFakeSchemaRepository("aws", "3.19.0")
aws.InitResourcesMetadata(repo)

analyzer := NewAnalyzer(al, repo)
result, err := analyzer.Analyze(c.cloud, c.iac, filter)

if err != nil {
Expand Down
10 changes: 6 additions & 4 deletions pkg/cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ func scanRun(opts *pkg.ScanOptions) error {

progress := globaloutput.NewProgress()

err := remote.Activate(opts.To, alerter, providerLibrary, supplierLibrary, progress)
resourceSchemaRepository := resource.NewSchemaRepository()

err := remote.Activate(opts.To, alerter, providerLibrary, supplierLibrary, progress, resourceSchemaRepository)
if err != nil {
return err
}
Expand All @@ -158,16 +160,16 @@ func scanRun(opts *pkg.ScanOptions) error {
logrus.Trace("Exited")
}()

scanner := pkg.NewScanner(supplierLibrary.Suppliers(), alerter)
scanner := pkg.NewScanner(supplierLibrary.Suppliers(), alerter, resourceSchemaRepository)

iacSupplier, err := supplier.GetIACSupplier(opts.From, providerLibrary, opts.BackendOptions)
iacSupplier, err := supplier.GetIACSupplier(opts.From, providerLibrary, opts.BackendOptions, resourceSchemaRepository)
if err != nil {
return err
}

resFactory := terraform.NewTerraformResourceFactory(providerLibrary)

ctl := pkg.NewDriftCTL(scanner, iacSupplier, alerter, resFactory, opts)
ctl := pkg.NewDriftCTL(scanner, iacSupplier, alerter, resFactory, opts, resourceSchemaRepository)

go func() {
<-c
Expand Down
20 changes: 1 addition & 19 deletions pkg/cmd/scan/output/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ func (c *Console) Write(analysis *analyser.Analysis) error {
pref = fmt.Sprintf("%s %s:", color.RedString("-"), path)
}
if change.Type == diff.UPDATE {
isJsonString := isFieldJsonString(difference.Res, path)
if isJsonString {
if change.JsonString {
prefix := " "
fmt.Printf(" %s\n%s%s\n", pref, prefix, jsonDiff(change.From, change.To, prefix))
continue
Expand Down Expand Up @@ -181,23 +180,6 @@ func groupByType(resources []resource.Resource) map[string][]resource.Resource {
return result
}

func isFieldJsonString(res resource.Resource, fieldName string) bool {
t := reflect.TypeOf(res)
var field reflect.StructField
var ok bool
if t.Kind() == reflect.Ptr {
field, ok = t.Elem().FieldByName(fieldName)
}
if t.Kind() != reflect.Ptr {
field, ok = t.FieldByName(fieldName)
}
if !ok {
return false
}

return field.Tag.Get("jsonstring") == "true"
}

func jsonDiff(a, b interface{}, prefix string) string {
aStr := fmt.Sprintf("%s", a)
bStr := fmt.Sprintf("%s", b)
Expand Down
73 changes: 73 additions & 0 deletions pkg/cmd/scan/output/console_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/zclconf/go-cty/cty/gocty"

"github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/cloudskiff/driftctl/test/goldenfile"
testresource "github.com/cloudskiff/driftctl/test/resource"

"github.com/cloudskiff/driftctl/pkg/analyser"
)
Expand Down Expand Up @@ -70,6 +73,76 @@ func TestConsole_Write(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := testresource.InitFakeSchemaRepository("aws", "3.19.0")
aws.InitResourcesMetadata(repo)
for _, res := range tt.args.analysis.Managed() {
fakeRes, ok := res.(*testresource.FakeResource)
if ok {
impliedType, _ := gocty.ImpliedType(fakeRes)
value, _ := gocty.ToCtyValue(fakeRes, impliedType)
fakeRes.CtyVal = &value
continue
}
fakeStringerRes, ok := res.(*testresource.FakeResourceStringer)
if ok {
impliedType, _ := gocty.ImpliedType(fakeStringerRes)
value, _ := gocty.ToCtyValue(fakeStringerRes, impliedType)
fakeStringerRes.CtyVal = &value
continue
}
}

for _, res := range tt.args.analysis.Unmanaged() {
fakeRes, ok := res.(*testresource.FakeResource)
if ok {
impliedType, _ := gocty.ImpliedType(fakeRes)
value, _ := gocty.ToCtyValue(fakeRes, impliedType)
fakeRes.CtyVal = &value
continue
}
fakeStringerRes, ok := res.(*testresource.FakeResourceStringer)
if ok {
impliedType, _ := gocty.ImpliedType(fakeStringerRes)
value, _ := gocty.ToCtyValue(fakeStringerRes, impliedType)
fakeStringerRes.CtyVal = &value
continue
}
}

for _, res := range tt.args.analysis.Deleted() {
fakeRes, ok := res.(*testresource.FakeResource)
if ok {
impliedType, _ := gocty.ImpliedType(fakeRes)
value, _ := gocty.ToCtyValue(fakeRes, impliedType)
fakeRes.CtyVal = &value
continue
}
fakeStringerRes, ok := res.(*testresource.FakeResourceStringer)
if ok {
impliedType, _ := gocty.ImpliedType(fakeStringerRes)
value, _ := gocty.ToCtyValue(fakeStringerRes, impliedType)
fakeStringerRes.CtyVal = &value
continue
}
}

for _, d := range tt.args.analysis.Differences() {
fakeRes, ok := d.Res.(*testresource.FakeResource)
if ok {
impliedType, _ := gocty.ImpliedType(fakeRes)
value, _ := gocty.ToCtyValue(fakeRes, impliedType)
fakeRes.CtyVal = &value
continue
}
fakeStringerRes, ok := d.Res.(*testresource.FakeResourceStringer)
if ok {
impliedType, _ := gocty.ImpliedType(fakeStringerRes)
value, _ := gocty.ToCtyValue(fakeStringerRes, impliedType)
fakeStringerRes.CtyVal = &value
continue
}
}

c := NewConsole()

stdout := os.Stdout // keep backup of the real stdout
Expand Down
4 changes: 3 additions & 1 deletion pkg/cmd/scan/output/output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func fakeAnalysisWithJsonFields() *analyser.Analysis {
Type: "aws_diff_resource",
}, Changelog: []analyser.Change{
{
JsonString: true,
Change: diff.Change{
Type: diff.UPDATE,
Path: []string{"Json"},
Expand All @@ -121,6 +122,7 @@ func fakeAnalysisWithJsonFields() *analyser.Analysis {
Type: "aws_diff_resource",
}, Changelog: []analyser.Change{
{
JsonString: true,
Change: diff.Change{
Type: diff.UPDATE,
Path: []string{"Json"},
Expand Down Expand Up @@ -176,7 +178,7 @@ func fakeAnalysisWithComputedFields() *analyser.Analysis {
Type: "aws_diff_resource",
},
)
a.AddDifference(analyser.Difference{Res: testresource.FakeResource{
a.AddDifference(analyser.Difference{Res: &testresource.FakeResource{
Id: "diff-id-1",
Type: "aws_diff_resource",
}, Changelog: []analyser.Change{
Expand Down
4 changes: 2 additions & 2 deletions pkg/driftctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ type DriftCTL struct {
strictMode bool
}

func NewDriftCTL(remoteSupplier resource.Supplier, iacSupplier resource.Supplier, alerter *alerter.Alerter, resFactory resource.ResourceFactory, opts *ScanOptions) *DriftCTL {
func NewDriftCTL(remoteSupplier resource.Supplier, iacSupplier resource.Supplier, alerter *alerter.Alerter, resFactory resource.ResourceFactory, opts *ScanOptions, resourceSchemaRepository resource.SchemaRepositoryInterface) *DriftCTL {
return &DriftCTL{
remoteSupplier,
iacSupplier,
alerter,
analyser.NewAnalyzer(alerter),
analyser.NewAnalyzer(alerter, resourceSchemaRepository),
opts.Filter,
resFactory,
opts.StrictMode,
Expand Down
Loading

0 comments on commit 30bc979

Please sign in to comment.