DiameterAgent - support for sharing group variables via request processors, fixes #1302

This commit is contained in:
DanB
2018-11-15 18:48:43 +01:00
parent 4d94021a1d
commit 55f853c1cc
6 changed files with 65 additions and 27 deletions

View File

@@ -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,
}

View File

@@ -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(

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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"},

View File

@@ -535,6 +535,8 @@ const (
OriginRealm = "OriginRealm"
ProductName = "ProductName"
CGRSubsystems = "cgr_subsystems"
IdxStart = "["
IdxEnd = "]"
)
// Migrator Action