Merge pull request #660 from cloudskiff/feat/driftignoreFlag

Add driftignore flag to specify a different .driftignore file
main
Elie 2021-06-21 15:13:43 +02:00 committed by GitHub
commit ee6cd5aec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 20 deletions

View File

@ -157,6 +157,11 @@ func NewScanCmd() *cobra.Command {
false, false,
"Includes cloud provider service-linked roles (disabled by default)", "Includes cloud provider service-linked roles (disabled by default)",
) )
fl.StringVar(&opts.DriftignorePath,
"driftignore",
".driftignore",
"Path to the driftignore file",
)
configDir, err := homedir.Dir() configDir, err := homedir.Dir()
if err != nil { if err != nil {

View File

@ -45,6 +45,8 @@ func TestScanCmd_Valid(t *testing.T) {
{args: []string{"scan", "--strict"}}, {args: []string{"scan", "--strict"}},
{args: []string{"scan", "--tf-provider-version", "1.2.3"}}, {args: []string{"scan", "--tf-provider-version", "1.2.3"}},
{args: []string{"scan", "--tf-provider-version", "3.30.2"}}, {args: []string{"scan", "--tf-provider-version", "3.30.2"}},
{args: []string{"scan", "--driftignore", "./path/to/driftignore.s3"}},
{args: []string{"scan", "--driftignore", ".driftignore"}},
} }
for _, tt := range cases { for _, tt := range cases {
@ -85,6 +87,7 @@ func TestScanCmd_Invalid(t *testing.T) {
{args: []string{"scan", "--filter", "Type='test'", "--filter", "Type='test2'"}, expected: "Filter flag should be specified only once"}, {args: []string{"scan", "--filter", "Type='test'", "--filter", "Type='test2'"}, expected: "Filter flag should be specified only once"},
{args: []string{"scan", "--tf-provider-version", ".30.2"}, expected: "Invalid version argument .30.2, expected a valid semver string (e.g. 2.13.4)"}, {args: []string{"scan", "--tf-provider-version", ".30.2"}, expected: "Invalid version argument .30.2, expected a valid semver string (e.g. 2.13.4)"},
{args: []string{"scan", "--tf-provider-version", "foo"}, expected: "Invalid version argument foo, expected a valid semver string (e.g. 2.13.4)"}, {args: []string{"scan", "--tf-provider-version", "foo"}, expected: "Invalid version argument foo, expected a valid semver string (e.g. 2.13.4)"},
{args: []string{"scan", "--driftignore"}, expected: "flag needs an argument: --driftignore"},
} }
for _, tt := range cases { for _, tt := range cases {

View File

@ -31,6 +31,7 @@ type ScanOptions struct {
DisableTelemetry bool DisableTelemetry bool
ProviderVersion string ProviderVersion string
ConfigDir string ConfigDir string
DriftignorePath string
} }
type DriftCTL struct { type DriftCTL struct {
@ -38,12 +39,11 @@ type DriftCTL struct {
iacSupplier resource.Supplier iacSupplier resource.Supplier
alerter alerter.AlerterInterface alerter alerter.AlerterInterface
analyzer analyser.Analyzer analyzer analyser.Analyzer
filter *jmespath.JMESPath
resourceFactory resource.ResourceFactory resourceFactory resource.ResourceFactory
strictMode bool
scanProgress globaloutput.Progress scanProgress globaloutput.Progress
iacProgress globaloutput.Progress iacProgress globaloutput.Progress
resourceSchemaRepository resource.SchemaRepositoryInterface resourceSchemaRepository resource.SchemaRepositoryInterface
opts *ScanOptions
} }
func NewDriftCTL(remoteSupplier resource.Supplier, func NewDriftCTL(remoteSupplier resource.Supplier,
@ -59,12 +59,11 @@ func NewDriftCTL(remoteSupplier resource.Supplier,
iacSupplier, iacSupplier,
alerter, alerter,
analyser.NewAnalyzer(alerter), analyser.NewAnalyzer(alerter),
opts.Filter,
resFactory, resFactory,
opts.StrictMode,
scanProgress, scanProgress,
iacProgress, iacProgress,
resourceSchemaRepository, resourceSchemaRepository,
opts,
} }
} }
@ -100,7 +99,7 @@ func (d DriftCTL) Run() (*analyser.Analysis, error) {
middlewares.NewAwsRoleManagedPolicyExpander(d.resourceFactory), middlewares.NewAwsRoleManagedPolicyExpander(d.resourceFactory),
) )
if !d.strictMode { if !d.opts.StrictMode {
middleware = append(middleware, middleware = append(middleware,
middlewares.NewAwsDefaults(), middlewares.NewAwsDefaults(),
) )
@ -112,8 +111,8 @@ func (d DriftCTL) Run() (*analyser.Analysis, error) {
return nil, err return nil, err
} }
if d.filter != nil { if d.opts.Filter != nil {
engine := filter.NewFilterEngine(d.filter) engine := filter.NewFilterEngine(d.opts.Filter)
remoteResources, err = engine.Run(remoteResources) remoteResources, err = engine.Run(remoteResources)
if err != nil { if err != nil {
return nil, err return nil, err
@ -125,7 +124,7 @@ func (d DriftCTL) Run() (*analyser.Analysis, error) {
} }
logrus.Debug("Checking for driftignore") logrus.Debug("Checking for driftignore")
driftIgnore := filter.NewDriftIgnore() driftIgnore := filter.NewDriftIgnore(d.opts.DriftignorePath)
analysis, err := d.analyzer.Analyze(remoteResources, resourcesFromState, driftIgnore) analysis, err := d.analyzer.Analyze(remoteResources, resourcesFromState, driftIgnore)
analysis.Duration = time.Since(start) analysis.Duration = time.Since(start)

View File

@ -15,13 +15,15 @@ type DriftIgnore struct {
resExclusionList map[string]struct{} // map[type.id] exists to ignore resExclusionList map[string]struct{} // map[type.id] exists to ignore
resExclusionWildcardList map[string]struct{} // map[type.id] exists with wildcard to ignore resExclusionWildcardList map[string]struct{} // map[type.id] exists with wildcard to ignore
driftExclusionList map[string][]string // map[type.id] contains path for drift to ignore driftExclusionList map[string][]string // map[type.id] contains path for drift to ignore
driftignorePath string
} }
func NewDriftIgnore() *DriftIgnore { func NewDriftIgnore(path string) *DriftIgnore {
d := DriftIgnore{ d := DriftIgnore{
resExclusionList: map[string]struct{}{}, resExclusionList: map[string]struct{}{},
resExclusionWildcardList: map[string]struct{}{}, resExclusionWildcardList: map[string]struct{}{},
driftExclusionList: map[string][]string{}, driftExclusionList: map[string][]string{},
driftignorePath: path,
} }
err := d.readIgnoreFile() err := d.readIgnoreFile()
if err != nil { if err != nil {
@ -31,7 +33,7 @@ func NewDriftIgnore() *DriftIgnore {
} }
func (r *DriftIgnore) readIgnoreFile() error { func (r *DriftIgnore) readIgnoreFile() error {
file, err := os.Open(".driftignore") file, err := os.Open(r.driftignorePath)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,7 +2,6 @@ package filter
import ( import (
"os" "os"
"path"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
@ -19,6 +18,7 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
name string name string
resources []resource.Resource resources []resource.Resource
want []bool want []bool
path string
}{ }{
{ {
name: "drift_ignore_no_file", name: "drift_ignore_no_file",
@ -28,10 +28,10 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
Id: "id1", Id: "id1",
}, },
}, },
want: []bool{ want: []bool{
false, false,
}, },
path: "testdata/drift_ignore_no_file/.driftignore",
}, },
{ {
name: "drift_ignore_empty", name: "drift_ignore_empty",
@ -44,6 +44,7 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
want: []bool{ want: []bool{
false, false,
}, },
path: "testdata/drift_ignore_empty/.driftignore",
}, },
{ {
name: "drift_ignore_invalid_lines", name: "drift_ignore_invalid_lines",
@ -61,6 +62,7 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
false, false,
true, true,
}, },
path: "testdata/drift_ignore_invalid_lines/.driftignore",
}, },
{ {
name: "drift_ignore_valid", name: "drift_ignore_valid",
@ -108,6 +110,7 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
true, true,
true, true,
}, },
path: "testdata/drift_ignore_valid/.driftignore",
}, },
{ {
name: "drift_ignore_wildcard", name: "drift_ignore_wildcard",
@ -150,16 +153,15 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
false, false,
true, true,
}, },
path: "testdata/drift_ignore_wildcard/.driftignore",
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cwd, _ := os.Getwd() cwd, _ := os.Getwd()
defer func() { _ = os.Chdir(cwd) }() defer func() { _ = os.Chdir(cwd) }()
if err := os.Chdir(path.Join("testdata", tt.name)); err != nil {
t.Fatal(err) r := NewDriftIgnore(tt.path)
}
r := NewDriftIgnore()
got := make([]bool, 0, len(tt.want)) got := make([]bool, 0, len(tt.want))
for _, res := range tt.resources { for _, res := range tt.resources {
got = append(got, r.IsResourceIgnored(res)) got = append(got, r.IsResourceIgnored(res))
@ -180,6 +182,7 @@ func TestDriftIgnore_IsFieldIgnored(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args []Args args []Args
path string
}{ }{
{ {
name: "drift_ignore_no_file", name: "drift_ignore_no_file",
@ -196,6 +199,7 @@ func TestDriftIgnore_IsFieldIgnored(t *testing.T) {
Want: false, Want: false,
}, },
}, },
path: "testdata/drift_ignore_no_file/.driftignore",
}, },
{ {
name: "drift_ignore_empty", name: "drift_ignore_empty",
@ -211,6 +215,7 @@ func TestDriftIgnore_IsFieldIgnored(t *testing.T) {
Want: false, Want: false,
}, },
}, },
path: "testdata/drift_ignore_empty/.driftignore",
}, },
{ {
name: "drift_ignore_fields", name: "drift_ignore_fields",
@ -281,16 +286,15 @@ func TestDriftIgnore_IsFieldIgnored(t *testing.T) {
Want: true, Want: true,
}, },
}, },
path: "testdata/drift_ignore_fields/.driftignore",
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cwd, _ := os.Getwd() cwd, _ := os.Getwd()
defer func() { _ = os.Chdir(cwd) }() defer func() { _ = os.Chdir(cwd) }()
if err := os.Chdir(path.Join("testdata", tt.name)); err != nil {
t.Fatal(err) r := NewDriftIgnore(tt.path)
}
r := NewDriftIgnore()
for _, arg := range tt.args { for _, arg := range tt.args {
got := r.IsFieldIgnored(arg.Res, arg.Path) got := r.IsFieldIgnored(arg.Res, arg.Path)
if arg.Want != got { if arg.Want != got {