Skip to content

Commit 44bc4a6

Browse files
authored
Fix existing query result propagation in case of the skip (#51)
Fix the refactoring-related bug that led to query target field losing the data in case of skip Preserve oxr and context data from the previous reconciliation loop Signed-off-by: Yury Tsarev <[email protected]>
1 parent cd4ee58 commit 44bc4a6

File tree

2 files changed

+502
-215
lines changed

2 files changed

+502
-215
lines changed

fn.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1.RunFunctionRequest
4040

4141
rsp := response.To(req, response.DefaultTTL)
4242

43+
// Ensure oxr to dxr gets propagated and we keep status around
44+
if err := f.propagateDesiredXR(req, rsp); err != nil {
45+
return rsp, nil //nolint:nilerr // errors are handled in rsp. We should not error main function and proceed with reconciliation
46+
}
47+
// Ensure the context is preserved
48+
f.preserveContext(req, rsp)
49+
4350
// Parse input and get credentials
4451
in, azureCreds, err := f.parseInputAndCredentials(req, rsp)
4552
if err != nil {
@@ -66,6 +73,9 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1.RunFunctionRequest
6673

6774
// Check if we should skip the query
6875
if f.shouldSkipQuery(req, in, rsp) {
76+
// Set success condition
77+
response.ConditionTrue(rsp, "FunctionSuccess", "Success").
78+
TargetCompositeAndClaim()
6979
return rsp, nil
7080
}
7181

@@ -174,9 +184,11 @@ func (f *Function) checkStatusTargetHasData(req *fnv1.RunFunctionRequest, in *v1
174184

175185
xrStatus := make(map[string]interface{})
176186
err = oxr.Resource.GetValueInto("status", &xrStatus)
187+
177188
if err == nil {
178189
// Check if the target field already has data
179190
statusField := strings.TrimPrefix(in.Target, "status.")
191+
180192
if hasData, _ := targetHasData(xrStatus, statusField); hasData {
181193
f.log.Info("Target already has data, skipping query", "target", in.Target)
182194

@@ -187,6 +199,8 @@ func (f *Function) checkStatusTargetHasData(req *fnv1.RunFunctionRequest, in *v1
187199
return true
188200
}
189201
}
202+
203+
// If we got here, either there was an error or the field doesn't have data
190204
return false
191205
}
192206

@@ -531,3 +545,58 @@ func targetHasData(data map[string]interface{}, key string) (bool, error) {
531545
// For other types (numbers, booleans), consider them as having data
532546
return true, nil
533547
}
548+
549+
// propagateDesiredXR ensures the desired XR is properly propagated without changing existing data
550+
func (f *Function) propagateDesiredXR(req *fnv1.RunFunctionRequest, rsp *fnv1.RunFunctionResponse) error {
551+
oxr, err := request.GetObservedCompositeResource(req)
552+
if err != nil {
553+
response.Fatal(rsp, errors.Wrap(err, "cannot get observed composite resource"))
554+
return err
555+
}
556+
557+
// The composite resource desired by previous functions in the pipeline
558+
dxr, err := request.GetDesiredCompositeResource(req)
559+
if err != nil {
560+
response.Fatal(rsp, errors.Wrap(err, "cannot get desired composite resource"))
561+
return err
562+
}
563+
564+
// If dxr is empty, initialize it from oxr
565+
if dxr.Resource.GetKind() == "" {
566+
f.log.Info("Initializing Desired XR from Observed XR")
567+
dxr.Resource.SetAPIVersion(oxr.Resource.GetAPIVersion())
568+
dxr.Resource.SetKind(oxr.Resource.GetKind())
569+
dxr.Resource.SetName(oxr.Resource.GetName())
570+
571+
// Copy status from observed XR
572+
xrStatus := make(map[string]interface{})
573+
err = oxr.Resource.GetValueInto("status", &xrStatus)
574+
if err == nil && len(xrStatus) > 0 {
575+
f.log.Info("Copying status from Observed XR to Desired XR")
576+
if err := dxr.Resource.SetValue("status", xrStatus); err != nil {
577+
f.log.Info("Error setting status in Desired XR", "error", err)
578+
return err
579+
}
580+
}
581+
}
582+
583+
// Save the desired XR in the response
584+
if err := response.SetDesiredCompositeResource(rsp, dxr); err != nil {
585+
response.Fatal(rsp, errors.Wrapf(err, "cannot set desired composite resource in %T", rsp))
586+
return err
587+
}
588+
589+
f.log.Info("Successfully propagated Desired XR")
590+
return nil
591+
}
592+
593+
// preserveContext ensures the context is preserved in the response
594+
func (f *Function) preserveContext(req *fnv1.RunFunctionRequest, rsp *fnv1.RunFunctionResponse) {
595+
// Get the existing context from the request
596+
existingContext := req.GetContext()
597+
if existingContext != nil {
598+
// Copy the existing context to the response
599+
rsp.Context = existingContext
600+
f.log.Info("Preserved existing context in response")
601+
}
602+
}

0 commit comments

Comments
 (0)