diff --git a/agents/diam_it_test.go b/agents/diam_it_test.go index bdf6a2e37..aded2d18c 100644 --- a/agents/diam_it_test.go +++ b/agents/diam_it_test.go @@ -50,15 +50,15 @@ var sTestsDiam = []func(t *testing.T){ testDiamItInitCfg, testDiamItResetDataDb, testDiamItResetStorDb, - //testDiamItStartEngine, + testDiamItStartEngine, testDiamItConnectDiameterClient, testDiamItApierRpcConn, testDiamItTPFromFolder, testDiamItDryRun, - //testDiamItCCRInit, - //testDiamItCCRUpdate, - //testDiamItCCRTerminate, - //testDiamItCCRSMS, + testDiamItCCRInit, + testDiamItCCRUpdate, + testDiamItCCRTerminate, + testDiamItCCRSMS, testDiamItKillEngine, } diff --git a/agents/diamagent.go b/agents/diamagent.go index 6d4ea7fd5..7388a4982 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -211,7 +211,6 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.DARequestProcessor, reqProcessor.Filters, agReq); err != nil || !pass { return pass, err } - fmt.Printf("processRequest, processor: %s, agreq: %s\n", utils.ToJSON(reqProcessor), utils.ToJSON(agReq)) if agReq.CGRRequest, err = agReq.AsNavigableMap(reqProcessor.RequestFields); err != nil { return } @@ -318,8 +317,8 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.DARequestProcessor, } if nM, err := agReq.AsNavigableMap(reqProcessor.ReplyFields); err != nil { return false, err - } else if err := agReq.Reply.Merge(nM); err != nil { - return false, err + } else { + agReq.Reply.Merge(nM) } if reqType == utils.MetaDryRun { utils.Logger.Info( diff --git a/config/navigablemap.go b/config/navigablemap.go index 9fc1a2e4b..27be2c75b 100644 --- a/config/navigablemap.go +++ b/config/navigablemap.go @@ -92,6 +92,7 @@ func (nM *NavigableMap) Set(path []string, data interface{}, apnd, ordered bool) // FieldAsInterface returns the field value as interface{} for the path specified // implements DataProvider +// supports spath with selective elements in case of []*NMItem func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) { lenPath := len(fldPath) if lenPath == 0 { @@ -101,6 +102,10 @@ func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, var canCast bool for i, spath := range fldPath { if i == lenPath-1 { // lastElement + if idxStart := strings.Index(spath, utils.IdxStart); idxStart != -1 && + strings.HasSuffix(spath, utils.IdxEnd) { + spath = spath[:idxStart] // ignore the selector for now since it is processed in other places + } var has bool fldVal, has = lastMp[spath] if !has { @@ -182,28 +187,27 @@ func (nM *NavigableMap) AsNavigableMap( } // Merge will update nM with values from a second one -func (nM *NavigableMap) Merge(nM2 *NavigableMap) (err error) { +func (nM *NavigableMap) Merge(nM2 *NavigableMap) { if nM2 == nil { return } - for k, v := range nM2.data { - oV, has := nM.data[k] - if !has { - nM.data[k] = v - continue - } - if oItms, isNMItems := oV.([]*NMItem); isNMItems { - vItms, isItms := v.([]*NMItem) - if !isItms { - return utils.ErrIncompatible - } - oItms = append(oItms, vItms...) - continue - } - nM.data[k] = v + if len(nM2.order) == 0 { + indexMapPaths(nM2.data, nil, &nM.order) } - if len(nM2.order) != 0 { - nM.order = append(nM.order, nM2.order...) + pathIdx := make(map[string]int) // will hold references for last index exported in case of []*NMItem + for _, path := range nM2.order { + val, _ := nM2.FieldAsInterface(path) + if valItms, isItms := val.([]*NMItem); isItms { + pathStr := strings.Join(path, utils.NestingSep) + pathIdx[pathStr] += 1 + if pathIdx[pathStr] > len(valItms) { + val = valItms[len(valItms)-1:] // slice with only last element in, so we can set it unlimited + } else { + val = []*NMItem{valItms[pathIdx[pathStr]-1]} // set only one item per path + } + } + nM.Set(path, val, true, + (len(nM.order) != 0 || len(nM.data) == 0)) } return } diff --git a/config/navigablemap_test.go b/config/navigablemap_test.go index 8b7bda8f1..ddcdca390 100644 --- a/config/navigablemap_test.go +++ b/config/navigablemap_test.go @@ -841,3 +841,35 @@ func TestNavMapAsCGREvent(t *testing.T) { t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(eEv), utils.ToJSON(cgrEv.Event)) } } + +func TestNavMapMerge(t *testing.T) { + nM2 := &NavigableMap{ + data: map[string]interface{}{ + "FirstLevel": map[string]interface{}{ + "SecondLevel": map[string]interface{}{ + "ThirdLevel": map[string]interface{}{ + "Fld1": []*NMItem{ + { + Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + Data: "Val1", + }, + { + Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + Data: "Val2", + }, + }, + }, + }, + }, + }, + order: [][]string{ + {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + }, + } + nM := NewNavigableMap(nil) + nM.Merge(nM2) + if !reflect.DeepEqual(nM2, nM) { + t.Errorf("expecting: %+v, received: %+v", nM2, nM) + } +} diff --git a/data/conf/samples/diamagent/dryrun.json b/data/conf/samples/diamagent/dryrun.json index 39f6f26a5..4e3e78df3 100644 --- a/data/conf/samples/diamagent/dryrun.json +++ b/data/conf/samples/diamagent/dryrun.json @@ -6,6 +6,7 @@ "id": "dryrun1", "filters": ["*string:*vars.*cmd:CCR", "*string:*req.Service-Context-Id:TestDiamItDryRun"], "flags": ["*dryrun"], + "continue_on_success": true, "request_fields":[ {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"}, {"tag": "Val1", "field_id": "Val1", "type": "*constant", "value": "1"}, @@ -38,7 +39,7 @@ }, { "id": "dryrun2", - "filters": ["*rsr::~*rep.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(1)](!^$)"], // make sure the CC-Total-Octets was populated in the previous processor + "filters": ["*rsr::~*rep.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[0](!^$)"], // make sure the CC-Total-Octets was populated in the previous processor "flags": ["*dryrun"], "request_fields":[ {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"}, diff --git a/utils/consts.go b/utils/consts.go index 39638d662..41aedb7e1 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -535,6 +535,8 @@ const ( OriginRealm = "OriginRealm" ProductName = "ProductName" CGRSubsystems = "cgr_subsystems" + IdxStart = "[" + IdxEnd = "]" ) // Migrator Action