@@ -5,12 +5,14 @@ import (
55 "path/filepath"
66 "reflect"
77 "strconv"
8+ "strings"
89
910 "github.com/pkg/errors"
1011 troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
1112 "github.com/replicatedhq/troubleshoot/pkg/constants"
1213 iutils "github.com/replicatedhq/troubleshoot/pkg/interfaceutils"
1314 "gopkg.in/yaml.v2"
15+ "k8s.io/apimachinery/pkg/api/resource"
1416 "k8s.io/klog/v2"
1517)
1618
@@ -108,6 +110,133 @@ func FindResource(kind string, clusterScoped bool, namespace string, name string
108110
109111}
110112
113+ func compareWhentoResource (w string , actual interface {}) (bool , error ) {
114+
115+ // check our "when" has operators
116+ var whenSplit []string
117+ if strings .ContainsAny (w , "!=<>" ) {
118+ whenSplit = strings .Split (strings .TrimSpace (w ), " " )
119+ } else {
120+ return false , errors .New ("no operators found" )
121+ }
122+
123+ // let's first check if we can cast "actual" as an int, that should inform us what comparison we're doing
124+ actualAsInt , ok := actual .(int )
125+ if ok {
126+ // it's an int! we can do integer comparison here
127+ // we're going to re-use an ill-fitting bit of code from the deployment analyzer for now
128+ return compareActualToWhen (w , actualAsInt )
129+ }
130+
131+ // if we've fallen through here we're going to have to try a bit harder to work out what we're comparing
132+ // let's try making it a string
133+ actualAsString , ok := actual .(string )
134+ if ! ok {
135+ return false , errors .New ("could not cast found value as string" )
136+ }
137+
138+ // now we can try checking if it's a "quantity"
139+ actualASQuantity , err := resource .ParseQuantity (actualAsString )
140+ if err == nil {
141+ // it's probably a size, we can do some comparison here
142+ // but I'm being lazy here so we'll convert our last argument to an int and throw it back at our existing int comparison function
143+ whenAsQuantity , err := resource .ParseQuantity (whenSplit [1 ])
144+ if err != nil {
145+ // our when wasn't a size! naughty user
146+ return false , errors .New ("Cannot compare size with not size" )
147+ }
148+ whenIntAsString := strconv .FormatInt (whenAsQuantity .Value (), 10 )
149+ // re-use that same compare function from earlier, might as well
150+ return compareActualToWhen (whenSplit [0 ]+ " " + whenIntAsString , int (actualASQuantity .Value ()))
151+
152+ }
153+
154+ return false , errors .New ("could not match comparison method for result" )
155+ }
156+
157+ func analyzeWhenField (actual interface {}, outcomes []* troubleshootv1beta2.Outcome , checkName string ) (* AnalyzeResult , error ) {
158+
159+ result := & AnalyzeResult {
160+ Title : checkName ,
161+ IconKey : "kubernetes_text_analyze" ,
162+ IconURI : "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg?w=13&h=16" ,
163+ }
164+
165+ for _ , outcome := range outcomes {
166+ if outcome .Fail != nil {
167+ if outcome .Fail .When != "" {
168+ compareResult , err := compareWhentoResource (outcome .Fail .When , actual )
169+ if err != nil {
170+ return nil , errors .Wrapf (err , "failed to process when statement: %s" , outcome .Fail .When )
171+ }
172+ if compareResult {
173+ result .IsFail = true
174+ result .Message = outcome .Fail .Message
175+ result .URI = outcome .Fail .URI
176+ return result , nil
177+ }
178+ } else {
179+ result .IsFail = true
180+ result .Message = outcome .Fail .Message
181+ result .URI = outcome .Fail .URI
182+
183+ return result , nil
184+ }
185+ }
186+ if outcome .Warn != nil {
187+
188+ if outcome .Warn .When != "" {
189+ compareResult , err := compareWhentoResource (outcome .Fail .When , actual )
190+ if err != nil {
191+ return nil , errors .Wrapf (err , "failed to process when statement: %s" , outcome .Warn .When )
192+ }
193+ if compareResult {
194+ result .IsWarn = true
195+ result .Message = outcome .Warn .Message
196+ result .URI = outcome .Warn .URI
197+ return result , nil
198+ }
199+ } else {
200+ result .IsWarn = true
201+ result .Message = outcome .Warn .Message
202+ result .URI = outcome .Warn .URI
203+
204+ return result , nil
205+ }
206+
207+ }
208+ if outcome .Pass != nil {
209+
210+ if outcome .Pass .When != "" {
211+ compareResult , err := compareWhentoResource (outcome .Pass .When , actual )
212+ if err != nil {
213+ return nil , errors .Wrapf (err , "failed to process when statement: %s" , outcome .Pass .When )
214+ }
215+ if compareResult {
216+ result .IsPass = true
217+ result .Message = outcome .Pass .Message
218+ result .URI = outcome .Pass .URI
219+ return result , nil
220+ }
221+ } else {
222+ result .IsPass = true
223+ result .Message = outcome .Pass .Message
224+ result .URI = outcome .Pass .URI
225+
226+ return result , nil
227+ }
228+ }
229+ }
230+
231+ return & AnalyzeResult {
232+ Title : checkName ,
233+ IconKey : "kubernetes_text_analyze" ,
234+ IconURI : "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg" ,
235+ IsFail : true ,
236+ Message : "Invalid analyzer" ,
237+ }, nil
238+ }
239+
111240func (a * AnalyzeClusterResource ) analyzeResource (analyzer * troubleshootv1beta2.ClusterResource , getFileContents getCollectedFileContents ) (* AnalyzeResult , error ) {
112241 selected , err := FindResource (analyzer .Kind , analyzer .ClusterScoped , analyzer .Namespace , analyzer .Name , getFileContents )
113242 if err != nil {
@@ -168,6 +297,15 @@ func (a *AnalyzeClusterResource) analyzeResource(analyzer *troubleshootv1beta2.C
168297 if result != nil {
169298 return result , nil
170299 }
300+ } else {
301+ // fall through to comparing from the when key
302+ result , err := analyzeWhenField (actual , analyzer .Outcomes , a .Title ())
303+ if err != nil {
304+ return nil , err
305+ }
306+ if result != nil {
307+ return result , nil
308+ }
171309 }
172310
173311 return & AnalyzeResult {
0 commit comments