Skip to content

Commit d64571b

Browse files
fix: correct bugs in values handling (#8)
* fix: correct bugs in values handling * feat: add comparing info in status.conditions * chore: typos
1 parent 118dee6 commit d64571b

File tree

2 files changed

+192
-40
lines changed

2 files changed

+192
-40
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: 184 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -122,23 +122,41 @@ func processFields(callInfo *CallInfo, fields map[string]interface{}, reqConfigu
122122
}
123123
reqConfiguration.Query[field] = stringVal
124124
} else if callInfo.ReqParams.Body.Contains(field) {
125-
mapBody[field] = value
125+
if mapBody[field] == nil {
126+
mapBody[field] = value
127+
}
126128
}
127129
}
128130
}
129131

130132
// 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
131-
func isCRUpdated(mg *unstructured.Unstructured, rm map[string]interface{}) (bool, error) {
133+
func isCRUpdated(mg *unstructured.Unstructured, rm map[string]interface{}) (ComparisonResult, error) {
132134
m, err := unstructuredtools.GetFieldsFromUnstructured(mg, "spec")
133135
if err != nil {
134-
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)
135142
}
136143

137-
return compareExisting(m, rm), nil
144+
return compareExisting(m, rm)
145+
}
146+
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
138156
}
139157

140158
// compareExisting recursively compares fields between two maps and logs differences.
141-
func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path ...string) bool {
159+
func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path ...string) (ComparisonResult, error) {
142160
for key, value := range mg {
143161
currentPath := append(path, key)
144162
pathStr := fmt.Sprintf("%v", currentPath)
@@ -148,63 +166,179 @@ func compareExisting(mg map[string]interface{}, rm map[string]interface{}, path
148166
continue
149167
}
150168

169+
// fmt.Println("Comparing", pathStr, value, rmValue)
170+
171+
if 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())
180+
}
181+
151182
switch reflect.TypeOf(value).Kind() {
152183
case reflect.Map:
153184
mgMap, ok1 := value.(map[string]interface{})
154185
if !ok1 {
155-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
156-
continue
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)
157195
}
158196
rmMap, ok2 := rmValue.(map[string]interface{})
159197
if !ok2 {
160-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
161-
continue
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)
162207
}
163-
if !compareExisting(mgMap, rmMap, currentPath...) {
164-
fmt.Printf("Values differ at '%s'\n", pathStr)
165-
return false
208+
res, err := compareExisting(mgMap, rmMap, currentPath...)
209+
if err != nil {
210+
return ComparisonResult{
211+
IsEqual: false,
212+
Reason: &Reason{
213+
Reason: "error comparing maps",
214+
FirstValue: value,
215+
SecondValue: rmValue,
216+
},
217+
}, err
218+
}
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
166229
}
167230
case reflect.Slice:
168231
valueSlice, ok1 := value.([]interface{})
169232
if !ok1 || reflect.TypeOf(rmValue).Kind() != reflect.Slice {
170-
fmt.Printf("Values are not both slices or type assertion failed at '%s'\n", pathStr)
171-
continue
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)
172242
}
173243
rmSlice, ok2 := rmValue.([]interface{})
174244
if !ok2 {
175-
fmt.Printf("Type assertion failed for slice at '%s'\n", pathStr)
176-
continue
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)
177254
}
178255
for i, v := range valueSlice {
179256
if reflect.TypeOf(v).Kind() == reflect.Map {
180257
mgMap, ok1 := v.(map[string]interface{})
181258
if !ok1 {
182-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
183-
continue
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)
184268
}
185269
rmMap, ok2 := rmSlice[i].(map[string]interface{})
186270
if !ok2 {
187-
fmt.Printf("Type assertion failed for map at '%s'\n", pathStr)
188-
continue
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)
280+
}
281+
res, err := compareExisting(mgMap, rmMap, currentPath...)
282+
if err != nil {
283+
return ComparisonResult{
284+
IsEqual: false,
285+
Reason: &Reason{
286+
Reason: "error comparing maps",
287+
FirstValue: value,
288+
SecondValue: rmValue,
289+
},
290+
}, err
189291
}
190-
if !compareExisting(mgMap, rmMap, currentPath...) {
191-
fmt.Printf("Values differ at '%s'\n", pathStr)
192-
return false
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
193302
}
194303
} else if v != rmSlice[i] {
195-
fmt.Printf("Values differ at '%s'\n", pathStr)
196-
return false
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
197313
}
198314
}
199315
default:
200-
if !compareAny(value, rmValue) {
201-
fmt.Printf("Values differ at '%s' %s %s\n", pathStr, value, rmValue)
202-
return false
316+
ok, err := compareAny(value, rmValue)
317+
if err != nil {
318+
return ComparisonResult{
319+
IsEqual: false,
320+
Reason: &Reason{
321+
Reason: "error comparing values",
322+
FirstValue: value,
323+
SecondValue: rmValue,
324+
},
325+
}, err
326+
}
327+
if !ok {
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
203337
}
204338
}
205339
}
206340

207-
return true
341+
return ComparisonResult{IsEqual: true}, nil
208342
}
209343
func numberCaster(value interface{}) int64 {
210344
switch v := value.(type) {
@@ -237,23 +371,35 @@ func numberCaster(value interface{}) int64 {
237371
}
238372
}
239373

240-
func compareAny(a any, b any) bool {
374+
func compareAny(a any, b any) (bool, error) {
241375
//if is number compare as number
242376
switch a.(type) {
243377
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
244378
ia := numberCaster(a)
245379
ib := numberCaster(b)
246-
return ia == ib
380+
return ia == ib, nil
247381
case string:
248-
sa := a.(string)
249-
sb := b.(string)
250-
return sa == sb
382+
sa, ok := a.(string)
383+
if !ok {
384+
return false, fmt.Errorf("type assertion failed - to string: %v", a)
385+
}
386+
sb, ok := b.(string)
387+
if !ok {
388+
return false, fmt.Errorf("type assertion failed - to string: %v", b)
389+
}
390+
return sa == sb, nil
251391
case bool:
252-
ba := a.(bool)
253-
bb := b.(bool)
254-
return ba == bb
392+
ba, ok := a.(bool)
393+
if !ok {
394+
return false, fmt.Errorf("type assertion failed - to bool: %v", a)
395+
}
396+
bb, ok := b.(bool)
397+
if !ok {
398+
return false, fmt.Errorf("type assertion failed - to bool: %v", b)
399+
}
400+
return ba == bb, nil
255401
default:
256-
return reflect.DeepEqual(a, b)
402+
return reflect.DeepEqual(a, b), nil
257403
}
258404
}
259405

0 commit comments

Comments
 (0)