engine: graph: Allow Recv overriding for Send/Recv

This allows us to pass in an alternate implementation for Recv, if we
want to temporarily use a different data source.
This commit is contained in:
James Shubin
2024-01-20 03:21:10 -05:00
parent 091bf3a64c
commit 1630eafbe3
2 changed files with 15 additions and 4 deletions

View File

@@ -121,7 +121,7 @@ func (obj *Engine) Process(ctx context.Context, vertex pgraph.Vertex) error {
if obj.Debug { if obj.Debug {
obj.Logf("SendRecv: %s", res) // receiving here obj.Logf("SendRecv: %s", res) // receiving here
} }
if updated, err := SendRecv(res); err != nil { if updated, err := SendRecv(res, nil); err != nil {
return errwrap.Wrapf(err, "could not SendRecv") return errwrap.Wrapf(err, "could not SendRecv")
} else if len(updated) > 0 { } else if len(updated) > 0 {
//for _, s := range graph.UpdatedStrings(updated) { //for _, s := range graph.UpdatedStrings(updated) {

View File

@@ -28,12 +28,17 @@ import (
"github.com/purpleidea/mgmt/util/errwrap" "github.com/purpleidea/mgmt/util/errwrap"
) )
// RecvFn represents a custom Recv function which can be used in place of the
// stock, built-in one. This is needed if we want to receive from a different
// resource data source than our own. (Only for special occasions of course!)
type RecvFn func(engine.RecvableRes) (map[string]*engine.Send, error)
// SendRecv pulls in the sent values into the receive slots. It is called by the // SendRecv pulls in the sent values into the receive slots. It is called by the
// receiver and must be given as input the full resource struct to receive on. // receiver and must be given as input the full resource struct to receive on.
// It applies the loaded values to the resource. It is called recursively, as it // It applies the loaded values to the resource. It is called recursively, as it
// recurses into any grouped resources found within the first receiver. It // recurses into any grouped resources found within the first receiver. It
// returns a map of resource pointer, to resource field key, to changed boolean. // returns a map of resource pointer, to resource field key, to changed boolean.
func SendRecv(res engine.RecvableRes) (map[engine.RecvableRes]map[string]*engine.Send, error) { func SendRecv(res engine.RecvableRes, fn RecvFn) (map[engine.RecvableRes]map[string]*engine.Send, error) {
updated := make(map[engine.RecvableRes]map[string]*engine.Send) // list of updated keys updated := make(map[engine.RecvableRes]map[string]*engine.Send) // list of updated keys
if groupableRes, ok := res.(engine.GroupableRes); ok { if groupableRes, ok := res.(engine.GroupableRes); ok {
for _, x := range groupableRes.GetGroup() { // grouped elements for _, x := range groupableRes.GetGroup() { // grouped elements
@@ -49,7 +54,7 @@ func SendRecv(res engine.RecvableRes) (map[engine.RecvableRes]map[string]*engine
// work correctly. We just need to make sure that things // work correctly. We just need to make sure that things
// are grouped in the correct order, but that is not our // are grouped in the correct order, but that is not our
// problem! Recurse and merge in the changed results... // problem! Recurse and merge in the changed results...
innerUpdated, err := SendRecv(recvableRes) innerUpdated, err := SendRecv(recvableRes, fn)
if err != nil { if err != nil {
return nil, errwrap.Wrapf(err, "recursive SendRecv error") return nil, errwrap.Wrapf(err, "recursive SendRecv error")
} }
@@ -77,7 +82,14 @@ func SendRecv(res engine.RecvableRes) (map[engine.RecvableRes]map[string]*engine
} }
} }
var err error
recv := res.Recv() recv := res.Recv()
if fn != nil {
recv, err = fn(res) // use a custom Recv function
if err != nil {
return nil, err
}
}
keys := []string{} keys := []string{}
for k := range recv { // map[string]*Send for k := range recv { // map[string]*Send
keys = append(keys, k) keys = append(keys, k)
@@ -87,7 +99,6 @@ func SendRecv(res engine.RecvableRes) (map[engine.RecvableRes]map[string]*engine
// // NOTE: this could expose private resource data like passwords // // NOTE: this could expose private resource data like passwords
// obj.Logf("SendRecv: %s recv: %+v", res, strings.Join(keys, ", ")) // obj.Logf("SendRecv: %s recv: %+v", res, strings.Join(keys, ", "))
//} //}
var err error
for k, v := range recv { // map[string]*Send for k, v := range recv { // map[string]*Send
// v.Res // SendableRes // a handle to the resource which is sending a value // v.Res // SendableRes // a handle to the resource which is sending a value
// v.Key // string // the key in the resource that we're sending // v.Key // string // the key in the resource that we're sending