-
Notifications
You must be signed in to change notification settings - Fork 25
/
listing.go
149 lines (130 loc) · 3.55 KB
/
listing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package helpers
import (
"sync"
"github.com/kubescape/opa-utils/reporthandling/apis"
"golang.org/x/exp/maps"
)
var allListsPool = &sync.Pool{
New: func() interface{} {
return &AllLists{}
},
}
// GetAllListsFromPool get the AllLists object from the pool
func GetAllListsFromPool() *AllLists {
l, ok := allListsPool.Get().(*AllLists)
if !ok {
return nil
}
// reset the object before returning it as it might be dirty
l.Clear()
return l
}
// PutAllListsToPool put the AllLists object back to the pool
func PutAllListsToPool(l *AllLists) {
allListsPool.Put(l)
}
// ReportObject any report object must be compliment with a map[string]interface{} structures
type ReportObject map[string]interface{}
// AllLists lists of resources/policies grouped by the status, this structure is meant for internal use of report handling and not an API
type AllLists struct {
itemToStatus map[string]apis.ScanningStatus
passed int
failed int
skipped int
other int
}
func (all *AllLists) Failed() int { return all.failed }
func (all *AllLists) Passed() int { return all.passed }
func (all *AllLists) Skipped() int { return all.skipped }
func (all *AllLists) Other() int { return all.other }
func (all *AllLists) Len() int {
return all.failed + all.passed + all.skipped + all.other
}
func (all *AllLists) All() map[string]apis.ScanningStatus {
return all.itemToStatus
}
// Initialize initialize the AllLists object map with the given size - this is an optimization for the map
func (all *AllLists) Initialize(size int) {
if all.itemToStatus == nil {
all.itemToStatus = make(map[string]apis.ScanningStatus, size)
}
}
// Clear remove all items and reset the counters
func (all *AllLists) Clear() {
if all.itemToStatus != nil {
maps.Clear(all.itemToStatus)
all.passed = 0
all.failed = 0
all.skipped = 0
all.other = 0
}
}
// Append append single string to matching status list
func (all *AllLists) Append(status apis.ScanningStatus, str ...string) {
if all.itemToStatus == nil {
all.itemToStatus = make(map[string]apis.ScanningStatus, len(str))
}
for _, s := range str {
oldStatus, exist := all.itemToStatus[s]
if !exist {
all.itemToStatus[s] = status
all.updateCounters(status, true)
// element exist with different status
} else if oldStatus != status {
// check if the new status is more significant
if result := apis.Compare(oldStatus, status); result == status {
all.itemToStatus[s] = status
all.updateCounters(status, true)
all.updateCounters(oldStatus, false)
}
}
}
}
// Helper function to update status counters
func (all *AllLists) updateCounters(status apis.ScanningStatus, increment bool) {
var delta int
if increment {
delta = 1
} else {
delta = -1
}
switch status {
case apis.StatusPassed:
all.passed += delta
case apis.StatusFailed:
all.failed += delta
case apis.StatusSkipped:
all.skipped += delta
default:
all.other += delta
}
}
// Update AllLists objects with
func (all *AllLists) Update(all2 *AllLists) {
for item, status := range all2.itemToStatus {
all.Append(apis.ScanningStatus(status), item)
}
}
func (all *AllLists) GetItems(status apis.ScanningStatus) []string {
var amount int
switch status {
case apis.StatusPassed:
amount = all.passed
case apis.StatusFailed:
amount = all.failed
case apis.StatusSkipped:
amount = all.skipped
default:
amount = all.other
}
if amount == 0 {
return []string{}
}
items := make([]string, 0, amount)
for item, itemStatus := range all.itemToStatus {
if itemStatus == status {
items = append(items, item)
}
}
return items
}