-
Notifications
You must be signed in to change notification settings - Fork 92
/
validate_specs.go
153 lines (128 loc) · 5.2 KB
/
validate_specs.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
150
151
152
153
package preflight
import (
"reflect"
"github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/loader"
"github.com/replicatedhq/troubleshoot/pkg/multitype"
"github.com/replicatedhq/troubleshoot/pkg/types"
)
// validatePreflight validates the preflight spec and returns a warning if there is any
func validatePreflight(kinds *loader.TroubleshootKinds) *types.ExitCodeWarning {
if len(kinds.PreflightsV1Beta2) == 0 && len(kinds.HostPreflightsV1Beta2) == 0 {
return types.NewExitCodeWarning("no preflight or host preflight spec was found")
}
for _, spec := range kinds.PreflightsV1Beta2 {
warning := validatePreflightSpecItems(spec.Spec.Collectors, spec.Spec.Analyzers)
if warning != nil {
return warning
}
}
for _, spec := range kinds.HostPreflightsV1Beta2 {
warning := validateHostPreflightSpecItems(spec.Spec.Collectors, spec.Spec.Analyzers)
if warning != nil {
return warning
}
}
return nil
}
// validatePreflightSpecItems validates the preflight spec items and returns a warning if there are any
// clusterResources or clusterInfo collectors added automatically to the preflight spec. It cannot be excluded
func validatePreflightSpecItems(collectors []*v1beta2.Collect, analyzers []*v1beta2.Analyze) *types.ExitCodeWarning {
var numberOfExcludedCollectors, numberOfExcludedAnalyzers int
var numberOfExcludedDefaultCollectors int
numberOfCollectors := len(collectors) + 2
numberOfAnalyzers := len(analyzers)
if numberOfCollectors >= 0 {
collectorsInterface := make([]interface{}, len(collectors))
for i, v := range collectors {
if v.ClusterInfo != nil || v.ClusterResources != nil {
numberOfExcludedDefaultCollectors++
}
collectorsInterface[i] = v
}
numberOfExcludedCollectors += countExcludedItems(collectorsInterface)
if numberOfExcludedCollectors+numberOfExcludedDefaultCollectors == numberOfCollectors {
return types.NewExitCodeWarning("All collectors were excluded by the applied values")
}
}
// if there are no analyzers, return a warning
// else check if all analyzers are excluded
if numberOfAnalyzers == 0 {
return types.NewExitCodeWarning("No analyzers found")
} else {
analyzersInterface := make([]interface{}, len(analyzers))
for i, v := range analyzers {
analyzersInterface[i] = v
}
numberOfExcludedAnalyzers = countExcludedItems(analyzersInterface)
if numberOfExcludedAnalyzers == numberOfAnalyzers {
return types.NewExitCodeWarning("All analyzers were excluded by the applied values")
}
}
return nil
}
// validateHostPreflightSpecItems validates the host preflight spec items and returns a warning if there is any
// no collectors are added or excluded automatically to the host preflight spec
func validateHostPreflightSpecItems(collectors []*v1beta2.HostCollect, analyzers []*v1beta2.HostAnalyze) *types.ExitCodeWarning {
var numberOfExcludedCollectors, numberOfExcludedAnalyzers int
numberOfCollectors := len(collectors)
numberOfAnalyzers := len(analyzers)
// if there are no collectors, return a warning
if numberOfCollectors == 0 {
return types.NewExitCodeWarning("No collectors found")
}
// if there are no analyzers, return a warning
if numberOfAnalyzers == 0 {
return types.NewExitCodeWarning("No analyzers found")
}
collectorsInterface := make([]interface{}, len(collectors))
for i, v := range collectors {
collectorsInterface[i] = v
}
analyzersInterface := make([]interface{}, len(analyzers))
for i, v := range analyzers {
analyzersInterface[i] = v
}
numberOfExcludedCollectors = countExcludedItems(collectorsInterface)
numberOfExcludedAnalyzers = countExcludedItems(analyzersInterface)
if numberOfExcludedCollectors == numberOfCollectors {
return types.NewExitCodeWarning("All collectors were excluded by the applied values")
}
if numberOfExcludedAnalyzers == numberOfAnalyzers {
return types.NewExitCodeWarning("All analyzers were excluded by the applied values")
}
return nil
}
// countExcludedItems counts and returns the number of excluded items in the given items slice.
// Items are assumed to be structures that may have an "Exclude" field as bool
// If the "Exclude" field is true, the item is considered excluded.
func countExcludedItems(items []interface{}) int {
numberOfExcludedItems := 0
for _, item := range items {
itemElem := reflect.ValueOf(item).Elem()
// Loop over all fields of the current item.
for i := 0; i < itemElem.NumField(); i++ {
// Get the value of the current field.
itemValue := itemElem.Field(i)
// If the current field is a pointer to a struct, check if it has an "Exclude" field.
if !itemValue.IsNil() {
elem := itemValue.Elem()
if elem.Kind() == reflect.Struct {
// Look for a field named "Exclude" in the struct.
excludeField := elem.FieldByName("Exclude")
if excludeField.IsValid() {
// Try to get the field's value as a *multitype.BoolOrString.
excludeValue, ok := excludeField.Interface().(*multitype.BoolOrString)
// If the field's value was successfully obtained and is not nil, and the value is true
if ok && excludeValue != nil {
if excludeValue.BoolOrDefaultFalse() {
numberOfExcludedItems++
}
}
}
}
}
}
}
return numberOfExcludedItems
}