Merge pull request #141 from cloudskiff/fea/send_one_aler_computed
only send one alert for computed fiedsmain
commit
305f1cfece
|
@ -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) {
|
||||||
|
|
|
@ -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: "You have diffs on computed fields, check the documentation for potential false positive drifts",
|
||||||
},
|
|
||||||
{
|
|
||||||
Message: "Struct.Baz is a computed field",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Message: "StructSlice.0.String is a computed field",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Message: "StructSlice.0.Array is a computed field",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue