Merge pull request #141 from cloudskiff/fea/send_one_aler_computed

only send one alert for computed fieds
main
Elie 2021-01-22 14:40:29 +01:00 committed by GitHub
commit 305f1cfece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 26 additions and 71 deletions

View File

@ -1,10 +1,8 @@
package analyser package analyser
import ( import (
"fmt"
"reflect" "reflect"
"sort" "sort"
"strings"
"github.com/cloudskiff/driftctl/pkg/alerter" "github.com/cloudskiff/driftctl/pkg/alerter"
"github.com/cloudskiff/driftctl/pkg/resource" "github.com/cloudskiff/driftctl/pkg/resource"
@ -36,6 +34,7 @@ func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resourc
filteredRemoteResource = append(filteredRemoteResource, remoteRes) filteredRemoteResource = append(filteredRemoteResource, remoteRes)
} }
haveComputedDiff := false
for _, stateRes := range resourcesFromState { for _, stateRes := range resourcesFromState {
i, remoteRes, found := findCorrespondingRes(filteredRemoteResource, stateRes) i, remoteRes, found := findCorrespondingRes(filteredRemoteResource, stateRes)
@ -64,6 +63,9 @@ func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resourc
} }
c := Change{Change: change} c := Change{Change: change}
c.Computed = a.isComputedField(stateRes, c) c.Computed = a.isComputedField(stateRes, c)
if c.Computed {
haveComputedDiff = true
}
changelog = append(changelog, c) changelog = append(changelog, c)
} }
if len(changelog) > 0 { if len(changelog) > 0 {
@ -71,9 +73,14 @@ func (a Analyzer) Analyze(remoteResources, resourcesFromState []resource.Resourc
Res: stateRes, Res: stateRes,
Changelog: changelog, Changelog: changelog,
}) })
a.sendAlertOnComputedField(stateRes, changelog)
} }
} }
if haveComputedDiff {
a.alerter.SendAlert("",
alerter.Alert{
Message: "You have diffs on computed fields, check the documentation for potential false positive drifts",
})
}
} }
// Add remaining unmanaged resources // Add remaining unmanaged resources
@ -109,29 +116,6 @@ func (a Analyzer) isComputedField(stateRes resource.Resource, change Change) boo
return false return false
} }
// sendAlertOnComputedField will send an alert to a channel for diffs on computed field
func (a Analyzer) sendAlertOnComputedField(stateRes resource.Resource, delta Changelog) {
for _, d := range delta {
if d.Computed {
// We need to copy the path (for console output compatibility) and remove the
// last index if it's a slice.
// We want a console output of format: struct.0.array.0: "foo" => "bar" (computed)
// We want a json output of format: "message": "struct.0.array is a computed field"
tmp := make([]string, len(d.Path))
copy(tmp, d.Path)
field, _ := a.getField(reflect.TypeOf(stateRes), tmp)
if field.Type.Kind() == reflect.Slice {
tmp = tmp[:len(tmp)-1]
}
path := strings.Join(tmp, ".")
a.alerter.SendAlert(fmt.Sprintf("%s.%s", stateRes.TerraformType(), stateRes.TerraformId()),
alerter.Alert{
Message: fmt.Sprintf("%s is a computed field", path),
})
}
}
}
// getField recursively finds the deepest field inside a resource depending on // getField recursively finds the deepest field inside a resource depending on
// its path and its type // its path and its type
func (a Analyzer) getField(t reflect.Type, path []string) (reflect.StructField, bool) { func (a Analyzer) getField(t reflect.Type, path []string) (reflect.StructField, bool) {

View File

@ -270,12 +270,9 @@ func TestAnalyze(t *testing.T) {
}, },
}, },
alerts: alerter.Alerts{ alerts: alerter.Alerts{
"FakeResource.foobar": { "": {
{ {
Message: "BarFoo is a computed field", Message: "You have diffs on computed fields, check the documentation for potential false positive drifts",
},
{
Message: "Struct.Baz is a computed field",
}, },
}, },
}, },
@ -352,9 +349,9 @@ func TestAnalyze(t *testing.T) {
}, },
}, },
alerts: alerter.Alerts{ alerts: alerter.Alerts{
"fakeres.foobar": { "": {
{ {
Message: "BarFoo is a computed field", Message: "You have diffs on computed fields, check the documentation for potential false positive drifts",
}, },
}, },
}, },
@ -673,17 +670,10 @@ func TestAnalyze(t *testing.T) {
{ {
Message: "Should not be ignored", Message: "Should not be ignored",
}, },
{
Message: "BarFoo is a computed field",
}, },
"": {
{ {
Message: "Struct.Baz is a computed field", Message: "You have diffs on computed fields, check the documentation for potential false positive drifts",
},
{
Message: "StructSlice.0.String is a computed field",
},
{
Message: "StructSlice.0.Array is a computed field",
}, },
}, },
}, },

View File

@ -28,8 +28,6 @@ func NewConsole() *Console {
} }
func (c *Console) Write(analysis *analyser.Analysis) error { func (c *Console) Write(analysis *analyser.Analysis) error {
var shouldWarnOnComputedFields bool
if analysis.Summary().TotalDeleted > 0 { if analysis.Summary().TotalDeleted > 0 {
fmt.Printf("Found deleted resources:\n") fmt.Printf("Found deleted resources:\n")
deletedByType := groupByType(analysis.Deleted()) deletedByType := groupByType(analysis.Deleted())
@ -89,7 +87,6 @@ func (c *Console) Write(analysis *analyser.Analysis) error {
} }
fmt.Printf(" %s %s => %s", pref, prettify(change.From), prettify(change.To)) fmt.Printf(" %s %s => %s", pref, prettify(change.From), prettify(change.To))
if change.Computed { if change.Computed {
shouldWarnOnComputedFields = true
fmt.Printf(" %s", color.YellowString("(computed)")) fmt.Printf(" %s", color.YellowString("(computed)"))
} }
fmt.Printf("\n") fmt.Printf("\n")
@ -99,8 +96,10 @@ func (c *Console) Write(analysis *analyser.Analysis) error {
c.writeSummary(analysis) c.writeSummary(analysis)
if shouldWarnOnComputedFields { for _, alerts := range analysis.Alerts() {
fmt.Printf("%s\n", color.YellowString("You have diffs on computed field, check the documentation for potential false positive drifts")) for _, alert := range alerts {
fmt.Printf("%s\n", color.YellowString(alert.Message))
}
} }
return nil return nil

View File

@ -229,18 +229,9 @@ func fakeAnalysisWithComputedFields() *analyser.Analysis {
}, },
}}) }})
a.SetAlerts(alerter.Alerts{ a.SetAlerts(alerter.Alerts{
"aws_diff_resource.diff-id-1": []alerter.Alert{ "": []alerter.Alert{
{ {
Message: "updated.field is a computed field", Message: "You have diffs on computed fields, check the documentation for potential false positive drifts",
},
{
Message: "a is a computed field",
},
{
Message: "struct.0.array is a computed field",
},
{
Message: "struct.0.string is a computed field",
}, },
}, },
}) })

View File

@ -78,18 +78,9 @@
], ],
"coverage": 100, "coverage": 100,
"alerts": { "alerts": {
"aws_diff_resource.diff-id-1": [ "": [
{ {
"message": "updated.field is a computed field" "message": "You have diffs on computed fields, check the documentation for potential false positive drifts"
},
{
"message": "a is a computed field"
},
{
"message": "struct.0.array is a computed field"
},
{
"message": "struct.0.string is a computed field"
} }
] ]
} }

View File

@ -11,4 +11,4 @@ Found 1 resource(s)
- 0 not covered by IaC - 0 not covered by IaC
- 0 deleted on cloud provider - 0 deleted on cloud provider
- 1/1 drifted from IaC - 1/1 drifted from IaC
You have diffs on computed field, check the documentation for potential false positive drifts You have diffs on computed fields, check the documentation for potential false positive drifts