From 95e38104bb7a37be9bd0a91482572eedd14f19db Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 12 Jun 2018 15:28:05 +0200 Subject: [PATCH] NavigableMap moved to engine, DataProvider interface with AsNavigableMap method --- agents/dmtagent.go | 6 ++--- agents/httpagent.go | 2 +- agents/libdmt_test.go | 6 +++-- agents/libhttpagent.go | 4 ++-- agents/librad.go | 20 ++++++++++++++-- agents/librad_test.go | 33 ++++++++++++++++++++++++++ agents/radagent.go | 6 ++--- engine/attributes.go | 2 +- engine/calldesc.go | 5 ++++ {utils => engine}/dataprovider.go | 7 +++++- engine/filters.go | 20 ++++++++-------- engine/filters_test.go | 26 ++++++++++---------- {utils => engine}/navigablemap.go | 28 ++++++++++------------ {utils => engine}/navigablemap_test.go | 28 +--------------------- engine/resources.go | 2 +- engine/stats.go | 2 +- engine/suppliers.go | 4 ++-- engine/thresholds.go | 2 +- sessions/sessions.go | 16 ++++++------- 19 files changed, 125 insertions(+), 94 deletions(-) rename {utils => engine}/dataprovider.go (87%) rename {utils => engine}/navigablemap.go (78%) rename {utils => engine}/navigablemap_test.go (72%) diff --git a/agents/dmtagent.go b/agents/dmtagent.go index 25306b197..7903f929d 100644 --- a/agents/dmtagent.go +++ b/agents/dmtagent.go @@ -159,14 +159,14 @@ func (da DiameterAgent) processCCR(ccr *CCR, reqProcessor *config.DARequestProce var initReply sessions.V1InitSessionReply err = da.sessionS.Call(utils.SessionSv1InitiateSession, procVars.asV1InitSessionArgs(cgrEv), &initReply) - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&initReply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&initReply, err); err != nil { return } case 2: var updateReply sessions.V1UpdateSessionReply err = da.sessionS.Call(utils.SessionSv1UpdateSession, procVars.asV1UpdateSessionArgs(cgrEv), &updateReply) - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&updateReply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&updateReply, err); err != nil { return } case 3, 4: // Handle them together since we generate CDR for them @@ -185,7 +185,7 @@ func (da DiameterAgent) processCCR(ccr *CCR, reqProcessor *config.DARequestProce } else if evntRply.MaxUsage != nil { cgrEv.Event[utils.Usage] = *evntRply.MaxUsage // make sure the CDR reflects the debit } - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&evntRply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&evntRply, err); err != nil { return } } diff --git a/agents/httpagent.go b/agents/httpagent.go index 305a6722a..76c514580 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -100,7 +100,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 utils.DataProvider, procVars processorVars, + dP engine.DataProvider, procVars processorVars, reply *httpReplyFields) (processed bool, err error) { tnt, err := dP.FieldAsString([]string{utils.Tenant}) diff --git a/agents/libdmt_test.go b/agents/libdmt_test.go index e945e2456..441b14657 100644 --- a/agents/libdmt_test.go +++ b/agents/libdmt_test.go @@ -27,6 +27,7 @@ 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" @@ -38,7 +39,8 @@ import ( var err error func TestDisectUsageForCCR(t *testing.T) { - if reqType, reqNr, reqCCTime, usedCCTime := disectUsageForCCR(time.Duration(0)*time.Second, time.Duration(300)*time.Second, false); reqType != 1 || reqNr != 0 || reqCCTime != 300 || usedCCTime != 0 { + if reqType, reqNr, reqCCTime, usedCCTime := disectUsageForCCR(time.Duration(0)*time.Second, + time.Duration(300)*time.Second, false); reqType != 1 || reqNr != 0 || reqCCTime != 300 || usedCCTime != 0 { t.Error(reqType, reqNr, reqCCTime, usedCCTime) } if reqType, reqNr, reqCCTime, usedCCTime := disectUsageForCCR(time.Duration(35)*time.Second, time.Duration(300)*time.Second, false); reqType != 2 || reqNr != 0 || reqCCTime != 300 || usedCCTime != 35 { @@ -226,7 +228,7 @@ func TestFieldOutVal(t *testing.T) { 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: utils.NavigableMap{ + utils.MetaCGRReply: engine.NavigableMap{ utils.Error: "RALS_ERROR:NOT_FOUND", }, } diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index 9183e3d54..76ce5a8c0 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -22,7 +22,7 @@ import ( "fmt" "net/http" - "github.com/cgrates/cgrates/utils" + "github.com/cgrates/cgrates/engine" ) // httpReplyField is one field written in HTTP reply @@ -45,7 +45,7 @@ type httpReplyFields struct { // newHAReqDecoder produces decoders func newHADataProvider(dpType string, - req *http.Request) (dP utils.DataProvider, err error) { + req *http.Request) (dP engine.DataProvider, err error) { switch dpType { default: return nil, fmt.Errorf("unsupported decoder type <%s>", dpType) diff --git a/agents/librad.go b/agents/librad.go index 9f9ef8b8e..f66996330 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -26,6 +26,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" "github.com/cgrates/radigo" @@ -61,7 +62,7 @@ func (pv processorVars) valAsInterface(fldPath string) (val interface{}, err err err = errors.New("not found") return } - return utils.NavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP)) + return engine.NavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP)) } // valAsString returns the string value for fldName @@ -74,7 +75,7 @@ func (pv processorVars) valAsString(fldPath string) (val string, err error) { if !pv.hasVar(fldName) { return "", utils.ErrNotFoundNoCaps } - return utils.NavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP)) + return engine.NavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP)) } // asV1AuthorizeArgs returns the arguments needed by SessionSv1.AuthorizeEvent @@ -398,3 +399,18 @@ func radReplyAppendAttributes(reply *radigo.Packet, procVars map[string]interfac } return } + +// NewCGRReply is specific to replies coming from CGRateS +func NewCGRReply(rply engine.NavigableMapper, + errRply error) (mp map[string]interface{}, err error) { + if errRply != nil { + return map[string]interface{}{ + utils.Error: errRply.Error()}, nil + } + nM, err := rply.AsNavigableMap(nil) + 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 +} diff --git a/agents/librad_test.go b/agents/librad_test.go index c288b719b..f42df5f92 100644 --- a/agents/librad_test.go +++ b/agents/librad_test.go @@ -19,6 +19,7 @@ along with this program. If not, see package agents import ( + "errors" "fmt" "reflect" "strings" @@ -26,6 +27,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" "github.com/cgrates/radigo" @@ -423,3 +425,34 @@ func TestRadReplyAppendAttributes(t *testing.T) { t.Errorf("Expecting: 3600, received: %s", avps[0].GetStringValue()) } } + +type myEv map[string]interface{} + +func (ev myEv) AsNavigableMap(tpl []*config.CfgCdrField) (engine.NavigableMap, error) { + return engine.NavigableMap(ev), nil +} + +func TestNewCGRReply(t *testing.T) { + eCgrRply := map[string]interface{}{ + utils.Error: "some", + } + 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)) + } + ev := myEv{ + "FirstLevel": map[string]interface{}{ + "SecondLevel": map[string]interface{}{ + "Fld1": "Val1", + }, + }, + } + eCgrRply = ev + eCgrRply[utils.Error] = "" + if rpl, err := NewCGRReply(engine.NavigableMapper(ev), nil); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCgrRply, rpl) { + t.Errorf("Expecting: %+v, received: %+v", eCgrRply, rpl) + } +} diff --git a/agents/radagent.go b/agents/radagent.go index 30e8af91d..4c18b072c 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -174,21 +174,21 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RARequestProcessor, var authReply sessions.V1AuthorizeReply err = ra.sessionS.Call(utils.SessionSv1AuthorizeEvent, procVars.asV1AuthorizeArgs(cgrEv), &authReply) - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&authReply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&authReply, err); err != nil { return } case MetaRadAcctStart: var initReply sessions.V1InitSessionReply err = ra.sessionS.Call(utils.SessionSv1InitiateSession, procVars.asV1InitSessionArgs(cgrEv), &initReply) - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&initReply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&initReply, err); err != nil { return } case MetaRadAcctUpdate: var updateReply sessions.V1UpdateSessionReply err = ra.sessionS.Call(utils.SessionSv1UpdateSession, procVars.asV1UpdateSessionArgs(cgrEv), &updateReply) - if procVars[utils.MetaCGRReply], err = utils.NewCGRReply(&updateReply, err); err != nil { + if procVars[utils.MetaCGRReply], err = NewCGRReply(&updateReply, err); err != nil { return } case MetaRadAcctStop: diff --git a/engine/attributes.go b/engine/attributes.go index c0ff1b22f..9520e5afe 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -91,7 +91,7 @@ func (alS *AttributeService) matchingAttributeProfilesForEvent(ev *utils.CGREven continue } if pass, err := alS.filterS.Pass(ev.Tenant, aPrfl.FilterIDs, - utils.NavigableMap(ev.Event)); err != nil { + NavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/calldesc.go b/engine/calldesc.go index 4fd256bb6..a4fc789be 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -1454,3 +1454,8 @@ func (cd *CallDescriptor) FieldAsString(fldPath []string) (fldVal string, err er func (cd *CallDescriptor) String() string { return utils.ToJSON(cd) } + +// AsNavigableMap is part of utils.DataProvider +func (cd *CallDescriptor) AsNavigableMap(tpl []*config.CfgCdrField) (nM NavigableMap, err error) { + return +} diff --git a/utils/dataprovider.go b/engine/dataprovider.go similarity index 87% rename from utils/dataprovider.go rename to engine/dataprovider.go index 040120fdd..6638d3f27 100644 --- a/utils/dataprovider.go +++ b/engine/dataprovider.go @@ -16,11 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package engine + +import ( + "github.com/cgrates/cgrates/config" +) // DataProvider is a data source from multiple formats 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) } diff --git a/engine/filters.go b/engine/filters.go index cd65051aa..2b4dfab9c 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -76,8 +76,8 @@ func (fS *FilterS) connStatS() (err error) { // Pass will check all filters wihin filterIDs and require them passing for dataProvider // there should be at least one filter passing, ie: if filters are not active event will fail to pass -// receives the event as utils.DataProvider so we can accept undecoded data (ie: HttpRequest) -func (fS *FilterS) Pass(tenant string, filterIDs []string, ev utils.DataProvider) (pass bool, err error) { +// receives the event as DataProvider so we can accept undecoded data (ie: HttpRequest) +func (fS *FilterS) Pass(tenant string, filterIDs []string, ev DataProvider) (pass bool, err error) { if len(filterIDs) == 0 { return true, nil } @@ -209,7 +209,7 @@ func (rf *FilterRule) CompileValues() (err error) { } // Pass is the method which should be used from outside. -func (fltr *FilterRule) Pass(dP utils.DataProvider, rpcClnt rpcclient.RpcClientConnection) (bool, error) { +func (fltr *FilterRule) Pass(dP DataProvider, rpcClnt rpcclient.RpcClientConnection) (bool, error) { switch fltr.Type { case MetaString: return fltr.passString(dP) @@ -230,7 +230,7 @@ func (fltr *FilterRule) Pass(dP utils.DataProvider, rpcClnt rpcclient.RpcClientC } } -func (fltr *FilterRule) passString(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passString(dP DataProvider) (bool, error) { strVal, err := dP.FieldAsString(strings.Split(fltr.FieldName, utils.HIERARCHY_SEP)) if err != nil { if err == utils.ErrNotFound { @@ -246,7 +246,7 @@ func (fltr *FilterRule) passString(dP utils.DataProvider) (bool, error) { return false, nil } -func (fltr *FilterRule) passStringPrefix(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passStringPrefix(dP DataProvider) (bool, error) { strVal, err := dP.FieldAsString(strings.Split(fltr.FieldName, utils.HIERARCHY_SEP)) if err != nil { if err == utils.ErrNotFound { @@ -263,11 +263,11 @@ func (fltr *FilterRule) passStringPrefix(dP utils.DataProvider) (bool, error) { } // ToDo when Timings will be available in DataDb -func (fltr *FilterRule) passTimings(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passTimings(dP DataProvider) (bool, error) { return false, utils.ErrNotImplemented } -func (fltr *FilterRule) passDestinations(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passDestinations(dP DataProvider) (bool, error) { dst, err := dP.FieldAsString(strings.Split(fltr.FieldName, utils.HIERARCHY_SEP)) if err != nil { if err == utils.ErrNotFound { @@ -289,7 +289,7 @@ func (fltr *FilterRule) passDestinations(dP utils.DataProvider) (bool, error) { return false, nil } -func (fltr *FilterRule) passRSR(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passRSR(dP DataProvider) (bool, error) { for _, rsrFld := range fltr.rsrFields { fldIface, err := dP.FieldAsInterface(strings.Split(rsrFld.Id, utils.HIERARCHY_SEP)) if err != nil { @@ -305,7 +305,7 @@ func (fltr *FilterRule) passRSR(dP utils.DataProvider) (bool, error) { return false, nil } -func (fltr *FilterRule) passStatS(dP utils.DataProvider, +func (fltr *FilterRule) passStatS(dP DataProvider, stats rpcclient.RpcClientConnection) (bool, error) { if stats == nil || reflect.ValueOf(stats).IsNil() { return false, errors.New("Missing StatS information") @@ -330,7 +330,7 @@ func (fltr *FilterRule) passStatS(dP utils.DataProvider, return false, nil } -func (fltr *FilterRule) passGreaterThan(dP utils.DataProvider) (bool, error) { +func (fltr *FilterRule) passGreaterThan(dP DataProvider) (bool, error) { fldIf, err := dP.FieldAsInterface(strings.Split(fltr.FieldName, utils.HIERARCHY_SEP)) if err != nil { if err == utils.ErrNotFound { diff --git a/engine/filters_test.go b/engine/filters_test.go index 7c5424595..8b4b483e0 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -154,7 +154,7 @@ func TestFilterPassGreaterThan(t *testing.T) { if err != nil { t.Error(err) } - ev := utils.NavigableMap{ + ev := NavigableMap{ "ASR": 20, } if passes, err := rf.passGreaterThan(ev); err != nil { @@ -296,13 +296,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { t.Errorf(err.Error()) } if pass, err := filterS.Pass("cgrates.org", - []string{"*string:Account:1007"}, utils.NavigableMap(failEvent)); err != nil { + []string{"*string:Account:1007"}, NavigableMap(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"}, utils.NavigableMap(passEvent)); err != nil { + []string{"*string:Account:1007"}, NavigableMap(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"}, utils.NavigableMap(failEvent)); err != nil { + []string{"*prefix:Account:10"}, NavigableMap(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"}, utils.NavigableMap(passEvent)); err != nil { + []string{"*prefix:Account:10"}, NavigableMap(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$)"}, utils.NavigableMap(failEvent)); err != nil { + []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(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$)"}, utils.NavigableMap(passEvent)); err != nil { + []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(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"}, utils.NavigableMap(failEvent)); err != nil { + []string{"*destinations:Destination:EU"}, NavigableMap(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"}, utils.NavigableMap(passEvent)); err != nil { + []string{"*destinations:Destination:EU_LANDLINE"}, NavigableMap(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"}, utils.NavigableMap(failEvent)); err != nil { + []string{"*gte:Weight:20"}, NavigableMap(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"}, utils.NavigableMap(passEvent)); err != nil { + []string{"*gte:Weight:10"}, NavigableMap(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{}, utils.NavigableMap(passEvent1)); err != nil { + []string{}, NavigableMap(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{}, utils.NavigableMap(passEvent2)); err != nil { + []string{}, NavigableMap(passEvent2)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) diff --git a/utils/navigablemap.go b/engine/navigablemap.go similarity index 78% rename from utils/navigablemap.go rename to engine/navigablemap.go index 64b4f8021..01b5b73d2 100644 --- a/utils/navigablemap.go +++ b/engine/navigablemap.go @@ -16,16 +16,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package engine import ( "errors" "fmt" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" ) // CGRReplier is the interface supported by replies convertible to CGRReply type NavigableMapper interface { - AsNavigableMap() (map[string]interface{}, error) + AsNavigableMap([]*config.CfgCdrField) (NavigableMap, error) } // NavigableMap is a map who's values can be navigated via path @@ -45,7 +48,7 @@ func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, e var has bool fldVal, has = lastMp[spath] if !has { - return nil, ErrNotFound + return nil, utils.ErrNotFound } return } else { @@ -57,7 +60,7 @@ func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, e lastMp, canCast = elmnt.(map[string]interface{}) if !canCast { err = fmt.Errorf("cannot cast field: %s to map[string]interface{}", - ToJSON(elmnt)) + utils.ToJSON(elmnt)) return } } @@ -75,24 +78,17 @@ func (nM NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error return } var canCast bool - if fldVal, canCast = CastFieldIfToString(valIface); !canCast { - return "", fmt.Errorf("cannot cast field: %s to string", ToJSON(valIface)) + if fldVal, canCast = utils.CastFieldIfToString(valIface); !canCast { + return "", fmt.Errorf("cannot cast field: %s to string", utils.ToJSON(valIface)) } return } func (nM NavigableMap) String() string { - return ToJSON(nM) + return utils.ToJSON(nM) } -// NewCGRReply is specific to replies coming from CGRateS -func NewCGRReply(rply NavigableMapper, errRply error) (nM map[string]interface{}, err error) { - if errRply != nil { - return NavigableMap{Error: errRply.Error()}, nil - } - if nM, err = rply.AsNavigableMap(); err != nil { - return - } - nM[Error] = "" // enforce empty error +// AsNavigableMap implements both NavigableMapper as well as DataProvider interfaces +func (nM NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM NavigableMap, err error) { return } diff --git a/utils/navigablemap_test.go b/engine/navigablemap_test.go similarity index 72% rename from utils/navigablemap_test.go rename to engine/navigablemap_test.go index de1e53e08..28e44f962 100644 --- a/utils/navigablemap_test.go +++ b/engine/navigablemap_test.go @@ -15,11 +15,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package engine import ( "errors" - "reflect" "strings" "testing" ) @@ -61,28 +60,3 @@ type myEv map[string]interface{} func (ev myEv) AsNavigableMap() (map[string]interface{}, error) { return NavigableMap(ev), nil } - -func TestCGRReplyNew(t *testing.T) { - eCgrRply := map[string]interface{}{ - Error: "some", - } - 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", ToJSON(eCgrRply), ToJSON(rpl)) - } - ev := myEv{ - "FirstLevel": map[string]interface{}{ - "SecondLevel": map[string]interface{}{ - "Fld1": "Val1", - }, - }, - } - eCgrRply = ev - eCgrRply[Error] = "" - if rpl, err := NewCGRReply(NavigableMapper(ev), nil); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eCgrRply, rpl) { - t.Errorf("Expecting: %+v, received: %+v", eCgrRply, rpl) - } -} diff --git a/engine/resources.go b/engine/resources.go index fdf876c04..05ec5ebee 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -464,7 +464,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev *utils.CGREvent, usageTT continue } if pass, err := rS.filterS.Pass(ev.Tenant, rPrf.FilterIDs, - utils.NavigableMap(ev.Event)); err != nil { + NavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/stats.go b/engine/stats.go index 0229b85e1..a7be8984f 100644 --- a/engine/stats.go +++ b/engine/stats.go @@ -169,7 +169,7 @@ func (sS *StatService) matchingStatQueuesForEvent(ev *utils.CGREvent) (sqs StatQ continue } if pass, err := sS.filterS.Pass(ev.Tenant, sqPrfl.FilterIDs, - utils.NavigableMap(ev.Event)); err != nil { + NavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/suppliers.go b/engine/suppliers.go index e46eaed09..032ecd0e5 100644 --- a/engine/suppliers.go +++ b/engine/suppliers.go @@ -137,7 +137,7 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *utils.CGREvent) continue } if pass, err := spS.filterS.Pass(ev.Tenant, splPrfl.FilterIDs, - utils.NavigableMap(ev.Event)); err != nil { + NavigableMap(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, - utils.NavigableMap(args.Event)); err != nil { + NavigableMap(args.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/thresholds.go b/engine/thresholds.go index fe335a788..1d0e85dbd 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -246,7 +246,7 @@ func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) ( continue } if pass, err := tS.filterS.Pass(args.Tenant, tPrfl.FilterIDs, - utils.NavigableMap(args.Event)); err != nil { + NavigableMap(args.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/sessions/sessions.go b/sessions/sessions.go index c1df01720..368d10e11 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -1336,8 +1336,8 @@ type V1AuthorizeReply struct { StatQueueIDs *[]string } -// AsCGRReply is part of utils.CGRReplier interface -func (v1AuthReply *V1AuthorizeReply) AsNavigableMap() (cgrReply map[string]interface{}, err error) { +// AsNavigableMap is part of engine.NavigableMapper interface +func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { cgrReply = make(map[string]interface{}) if v1AuthReply.Attributes != nil { attrs := make(map[string]interface{}) @@ -1551,8 +1551,8 @@ type V1InitSessionReply struct { StatQueueIDs *[]string } -// AsCGRReply is part of utils.CGRReplier interface -func (v1Rply *V1InitSessionReply) AsNavigableMap() (cgrReply map[string]interface{}, err error) { +// AsNavigableMap is part of engine.NavigableMapper interface +func (v1Rply *V1InitSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { cgrReply = make(map[string]interface{}) if v1Rply.Attributes != nil { attrs := make(map[string]interface{}) @@ -1731,8 +1731,8 @@ type V1UpdateSessionReply struct { MaxUsage *time.Duration } -// AsCGRReply is part of utils.CGRReplier interface -func (v1Rply *V1UpdateSessionReply) AsNavigableMap() (cgrReply map[string]interface{}, err error) { +// AsNavigableMap is part of engine.NavigableMapper interface +func (v1Rply *V1UpdateSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { cgrReply = make(map[string]interface{}) if v1Rply.Attributes != nil { attrs := make(map[string]interface{}) @@ -1898,8 +1898,8 @@ type V1ProcessEventReply struct { Attributes *engine.AttrSProcessEventReply } -// AsCGRReply is part of utils.CGRReplier interface -func (v1Rply *V1ProcessEventReply) AsNavigableMap() (cgrReply map[string]interface{}, err error) { +// AsNavigableMap is part of engine.NavigableMapper interface +func (v1Rply *V1ProcessEventReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { cgrReply = make(map[string]interface{}) if v1Rply.MaxUsage != nil { cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage