NavigableMap with ordered items

This commit is contained in:
DanB
2018-06-13 18:34:42 +02:00
parent 20651341ed
commit 73552ef89c
16 changed files with 169 additions and 104 deletions

View File

@@ -60,7 +60,7 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
var processed bool
procVars := make(processorVars)
rpl := newHTTPReplyFields()
rpl := engine.NewNavigableMap(nil)
for _, reqProcessor := range ha.reqProcessors {
var lclProcessed bool
if lclProcessed, err = ha.processRequest(reqProcessor, dcdr,
@@ -101,8 +101,7 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// processRequest represents one processor processing the request
func (ha *HTTPAgent) processRequest(reqProcessor *config.HttpAgntProcCfg,
dP engine.DataProvider, procVars processorVars,
reply *httpReplyFields) (processed bool, err error) {
reply *engine.NavigableMap) (processed bool, err error) {
tnt, err := dP.FieldAsString([]string{utils.Tenant})
if err != nil {
return false, err
@@ -116,11 +115,11 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.HttpAgntProcCfg,
procVars[k] = strconv.FormatBool(v)
}
if reqProcessor.DryRun {
utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, RADIUS request: %s", utils.RadiusAgent, dP))
utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, process variabiles: %+v", utils.RadiusAgent, procVars))
utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, HTTP request: %s", utils.HTTPAgent, dP))
utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, process variables: %+v", utils.HTTPAgent, procVars))
}
/*
cgrEv, err := radReqAsCGREvent(req, procVars, reqProcessor.Flags, reqProcessor.RequestFields)
ev, err := radReqAsCGREvent(req, procVars, reqProcessor.Flags, reqProcessor.RequestFields)
if err != nil {
return false, err
}

View File

@@ -27,7 +27,6 @@ import (
"time"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/sessions"
"github.com/cgrates/cgrates/utils"
"github.com/fiorix/go-diameter/diam"
@@ -215,24 +214,35 @@ func TestFieldOutVal(t *testing.T) {
t.Errorf("Expecting:\n%s\nReceived:\n%s", eOut, fldOut)
}
// Without groupedAVP, we shoud get the first subscriptionId
cfgFld = &config.CfgCdrField{Tag: "Grouped2", Type: utils.MetaGrouped, FieldId: "Account",
FieldFilter: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Type(1)", utils.INFIELD_SEP),
Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true}
cfgFld = &config.CfgCdrField{
Tag: "Grouped2",
Type: utils.MetaGrouped, FieldId: "Account",
FieldFilter: utils.ParseRSRFieldsMustCompile(
"Subscription-Id>Subscription-Id-Type(1)", utils.INFIELD_SEP),
Value: utils.ParseRSRFieldsMustCompile(
"Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true}
eOut = "208708000003"
if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0), nil); err != nil {
t.Error(err)
} else if fldOut != eOut {
t.Errorf("Expecting:\n%s\nReceived:\n%s", eOut, fldOut)
}
cfgFld = &config.CfgCdrField{Tag: "TestMultipleFiltersEmptyReply", Type: utils.META_COMPOSED, FieldId: "Account",
FieldFilter: utils.ParseRSRFieldsMustCompile("*cgrReply>Error(^$);*cgrReply>MaxUsage(!300);*cgrReply>MaxUsage(!0)", utils.INFIELD_SEP),
Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true}
cfgFld = &config.CfgCdrField{
Tag: "TestMultipleFiltersEmptyReply",
Type: utils.META_COMPOSED, FieldId: "Account",
FieldFilter: utils.ParseRSRFieldsMustCompile(
"*cgrReply>Error(^$);*cgrReply>MaxUsage(!300);*cgrReply>MaxUsage(!0)",
utils.INFIELD_SEP),
Value: utils.ParseRSRFieldsMustCompile(
"Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP),
Mandatory: true}
procVars := processorVars{
utils.MetaCGRReply: engine.NavigableMap{
utils.MetaCGRReply: map[string]interface{}{
utils.Error: "RALS_ERROR:NOT_FOUND",
},
}
if _, err := fieldOutVal(m, cfgFld, time.Duration(0), procVars); err != ErrFilterNotPassing {
if _, err := fieldOutVal(m, cfgFld, time.Duration(0),
procVars); err != ErrFilterNotPassing {
t.Error(err)
}
}

View File

@@ -25,24 +25,6 @@ import (
"github.com/cgrates/cgrates/engine"
)
// httpReplyField is one field written in HTTP reply
type httpReplyField struct {
fldPath string
fldVal string
}
func newHTTPReplyFields() *httpReplyFields {
return &httpReplyFields{indexed: make(map[string]*httpReplyField),
ordered: make([]*httpReplyField, 0)}
}
// httpReplyFields is the reply which will be written to HTTP
// both flds and ordered are pointig towards same httpReplyField
type httpReplyFields struct {
indexed map[string]*httpReplyField // map[fldPath]*httpReplyField
ordered []*httpReplyField // keep order for export
}
// newHAReqDecoder produces decoders
func newHADataProvider(dpType string,
req *http.Request) (dP engine.DataProvider, err error) {
@@ -61,8 +43,8 @@ func newHAReplyEncoder(encType string,
}
}
// httpAgentReplyEncoder will encode fields from httpReplyFields
// httpAgentReplyEncoder will encode []*engine.NMElement
// and write content to http writer
type httpAgentReplyEncoder interface {
encode(*httpReplyFields) error
encode(*engine.NavigableMap) error
}

View File

@@ -62,7 +62,7 @@ func (pv processorVars) valAsInterface(fldPath string) (val interface{}, err err
err = errors.New("not found")
return
}
return engine.NavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP))
return engine.NewNavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP))
}
// valAsString returns the string value for fldName
@@ -75,7 +75,7 @@ func (pv processorVars) valAsString(fldPath string) (val string, err error) {
if !pv.hasVar(fldName) {
return "", utils.ErrNotFoundNoCaps
}
return engine.NavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP))
return engine.NewNavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP))
}
// asV1AuthorizeArgs returns the arguments needed by SessionSv1.AuthorizeEvent
@@ -411,6 +411,7 @@ func NewCGRReply(rply engine.NavigableMapper,
if err != nil {
return nil, err
}
nM[utils.Error] = "" // enforce empty error
return map[string]interface{}(nM), nil // convert from NM to map due to decapsulation later
mp = nM.AsMapStringInterface()
mp[utils.Error] = "" // enforce empty error
return mp, nil
}

View File

@@ -428,8 +428,8 @@ func TestRadReplyAppendAttributes(t *testing.T) {
type myEv map[string]interface{}
func (ev myEv) AsNavigableMap(tpl []*config.CfgCdrField) (engine.NavigableMap, error) {
return engine.NavigableMap(ev), nil
func (ev myEv) AsNavigableMap(tpl []*config.CfgCdrField) (*engine.NavigableMap, error) {
return engine.NewNavigableMap(ev), nil
}
func TestNewCGRReply(t *testing.T) {
@@ -439,7 +439,8 @@ func TestNewCGRReply(t *testing.T) {
if rpl, err := NewCGRReply(nil, errors.New("some")); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCgrRply, rpl) {
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eCgrRply), utils.ToJSON(rpl))
t.Errorf("Expecting: %+v, received: %+v",
utils.ToJSON(eCgrRply), utils.ToJSON(rpl))
}
ev := myEv{
"FirstLevel": map[string]interface{}{

View File

@@ -91,7 +91,7 @@ func (alS *AttributeService) matchingAttributeProfilesForEvent(ev *utils.CGREven
continue
}
if pass, err := alS.filterS.Pass(ev.Tenant, aPrfl.FilterIDs,
NavigableMap(ev.Event)); err != nil {
NewNavigableMap(ev.Event)); err != nil {
return nil, err
} else if !pass {
continue

View File

@@ -1456,6 +1456,6 @@ func (cd *CallDescriptor) String() string {
}
// AsNavigableMap is part of utils.DataProvider
func (cd *CallDescriptor) AsNavigableMap(tpl []*config.CfgCdrField) (nM NavigableMap, err error) {
return
func (cd *CallDescriptor) AsNavigableMap(tpl []*config.CfgCdrField) (nM *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}

View File

@@ -27,5 +27,5 @@ type DataProvider interface {
FieldAsInterface(fldPath []string) (interface{}, error)
FieldAsString(fldPath []string) (string, error)
String() string // printable versin of data
AsNavigableMap(cfgFlds []*config.CfgCdrField) (NavigableMap, error)
AsNavigableMap([]*config.CfgCdrField) (*NavigableMap, error)
}

View File

@@ -154,16 +154,16 @@ func TestFilterPassGreaterThan(t *testing.T) {
if err != nil {
t.Error(err)
}
ev := NavigableMap{
"ASR": 20,
ev := &NavigableMap{
data: map[string]interface{}{"ASR": 20},
}
if passes, err := rf.passGreaterThan(ev); err != nil {
t.Error(err)
} else if !passes {
t.Error("not passing")
}
ev = map[string]interface{}{
"ASR": 40,
ev = &NavigableMap{
data: map[string]interface{}{"ASR": 40},
}
if passes, err := rf.passGreaterThan(ev); err != nil {
t.Error(err)
@@ -188,8 +188,8 @@ func TestFilterPassGreaterThan(t *testing.T) {
} else if !passes {
t.Error("not passing")
}
ev = map[string]interface{}{
"ASR": 20,
ev = &NavigableMap{
data: map[string]interface{}{"ASR": 20},
}
if passes, err := rf.passGreaterThan(ev); err != nil {
t.Error(err)
@@ -200,8 +200,8 @@ func TestFilterPassGreaterThan(t *testing.T) {
if err != nil {
t.Error(err)
}
ev = map[string]interface{}{
"ACD": time.Duration(2 * time.Minute),
ev = &NavigableMap{
data: map[string]interface{}{"ACD": time.Duration(2 * time.Minute)},
}
if passes, err := rf.passGreaterThan(ev); err != nil {
t.Error(err)
@@ -296,13 +296,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
t.Errorf(err.Error())
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:Account:1007"}, NavigableMap(failEvent)); err != nil {
[]string{"*string:Account:1007"}, NewNavigableMap(failEvent)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:Account:1007"}, NavigableMap(passEvent)); err != nil {
[]string{"*string:Account:1007"}, NewNavigableMap(passEvent)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
@@ -314,13 +314,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
"Account": "1007",
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*prefix:Account:10"}, NavigableMap(failEvent)); err != nil {
[]string{"*prefix:Account:10"}, NewNavigableMap(failEvent)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*prefix:Account:10"}, NavigableMap(passEvent)); err != nil {
[]string{"*prefix:Account:10"}, NewNavigableMap(passEvent)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
@@ -332,13 +332,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
"Tenant": "cgrates.org",
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(failEvent)); err != nil {
[]string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NewNavigableMap(failEvent)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(passEvent)); err != nil {
[]string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NewNavigableMap(passEvent)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
@@ -352,13 +352,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
utils.Destination: "+4986517174963",
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*destinations:Destination:EU"}, NavigableMap(failEvent)); err != nil {
[]string{"*destinations:Destination:EU"}, NewNavigableMap(failEvent)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*destinations:Destination:EU_LANDLINE"}, NavigableMap(passEvent)); err != nil {
[]string{"*destinations:Destination:EU_LANDLINE"}, NewNavigableMap(passEvent)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
@@ -370,13 +370,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
utils.Weight: 20,
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*gte:Weight:20"}, NavigableMap(failEvent)); err != nil {
[]string{"*gte:Weight:20"}, NewNavigableMap(failEvent)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*gte:Weight:10"}, NavigableMap(passEvent)); err != nil {
[]string{"*gte:Weight:10"}, NewNavigableMap(passEvent)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
@@ -404,13 +404,13 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) {
utils.Weight: 20,
}
if pass, err := filterS.Pass("cgrates.org",
[]string{}, NavigableMap(passEvent1)); err != nil {
[]string{}, NewNavigableMap(passEvent1)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("itsyscom.com",
[]string{}, NavigableMap(passEvent2)); err != nil {
[]string{}, NewNavigableMap(passEvent2)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)

View File

@@ -28,20 +28,50 @@ import (
// CGRReplier is the interface supported by replies convertible to CGRReply
type NavigableMapper interface {
AsNavigableMap([]*config.CfgCdrField) (NavigableMap, error)
AsNavigableMap([]*config.CfgCdrField) (*NavigableMap, error)
}
// NewNavigableMap constructs a NavigableMap
func NewNavigableMap(data map[string]interface{}) *NavigableMap {
if data == nil {
data = make(map[string]interface{})
}
return &NavigableMap{data: data}
}
// NavigableMap is a map who's values can be navigated via path
type NavigableMap map[string]interface{}
// data can be retrieved as ordered
// NavigableMap is not thread safe due to performance demands, could come back if needed
type NavigableMap struct {
data map[string]interface{} // layered map
order [][]string // order of field paths
}
// Add will add items into NavigableMap populating also order
func (nM *NavigableMap) Add(path []string, data interface{}) {
nM.order = append(nM.order)
mp := nM.data
for i, spath := range path {
_, has := mp[spath]
if !has {
if i == len(path)-1 { // last path
mp[spath] = data
return
}
mp[spath] = make(map[string]interface{})
}
mp = mp[spath].(map[string]interface{}) // so we can check further down
}
}
// FieldAsInterface returns the field value as interface{} for the path specified
// implements DataProvider
func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) {
func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) {
lenPath := len(fldPath)
if lenPath == 0 {
return nil, errors.New("empty field path")
}
lastMp := nM // last map when layered
lastMp := nM.data // last map when layered
var canCast bool
for i, spath := range fldPath {
if i == lenPath-1 { // lastElement
@@ -71,7 +101,7 @@ func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, e
// FieldAsString returns the field value as string for the path specified
// implements DataProvider
func (nM NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error) {
func (nM *NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error) {
var valIface interface{}
valIface, err = nM.FieldAsInterface(fldPath)
if err != nil {
@@ -84,11 +114,51 @@ func (nM NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error
return
}
func (nM NavigableMap) String() string {
return utils.ToJSON(nM)
func (nM *NavigableMap) String() string {
return utils.ToJSON(nM.data)
}
// AsMapStringInterface returns the data out of map, ignoring the order part
func (nM *NavigableMap) AsMapStringInterface() map[string]interface{} {
return nM.data
}
type NMItem struct {
Path []string // path in map
Data interface{} // value of the element
}
// indexMapElements will recursively go through map and index the element paths into elmns
func indexMapElements(mp map[string]interface{}, path []string, elms *[]*NMItem) {
for k, v := range mp {
vPath := append(path, k)
if mpIface, isMap := v.(map[string]interface{}); isMap {
indexMapElements(mpIface, vPath, elms)
} else {
elmsOut := append(*elms, &NMItem{vPath, v})
*elms = elmsOut
}
}
}
// Items returns the items in map, ordered by order information
func (nM *NavigableMap) Items() (itms []*NMItem) {
if len(nM.data) == 0 {
return
}
if len(nM.order) == 0 {
indexMapElements(nM.data, []string{}, &itms)
return
}
itms = make([]*NMItem, len(nM.order))
for i, path := range nM.order {
val, _ := nM.FieldAsInterface(path)
itms[i] = &NMItem{Data: val, Path: path}
}
return
}
// AsNavigableMap implements both NavigableMapper as well as DataProvider interfaces
func (nM NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM NavigableMap, err error) {
return
func (nM *NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM *NavigableMap, err error) {
return nil, utils.ErrNotImplemented
}

View File

@@ -24,15 +24,17 @@ import (
)
func TestNavMapGetFieldAsString(t *testing.T) {
nM := NavigableMap{
"FirstLevel": map[string]interface{}{
"SecondLevel": map[string]interface{}{
"ThirdLevel": map[string]interface{}{
"Fld1": "Val1",
nM := &NavigableMap{
data: map[string]interface{}{
"FirstLevel": map[string]interface{}{
"SecondLevel": map[string]interface{}{
"ThirdLevel": map[string]interface{}{
"Fld1": "Val1",
},
},
},
"AnotherFirstLevel": "ValAnotherFirstLevel",
},
"AnotherFirstLevel": "ValAnotherFirstLevel",
}
eVal := "Val1"
if strVal, err := nM.FieldAsString(
@@ -57,6 +59,6 @@ func TestNavMapGetFieldAsString(t *testing.T) {
type myEv map[string]interface{}
func (ev myEv) AsNavigableMap() (map[string]interface{}, error) {
return NavigableMap(ev), nil
func (ev myEv) AsNavigableMap() (*NavigableMap, error) {
return NewNavigableMap(ev), nil
}

View File

@@ -464,7 +464,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev *utils.CGREvent, usageTT
continue
}
if pass, err := rS.filterS.Pass(ev.Tenant, rPrf.FilterIDs,
NavigableMap(ev.Event)); err != nil {
NewNavigableMap(ev.Event)); err != nil {
return nil, err
} else if !pass {
continue

View File

@@ -169,7 +169,7 @@ func (sS *StatService) matchingStatQueuesForEvent(ev *utils.CGREvent) (sqs StatQ
continue
}
if pass, err := sS.filterS.Pass(ev.Tenant, sqPrfl.FilterIDs,
NavigableMap(ev.Event)); err != nil {
NewNavigableMap(ev.Event)); err != nil {
return nil, err
} else if !pass {
continue

View File

@@ -137,7 +137,7 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *utils.CGREvent)
continue
}
if pass, err := spS.filterS.Pass(ev.Tenant, splPrfl.FilterIDs,
NavigableMap(ev.Event)); err != nil {
NewNavigableMap(ev.Event)); err != nil {
return nil, err
} else if !pass {
continue
@@ -277,7 +277,7 @@ func (spS *SupplierService) sortedSuppliersForEvent(args *ArgsGetSuppliers) (sor
for _, s := range splPrfl.Suppliers {
if len(s.FilterIDs) != 0 { // filters should be applied, check them here
if pass, err := spS.filterS.Pass(args.Tenant, s.FilterIDs,
NavigableMap(args.Event)); err != nil {
NewNavigableMap(args.Event)); err != nil {
return nil, err
} else if !pass {
continue

View File

@@ -246,7 +246,7 @@ func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) (
continue
}
if pass, err := tS.filterS.Pass(args.Tenant, tPrfl.FilterIDs,
NavigableMap(args.Event)); err != nil {
NewNavigableMap(args.Event)); err != nil {
return nil, err
} else if !pass {
continue

View File

@@ -1337,8 +1337,9 @@ type V1AuthorizeReply struct {
}
// AsNavigableMap is part of engine.NavigableMapper interface
func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) {
cgrReply = make(map[string]interface{})
func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(
ignr []*config.CfgCdrField) (*engine.NavigableMap, error) {
cgrReply := make(map[string]interface{})
if v1AuthReply.Attributes != nil {
attrs := make(map[string]interface{})
for _, fldName := range v1AuthReply.Attributes.AlteredFields {
@@ -1363,8 +1364,7 @@ func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(ignr []*config.CfgCdrField)
if v1AuthReply.StatQueueIDs != nil {
cgrReply[utils.CapStatQueues] = *v1AuthReply.StatQueueIDs
}
cgrReply[utils.Error] = "" // so we can compare in filters
return
return engine.NewNavigableMap(cgrReply), nil
}
// BiRPCV1Authorize performs authorization for CGREvent based on specific components
@@ -1552,8 +1552,9 @@ type V1InitSessionReply struct {
}
// AsNavigableMap is part of engine.NavigableMapper interface
func (v1Rply *V1InitSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) {
cgrReply = make(map[string]interface{})
func (v1Rply *V1InitSessionReply) AsNavigableMap(
ignr []*config.CfgCdrField) (*engine.NavigableMap, error) {
cgrReply := make(map[string]interface{})
if v1Rply.Attributes != nil {
attrs := make(map[string]interface{})
for _, fldName := range v1Rply.Attributes.AlteredFields {
@@ -1575,8 +1576,7 @@ func (v1Rply *V1InitSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cg
if v1Rply.StatQueueIDs != nil {
cgrReply[utils.CapStatQueues] = *v1Rply.StatQueueIDs
}
cgrReply[utils.Error] = ""
return
return engine.NewNavigableMap(cgrReply), nil
}
// BiRPCV2InitiateSession initiates a new session, returns the maximum duration the session can last
@@ -1732,8 +1732,9 @@ type V1UpdateSessionReply struct {
}
// AsNavigableMap is part of engine.NavigableMapper interface
func (v1Rply *V1UpdateSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) {
cgrReply = make(map[string]interface{})
func (v1Rply *V1UpdateSessionReply) AsNavigableMap(
ignr []*config.CfgCdrField) (*engine.NavigableMap, error) {
cgrReply := make(map[string]interface{})
if v1Rply.Attributes != nil {
attrs := make(map[string]interface{})
for _, fldName := range v1Rply.Attributes.AlteredFields {
@@ -1746,8 +1747,7 @@ func (v1Rply *V1UpdateSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (
if v1Rply.MaxUsage != nil {
cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage
}
cgrReply[utils.Error] = ""
return
return engine.NewNavigableMap(cgrReply), nil
}
// BiRPCV1UpdateSession updates an existing session, returning the duration which the session can still last
@@ -1899,8 +1899,9 @@ type V1ProcessEventReply struct {
}
// AsNavigableMap is part of engine.NavigableMapper interface
func (v1Rply *V1ProcessEventReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) {
cgrReply = make(map[string]interface{})
func (v1Rply *V1ProcessEventReply) AsNavigableMap(
ignr []*config.CfgCdrField) (*engine.NavigableMap, error) {
cgrReply := make(map[string]interface{})
if v1Rply.MaxUsage != nil {
cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage
}
@@ -1916,8 +1917,7 @@ func (v1Rply *V1ProcessEventReply) AsNavigableMap(ignr []*config.CfgCdrField) (c
}
cgrReply[utils.CapAttributes] = attrs
}
cgrReply[utils.Error] = ""
return
return engine.NewNavigableMap(cgrReply), nil
}
// Called on session end, should send the CDR to CDRS