Skip to content

Commit b5d1de9

Browse files
feat: add comparing info in status.conditions
1 parent 3c2230a commit b5d1de9

File tree

2 files changed

+155
-35
lines changed

2 files changed

+155
-35
lines changed

internal/restResources/restResources.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,18 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
196196
log.Debug("Updating status", "error", err)
197197
return controller.ExternalObservation{}, err
198198
}
199-
ok, err := isCRUpdated(mg, *body)
199+
res, err := isCRUpdated(mg, *body)
200200
if err != nil {
201201
log.Debug("Checking if CR is updated", "error", err)
202202
return controller.ExternalObservation{}, err
203203
}
204-
if !ok {
204+
if !res.IsEqual {
205+
cond := condition.Unavailable()
206+
if res.Reason != nil {
207+
cond.Reason = fmt.Sprintf("Resource is not up-to-date due to %s - spec value: %s, remote value: %s", res.Reason.Reason, res.Reason.FirstValue, res.Reason.SecondValue)
208+
}
209+
210+
unstructuredtools.SetCondition(mg, cond)
205211
log.Debug("External resource not up-to-date", "kind", mg.GetKind())
206212
return controller.ExternalObservation{
207213
ResourceExists: true,

internal/restResources/support.go

Lines changed: 147 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,33 @@ func processFields(callInfo *CallInfo, fields map[string]interface{}, reqConfigu
130130
}
131131

132132
// isCRUpdated checks if the CR was updated by comparing the fields in the CR with the response from the API call, if existing cr fields are different from the response, it returns false
133-
func isCRUpdated(mg *unstructured.Unstructured, rm map[string]interface{}) (bool, error) {
133+
func isCRUpdated(mg *unstructured.Unstructured, rm map[string]interface{}) (ComparisonResult, error) {
134134
m, err := unstructuredtools.GetFieldsFromUnstructured(mg, "spec")
135135
if err != nil {
136-
return false, fmt.Errorf("error getting spec fields: %w", err)
136+
return ComparisonResult{
137+
IsEqual: false,
138+
Reason: &Reason{
139+
Reason: "error getting spec fields",
140+
},
141+
}, fmt.Errorf("error getting spec fields: %w", err)
137142
}
138143

139144
return compareExisting(m, rm)
140145
}
141146

147+
type Reason struct {
148+
Reason string
149+
FirstValue any
150+
SecondValue any
151+
}
152+
153+
type ComparisonResult struct {
154+
IsEqual bool
155+
Reason *Reason
156+
}
157+
142158
// compareExisting recursively compares fields between two maps and logs differences.
143-
func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path ...string) (bool, error) {
159+
func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path ...string) (ComparisonResult, error) {
144160
for key, value := range mg {
145161
currentPath := append(path, key)
146162
pathStr := fmt.Sprintf("%v", currentPath)
@@ -150,81 +166,179 @@ func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path
150166
continue
151167
}
152168

153-
fmt.Println("Comparing", pathStr, value, rmValue)
169+
// fmt.Println("Comparing", pathStr, value, rmValue)
154170

155171
if reflect.TypeOf(value).Kind() != reflect.TypeOf(rmValue).Kind() {
156-
return false, fmt.Errorf("types differ at %s - %s is different from %s", pathStr, reflect.TypeOf(value).Kind(), reflect.TypeOf(rmValue).Kind())
172+
return ComparisonResult{
173+
IsEqual: false,
174+
Reason: &Reason{
175+
Reason: "types differ",
176+
FirstValue: value,
177+
SecondValue: rmValue,
178+
},
179+
}, fmt.Errorf("types differ at %s - %s is different from %s", pathStr, reflect.TypeOf(value).Kind(), reflect.TypeOf(rmValue).Kind())
157180
}
158181

159182
switch reflect.TypeOf(value).Kind() {
160183
case reflect.Map:
161184
mgMap, ok1 := value.(map[string]interface{})
162185
if !ok1 {
163-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
164-
return false, fmt.Errorf("type assertion failed for map at %s", pathStr)
186+
// fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
187+
return ComparisonResult{
188+
IsEqual: false,
189+
Reason: &Reason{
190+
Reason: "type assertion failed",
191+
FirstValue: value,
192+
SecondValue: rmValue,
193+
},
194+
}, fmt.Errorf("type assertion failed for map at %s", pathStr)
165195
}
166196
rmMap, ok2 := rmValue.(map[string]interface{})
167197
if !ok2 {
168-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
169-
return false, fmt.Errorf("type assertion failed for map at %s", pathStr)
198+
// fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
199+
return ComparisonResult{
200+
IsEqual: false,
201+
Reason: &Reason{
202+
Reason: "type assertion failed",
203+
FirstValue: value,
204+
SecondValue: rmValue,
205+
},
206+
}, fmt.Errorf("type assertion failed for map at %s", pathStr)
170207
}
171-
ok, err := compareExisting(mgMap, rmMap, currentPath...)
208+
res, err := compareExisting(mgMap, rmMap, currentPath...)
172209
if err != nil {
173-
return false, err
210+
return ComparisonResult{
211+
IsEqual: false,
212+
Reason: &Reason{
213+
Reason: "error comparing maps",
214+
FirstValue: value,
215+
SecondValue: rmValue,
216+
},
217+
}, err
174218
}
175-
if !ok {
176-
fmt.Printf("Values differ at '%s'\n", pathStr)
177-
return false, nil
219+
if !res.IsEqual {
220+
// fmt.Printf("Values differ at '%s'\n", pathStr)
221+
return ComparisonResult{
222+
IsEqual: false,
223+
Reason: &Reason{
224+
Reason: "values differ",
225+
FirstValue: value,
226+
SecondValue: rmValue,
227+
},
228+
}, nil
178229
}
179230
case reflect.Slice:
180231
valueSlice, ok1 := value.([]interface{})
181232
if !ok1 || reflect.TypeOf(rmValue).Kind() != reflect.Slice {
182-
fmt.Printf("Values are not both slices or type assertion failed at '%s'\n", pathStr)
183-
return false, fmt.Errorf("values are not both slices or type assertion failed at %s", pathStr)
233+
// fmt.Printf("Values are not both slices or type assertion failed at '%s'\n", pathStr)
234+
return ComparisonResult{
235+
IsEqual: false,
236+
Reason: &Reason{
237+
Reason: "values are not both slices or type assertion failed",
238+
FirstValue: value,
239+
SecondValue: rmValue,
240+
},
241+
}, fmt.Errorf("values are not both slices or type assertion failed at %s", pathStr)
184242
}
185243
rmSlice, ok2 := rmValue.([]interface{})
186244
if !ok2 {
187-
fmt.Printf("Type assertion failed for slice at '%s'\n", pathStr)
188-
return false, fmt.Errorf("type assertion failed for slice at %s", pathStr)
245+
// fmt.Printf("Type assertion failed for slice at '%s'\n", pathStr)
246+
return ComparisonResult{
247+
IsEqual: false,
248+
Reason: &Reason{
249+
Reason: "values are not both slices or type assertion failed",
250+
FirstValue: value,
251+
SecondValue: rmValue,
252+
},
253+
}, fmt.Errorf("type assertion failed for slice at %s", pathStr)
189254
}
190255
for i, v := range valueSlice {
191256
if reflect.TypeOf(v).Kind() == reflect.Map {
192257
mgMap, ok1 := v.(map[string]interface{})
193258
if !ok1 {
194-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
195-
return false, fmt.Errorf("type assertion failed for map at %s", pathStr)
259+
// fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
260+
return ComparisonResult{
261+
IsEqual: false,
262+
Reason: &Reason{
263+
Reason: "type assertion failed",
264+
FirstValue: value,
265+
SecondValue: rmValue,
266+
},
267+
}, fmt.Errorf("type assertion failed for map at %s", pathStr)
196268
}
197269
rmMap, ok2 := rmSlice[i].(map[string]interface{})
198270
if !ok2 {
199-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
200-
return false, fmt.Errorf("type assertion failed for map at %s", pathStr)
271+
// fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
272+
return ComparisonResult{
273+
IsEqual: false,
274+
Reason: &Reason{
275+
Reason: "type assertion failed",
276+
FirstValue: value,
277+
SecondValue: rmValue,
278+
},
279+
}, fmt.Errorf("type assertion failed for map at %s", pathStr)
201280
}
202-
ok, err := compareExisting(mgMap, rmMap, currentPath...)
281+
res, err := compareExisting(mgMap, rmMap, currentPath...)
203282
if err != nil {
204-
return false, err
283+
return ComparisonResult{
284+
IsEqual: false,
285+
Reason: &Reason{
286+
Reason: "error comparing maps",
287+
FirstValue: value,
288+
SecondValue: rmValue,
289+
},
290+
}, err
205291
}
206-
if !ok {
207-
fmt.Printf("Values differ at '%s'\n", pathStr)
208-
return false, nil
292+
if !res.IsEqual {
293+
// fmt.Printf("Values differ at '%s'\n", pathStr)
294+
return ComparisonResult{
295+
IsEqual: false,
296+
Reason: &Reason{
297+
Reason: "values differ",
298+
FirstValue: value,
299+
SecondValue: rmValue,
300+
},
301+
}, nil
209302
}
210303
} else if v != rmSlice[i] {
211-
fmt.Printf("Values differ at '%s'\n", pathStr)
212-
return false, nil
304+
// fmt.Printf("Values differ at '%s'\n", pathStr)
305+
return ComparisonResult{
306+
IsEqual: false,
307+
Reason: &Reason{
308+
Reason: "values differ",
309+
FirstValue: value,
310+
SecondValue: rmValue,
311+
},
312+
}, nil
213313
}
214314
}
215315
default:
216316
ok, err := compareAny(value, rmValue)
217317
if err != nil {
218-
return false, err
318+
return ComparisonResult{
319+
IsEqual: false,
320+
Reason: &Reason{
321+
Reason: "error comparing values",
322+
FirstValue: value,
323+
SecondValue: rmValue,
324+
},
325+
}, err
219326
}
220327
if !ok {
221-
fmt.Printf("Values differ at '%s' %s %s\n", pathStr, value, rmValue)
222-
return false, nil
328+
// fmt.Printf("Values differ at '%s' %s %s\n", pathStr, value, rmValue)
329+
return ComparisonResult{
330+
IsEqual: false,
331+
Reason: &Reason{
332+
Reason: "values differ",
333+
FirstValue: value,
334+
SecondValue: rmValue,
335+
},
336+
}, nil
223337
}
224338
}
225339
}
226340

227-
return true, nil
341+
return ComparisonResult{IsEqual: true}, nil
228342
}
229343
func numberCaster(value interface{}) int64 {
230344
switch v := value.(type) {

0 commit comments

Comments
 (0)