Skip to content

Commit f34d544

Browse files
authored
Merge pull request #314 from cloudskiff/issue_232_lotoussa
DriftIgnore implement new wildcard match checker
2 parents aa7b6e7 + 3da401a commit f34d544

3 files changed

Lines changed: 117 additions & 9 deletions

File tree

pkg/filter/driftignore.go

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ import (
1212
)
1313

1414
type DriftIgnore struct {
15-
resExclusionList map[string]struct{} // map[type.id] exists to ignore
16-
driftExclusionList map[string][]string // map[type.id] contains path for drift to ignore
15+
resExclusionList map[string]struct{} // map[type.id] exists to ignore
16+
resExclusionWildcardList map[string]struct{} // map[type.id] exists with wildcard to ignore
17+
driftExclusionList map[string][]string // map[type.id] contains path for drift to ignore
1718
}
1819

1920
func NewDriftIgnore() *DriftIgnore {
2021
d := DriftIgnore{
21-
resExclusionList: map[string]struct{}{},
22-
driftExclusionList: map[string][]string{},
22+
resExclusionList: map[string]struct{}{},
23+
resExclusionWildcardList: map[string]struct{}{},
24+
driftExclusionList: map[string][]string{},
2325
}
2426
err := d.readIgnoreFile()
2527
if err != nil {
@@ -53,16 +55,20 @@ func (r *DriftIgnore) readIgnoreFile() error {
5355
}).Warnf("unable to parse line, invalid length, got %d expected >= 2", nbArgs)
5456
continue
5557
}
58+
res := strings.Join(typeVal[0:2], ".")
5659
if nbArgs == 2 { // We want to ignore a resource (type.id)
5760
logrus.WithFields(logrus.Fields{
5861
"type": typeVal[0],
5962
"id": typeVal[1],
6063
}).Debug("Found ignore resource rule in .driftignore")
61-
r.resExclusionList[strings.Join(typeVal, ".")] = struct{}{}
64+
resExclusionTypeList := r.resExclusionList
65+
if strings.Contains(res, "*") {
66+
resExclusionTypeList = r.resExclusionWildcardList
67+
}
68+
resExclusionTypeList[res] = struct{}{}
6269
continue
6370
}
6471
// Here we want to ignore a drift (type.id.path.to.field)
65-
res := strings.Join(typeVal[0:2], ".")
6672
ignoreSublist, exists := r.driftExclusionList[res]
6773
if !exists {
6874
ignoreSublist = make([]string, 0, 1)
@@ -87,9 +93,17 @@ func (r *DriftIgnore) readIgnoreFile() error {
8793
}
8894

8995
func (r *DriftIgnore) IsResourceIgnored(res resource.Resource) bool {
90-
_, isExclusionRule := r.resExclusionList[fmt.Sprintf("%s.%s", res.TerraformType(), res.TerraformId())]
91-
_, isExclusionWildcardRule := r.resExclusionList[fmt.Sprintf("%s.*", res.TerraformType())]
92-
return isExclusionRule || isExclusionWildcardRule
96+
strRes := fmt.Sprintf("%s.%s", res.TerraformType(), res.TerraformId())
97+
98+
if _, isExclusionRule := r.resExclusionList[strRes]; isExclusionRule {
99+
return true
100+
}
101+
for resExclusion := range r.resExclusionWildcardList {
102+
if wildcardMatchChecker(strRes, resExclusion) {
103+
return true
104+
}
105+
}
106+
return false
93107
}
94108

95109
func (r *DriftIgnore) IsFieldIgnored(res resource.Resource, path []string) bool {
@@ -129,11 +143,33 @@ RuleCheck:
129143
return false
130144
}
131145

146+
//Check two strings recursively, pattern can contain wildcard
147+
func wildcardMatchChecker(str, pattern string) bool {
148+
if str == "" && pattern == "" {
149+
return true
150+
}
151+
if strings.HasPrefix(pattern, "*") {
152+
if str != "" {
153+
return wildcardMatchChecker(str[1:], pattern) || wildcardMatchChecker(str, pattern[1:])
154+
}
155+
return wildcardMatchChecker(str, pattern[1:])
156+
}
157+
if str != "" && pattern != "" && str[0] == pattern[0] {
158+
return wildcardMatchChecker(str[1:], pattern[1:])
159+
}
160+
return false
161+
}
162+
132163
/**
133164
* Read a line of ignore
165+
* Handle multiple asterisks escaping
134166
* Handle split on dots and escaping
135167
*/
136168
func readDriftIgnoreLine(line string) []string {
169+
for strings.Contains(line, "**") {
170+
line = strings.ReplaceAll(line, "**", "*")
171+
}
172+
137173
var splitted []string
138174
lastWordEnd := 0
139175
for i := range line {

pkg/filter/driftignore_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,48 @@ func TestDriftIgnore_IsResourceIgnored(t *testing.T) {
109109
true,
110110
},
111111
},
112+
{
113+
name: "drift_ignore_wildcard",
114+
resources: []resource.Resource{
115+
&resource2.FakeResource{
116+
Type: "type1",
117+
Id: "id1",
118+
},
119+
&resource2.FakeResource{
120+
Type: "type2",
121+
Id: "id1",
122+
},
123+
&resource2.FakeResource{
124+
Type: "type2",
125+
Id: "id11",
126+
},
127+
&resource2.FakeResource{
128+
Type: "type2",
129+
Id: "id2",
130+
},
131+
&resource2.FakeResource{
132+
Type: "type3",
133+
Id: "id100",
134+
},
135+
&resource2.FakeResource{
136+
Type: "type3",
137+
Id: "id101",
138+
},
139+
&resource2.FakeResource{
140+
Type: "type4",
141+
Id: "id\\WithBac*slash***\\*\\",
142+
},
143+
},
144+
want: []bool{
145+
false,
146+
true,
147+
true,
148+
false,
149+
true,
150+
false,
151+
true,
152+
},
153+
},
112154
}
113155
for _, tt := range tests {
114156
t.Run(tt.name, func(t *testing.T) {
@@ -280,6 +322,31 @@ func Test_escapableSplit(t *testing.T) {
280322
line: "*.subfoobar",
281323
want: []string{"*", "subfoobar"},
282324
},
325+
{
326+
name: "text wildcard dot",
327+
line: "res*.subfoobar",
328+
want: []string{"res*", "subfoobar"},
329+
},
330+
{
331+
name: "missing text multiple wildcard dot",
332+
line: "r*s*.s**ub***ob********a*r",
333+
want: []string{"r*s*", "s*ub*ob*a*r"},
334+
},
335+
{
336+
name: "prefix wildcard dot",
337+
line: "*res.subfoobar",
338+
want: []string{"*res", "subfoobar"},
339+
},
340+
{
341+
name: "suffix multiple wildcard dot",
342+
line: "res.subfoobar*****",
343+
want: []string{"res", "subfoobar*"},
344+
},
345+
{
346+
name: "dot wildcard",
347+
line: "res.*",
348+
want: []string{"res", "*"},
349+
},
283350
}
284351
for _, tt := range tests {
285352
t.Run(tt.name, func(t *testing.T) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*2**.**d1*
2+
type3.id1***0
3+
*.id\\WithBa*slas*\\**\\
4+
5+
# this is *** comment

0 commit comments

Comments
 (0)