Merge pull request #660 from cloudskiff/feat/driftignoreFlag
Add driftignore flag to specify a different .driftignore filemain
commit
ee6cd5aec0
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue