From a2954c77c922d2c5f07ec4f22578f852847fa663 Mon Sep 17 00:00:00 2001 From: TeoV Date: Wed, 27 Nov 2019 11:10:05 -0500 Subject: [PATCH] Finish updating integration test after modification --- cdrc/csv.go | 4 +- config/objdp.go | 23 ++- config/slicedp.go | 18 ++- .../samples/cdrewithattributes/cgrates.json | 22 +-- .../samples/dispatchers/diamagent/data.json | 2 +- data/conf/samples/ers/cgrates.json | 18 +-- engine/eventcost_test.go | 2 +- engine/filters.go | 136 ++++++++---------- ers/filecsv.go | 2 +- general_tests/filters_it_test.go | 16 +-- general_tests/objectdp_test.go | 4 +- 11 files changed, 117 insertions(+), 130 deletions(-) diff --git a/cdrc/csv.go b/cdrc/csv.go index 6bfd74004..468e8e865 100644 --- a/cdrc/csv.go +++ b/cdrc/csv.go @@ -107,7 +107,7 @@ func (self *CsvRecordsProcessor) processFlatstoreRecord(record []string) ([]stri // Takes the record from a slice and turns it into StoredCdrs, posting them to the cdrServer func (self *CsvRecordsProcessor) processRecord(record []string) ([]*engine.CDR, error) { - csvProvider := config.NewSliceDP(record) + csvProvider := config.NewSliceDP(record, utils.MetaReq) recordCdrs := make([]*engine.CDR, 0) // More CDRs based on the number of filters and field templates for _, cdrcCfg := range self.cdrcCfgs { // cdrFields coming from more templates will produce individual storCdr records tenant, err := cdrcCfg.Tenant.ParseDataProvider(csvProvider, utils.NestingSep) // each profile of cdrc can have different tenant @@ -146,7 +146,7 @@ func (self *CsvRecordsProcessor) processRecord(record []string) ([]*engine.CDR, func (self *CsvRecordsProcessor) recordToStoredCdr(record []string, cdrcCfg *config.CdrcCfg, tenant string) (*engine.CDR, error) { storedCdr := &engine.CDR{OriginHost: "0.0.0.0", Source: cdrcCfg.CdrSourceId, ExtraFields: make(map[string]string), Cost: -1} var err error - csvProvider := config.NewSliceDP(record) // used for filterS and for RSRParsers + csvProvider := config.NewSliceDP(record, utils.MetaReq) // used for filterS and for RSRParsers var lazyHttpFields []*config.FCTemplate fldVals := make(map[string]string) for _, cdrFldCfg := range cdrcCfg.ContentFields { diff --git a/config/objdp.go b/config/objdp.go index 10ed91fb0..d6f95b0e9 100644 --- a/config/objdp.go +++ b/config/objdp.go @@ -27,14 +27,15 @@ import ( ) //NewObjectDP constructs a DataProvider -func NewObjectDP(obj interface{}) (dP DataProvider) { - dP = &ObjectDP{obj: obj, cache: make(map[string]interface{})} +func NewObjectDP(obj interface{}, prfxSls []string) (dP DataProvider) { + dP = &ObjectDP{obj: obj, cache: make(map[string]interface{}), prfxSls: prfxSls} return } type ObjectDP struct { - obj interface{} - cache map[string]interface{} + obj interface{} + cache map[string]interface{} + prfxSls []string } func (objDp *ObjectDP) setCache(path string, val interface{}) { @@ -55,14 +56,26 @@ func (objDP *ObjectDP) String() string { // FieldAsInterface is part of engine.DataProvider interface func (objDP *ObjectDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { obj := objDP.obj + clnFldPath := fldPath // []string{ BalanceMap *monetary[0] Value } var has bool if data, has = objDP.getCache(strings.Join(fldPath, utils.NestingSep)); has { return } + if len(objDP.prfxSls) != 0 { + if len(clnFldPath) < len(objDP.prfxSls) { + return nil, fmt.Errorf("invalid path <%s> compared to prefix <%s>", clnFldPath, objDP.prfxSls) + } + for i, prfx := range objDP.prfxSls { + if clnFldPath[i] != prfx { + return nil, fmt.Errorf("wrong prefix when compared <%s> with <%s>", clnFldPath, objDP.prfxSls) + } + } + clnFldPath = clnFldPath[len(objDP.prfxSls):] + } var prevFld string - for _, fld := range fldPath { + for _, fld := range clnFldPath { var slctrStr string if splt := strings.Split(fld, utils.IdxStart); len(splt) != 1 { // check if we have selector fld = splt[0] diff --git a/config/slicedp.go b/config/slicedp.go index 0ab630dc2..ee538f4ac 100644 --- a/config/slicedp.go +++ b/config/slicedp.go @@ -28,15 +28,17 @@ import ( ) // NewSliceDP constructs a DataProvider -func NewSliceDP(record []string) (dP DataProvider) { - dP = &SliceDP{req: record, cache: NewNavigableMap(nil)} +func NewSliceDP(record []string, pathPrfx string) (dP DataProvider) { + dP = &SliceDP{req: record, cache: NewNavigableMap(nil), pathPrfx: pathPrfx} return } // SliceDP implements engine.DataProvider so we can pass it to filters type SliceDP struct { - req []string - cache *NavigableMap + req []string + cache *NavigableMap + pathPrfx string // if this comes in path it will be ignored + // pathPrfx should be reviewed once the cdrc is removed } // String is part of engine.DataProvider interface @@ -50,7 +52,11 @@ func (cP *SliceDP) FieldAsInterface(fldPath []string) (data interface{}, err err if len(fldPath) == 0 { return } - if fldPath[0] != utils.MetaReq || len(fldPath) < 2 { + idx := fldPath[0] + if len(fldPath) == 2 { + idx = fldPath[1] + } + if cP.pathPrfx != utils.EmptyString && (fldPath[0] != cP.pathPrfx || len(fldPath) < 2) { return "", utils.ErrPrefixNotFound(strings.Join(fldPath, utils.NestingSep)) } if data, err = cP.cache.FieldAsInterface(fldPath); err == nil || @@ -58,7 +64,7 @@ func (cP *SliceDP) FieldAsInterface(fldPath []string) (data interface{}, err err return } err = nil // cancel previous err - if cfgFieldIdx, err := strconv.Atoi(fldPath[1]); err != nil { + if cfgFieldIdx, err := strconv.Atoi(idx); err != nil { return nil, fmt.Errorf("Ignoring record: %v with error : %+v", cP.req, err) } else if len(cP.req) <= cfgFieldIdx { return nil, utils.ErrNotFound diff --git a/data/conf/samples/cdrewithattributes/cgrates.json b/data/conf/samples/cdrewithattributes/cgrates.json index 77b33ee0e..0c6cfd0f7 100755 --- a/data/conf/samples/cdrewithattributes/cgrates.json +++ b/data/conf/samples/cdrewithattributes/cgrates.json @@ -48,17 +48,17 @@ "attributes_context":"*cdre", "filters" :["*string:~*req.Source:test2"], "content_fields": [ - {"tag": "CGRID", "type": "*composed", "value": "~*req.CGRID"}, - {"tag": "RunID", "type": "*composed", "value": "~*req.RunID"}, - {"tag":"Source", "type": "*composed", "value": "~*req.Source"}, - {"tag":"OriginID", "type": "*composed", "value": "~*req.OriginID"}, - {"tag":"Tenant", "type": "*composed", "value": "~*req.Tenant"}, - {"tag":"Category", "type": "*composed", "value": "~*req.Category"}, - {"tag":"Account", "type": "*composed", "value": "~*req.Account"}, - {"tag":"Subject", "type": "*composed", "value": "~*req.Subject"}, - {"tag":"Destination", "type": "*composed", "value": "~*req.Destination"}, - {"tag":"Usage", "type": "*composed", "value": "~*req.Usage"}, - {"tag":"Cost", "type": "*composed", "value": "~*req.Cost", "rounding_decimals": 4}, + {"tag": "CGRID", "type": "*composed", "value": "~CGRID"}, + {"tag": "RunID", "type": "*composed", "value": "~RunID"}, + {"tag":"Source", "type": "*composed", "value": "~Source"}, + {"tag":"OriginID", "type": "*composed", "value": "~OriginID"}, + {"tag":"Tenant", "type": "*composed", "value": "~Tenant"}, + {"tag":"Category", "type": "*composed", "value": "~Category"}, + {"tag":"Account", "type": "*composed", "value": "~Account"}, + {"tag":"Subject", "type": "*composed", "value": "~Subject"}, + {"tag":"Destination", "type": "*composed", "value": "~Destination"}, + {"tag":"Usage", "type": "*composed", "value": "~Usage"}, + {"tag":"Cost", "type": "*composed", "value": "~Cost", "rounding_decimals": 4}, ], }, }, diff --git a/data/conf/samples/dispatchers/diamagent/data.json b/data/conf/samples/dispatchers/diamagent/data.json index 591ed7d0d..522db8708 100644 --- a/data/conf/samples/dispatchers/diamagent/data.json +++ b/data/conf/samples/dispatchers/diamagent/data.json @@ -34,7 +34,7 @@ { "id": "data_update_grp1", "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:2", - "*string:*req.Multiple-Services-Credit-Control.Rating-Group:1", "*prefix:*req.Service-Context-Id:gprs"], + "*string:~*req.Multiple-Services-Credit-Control.Rating-Group:1", "*prefix:~*req.Service-Context-Id:gprs"], "flags": ["*update", "*accounts"], "request_fields":[ {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*data"}, diff --git a/data/conf/samples/ers/cgrates.json b/data/conf/samples/ers/cgrates.json index 35ac07e3f..c44bc80d5 100644 --- a/data/conf/samples/ers/cgrates.json +++ b/data/conf/samples/ers/cgrates.json @@ -103,12 +103,12 @@ "flags": ["*dryrun"], "processed_path": "/tmp/ers2/out", "content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value - {"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "*voice", "mandatory": true}, + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice", "mandatory": true}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "~*req.0", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "~*req.1", "mandatory": true}, - {"tag": "Direction", "field_id": "Direction", "type": "*composed", "value": "*out", "mandatory": true}, + {"tag": "Direction", "field_id": "Direction", "type": "*constant", "value": "*out", "mandatory": true}, {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "~*req.2", "mandatory": true}, - {"tag": "Category", "field_id": "Category", "type": "*composed", "value": "call", "mandatory": true}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "call", "mandatory": true}, {"tag": "Account", "field_id": "Account", "type": "*composed", "value": "~*req.3", "mandatory": true}, {"tag": "Subject", "field_id": "Subject", "type": "*composed", "value": "~*req.3", "mandatory": true}, {"tag": "Destination", "field_id": "Destination", "type": "*composed", "value": "~*req.4:s/0([1-9]\\d+)/+49${1}/", "mandatory": true}, @@ -130,10 +130,10 @@ "processed_path": "/tmp/init_session/out", "content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value {"tag": "Tenant", "field_id": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "TOR", "field_id": "ToR", "type": "*variable", "value": "*voice", "mandatory": true}, + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice", "mandatory": true}, {"tag": "OriginID", "field_id": "OriginID", "type": "*variable", "value": "~*req.2", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", "type": "*variable", "value": "~*req.3", "mandatory": true}, - {"tag": "Category", "field_id": "Category", "type": "*variable", "value": "call", "mandatory": true}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "call", "mandatory": true}, {"tag": "Account", "field_id": "Account", "type": "*variable", "value": "~*req.4", "mandatory": true}, {"tag": "Subject", "field_id": "Subject", "type": "*variable", "value": "~*req.5", "mandatory": true}, {"tag": "Destination", "field_id": "Destination", "type": "*variable", "value": "~*req.6", "mandatory": true}, @@ -167,10 +167,10 @@ "processed_path": "/tmp/cdrs/out", "content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value {"tag": "Tenant", "field_id": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "TOR", "field_id": "ToR", "type": "*variable", "value": "*voice", "mandatory": true}, + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice", "mandatory": true}, {"tag": "OriginID", "field_id": "OriginID", "type": "*variable", "value": "~*req.2", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", "type": "*variable", "value": "~*req.3", "mandatory": true}, - {"tag": "Category", "field_id": "Category", "type": "*variable", "value": "call", "mandatory": true}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "call", "mandatory": true}, {"tag": "Account", "field_id": "Account", "type": "*variable", "value": "~*req.4", "mandatory": true}, {"tag": "Subject", "field_id": "Subject", "type": "*variable", "value": "~*req.5", "mandatory": true}, {"tag": "Destination", "field_id": "Destination", "type": "*variable", "value": "~*req.6", "mandatory": true}, @@ -192,13 +192,13 @@ "flags": ["*cdrs","*log"], "filters":["*string:~*req.3:1002"], "content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value - {"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "*voice", "mandatory": true}, + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice", "mandatory": true}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "~*req.0", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "~*req.1", "mandatory": true}, {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "~*req.2", "mandatory": true}, {"tag": "Category", "field_id": "Category", "type": "*composed", "value": "call", "mandatory": true}, {"tag": "Account", "field_id": "Account", "type": "*composed", "value": "~*req.3", "mandatory": true}, - {"tag": "Source", "field_id": "Source", "type": "*composed", "value": "ers_csv", "mandatory": true}, + {"tag": "Source", "field_id": "Source", "type": "*constant", "value": "ers_csv", "mandatory": true}, {"tag": "Subject", "field_id": "Subject", "type": "*composed", "value": "~*req.3", "mandatory": true}, {"tag": "Destination", "field_id": "Destination", "type": "*composed", "value": "~*req.4:s/0([1-9]\\d+)/+49${1}/", "mandatory": true}, {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "~*req.5", "mandatory": true}, diff --git a/engine/eventcost_test.go b/engine/eventcost_test.go index aa8f13cfa..e241b7104 100644 --- a/engine/eventcost_test.go +++ b/engine/eventcost_test.go @@ -2523,7 +2523,7 @@ func TestECSyncKeys(t *testing.T) { } func TestECAsDataProvider(t *testing.T) { - ecDP := config.NewObjectDP(testEC) + ecDP := config.NewObjectDP(testEC, nil) if data, err := ecDP.FieldAsInterface([]string{"RunID"}); err != nil { t.Error(err) } else if data != utils.META_DEFAULT { diff --git a/engine/filters.go b/engine/filters.go index ef4f06320..cf4d7c491 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -126,7 +126,7 @@ func (fS *FilterS) Pass(tenant string, filterIDs []string, continue } for _, fltr := range f.Rules { - fieldNameDP, err = fS.getFieldNameDataProvider(ev, &fltr.FieldName, tenant) + fieldNameDP, err = fS.getFieldNameDataProvider(ev, fltr.FieldName, tenant) if err != nil { return pass, err } @@ -227,24 +227,14 @@ func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error) return rf, nil } -//itemFilter is used for *stats and *resources filter type -type itemFilter struct { - ItemID string - FilterType string - FilterValue string -} - // FilterRule filters requests coming into various places // Pass rule: default negative, one mathing rule should pass the filter type FilterRule struct { - Type string // Filter type (*string, *timing, *rsr_filters, *stats, *lt, *lte, *gt, *gte) - FieldName string // Name of the field providing us the Values to check (used in case of some ) - Values []string // Filter definition - rsrFields config.RSRParsers // Cache here the RSRFilter Values - negative *bool - statItems []*itemFilter // Cached compiled itemFilter out of Values - resourceItems []*itemFilter // Cached compiled itemFilter out of Values - accountItems []*itemFilter // Cached compiled itemFilter out of Values + Type string // Filter type (*string, *timing, *rsr_filters, *stats, *lt, *lte, *gt, *gte) + FieldName string // Name of the field providing us the Values to check (used in case of some ) + Values []string // Filter definition + rsrFields config.RSRParsers // Cache here the RSRFilter Values + negative *bool } // Separate method to compile RSR fields @@ -496,15 +486,15 @@ func (fltr *FilterRule) passEqualTo(fielNameDP config.DataProvider, fieldValuesD } func (fS *FilterS) getFieldNameDataProvider(initialDP config.DataProvider, - fieldName *string, tenant string) (dp config.DataProvider, err error) { + fieldName string, tenant string) (dp config.DataProvider, err error) { switch { - case strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaAccounts): + case strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaAccounts): // sample of fieldName : ~*accounts.1001.BalanceMap.*monetary[0].Value // split the field name in 3 parts // fieldNameType (~*accounts), accountID(1001) and quried part (BalanceMap.*monetary[0].Value) - splitFldName := strings.SplitN(*fieldName, utils.NestingSep, 3) + splitFldName := strings.SplitN(fieldName, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldName) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldName) } var account *Account if err = fS.ralSConns.Call(utils.ApierV2GetAccount, @@ -512,27 +502,24 @@ func (fS *FilterS) getFieldNameDataProvider(initialDP config.DataProvider, return } //construct dataProvider from account and set it furthder - dp = config.NewObjectDP(account) - // remove from fieldname the fielNameType and the AccountID - *fieldName = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaResources): + dp = config.NewObjectDP(account, []string{utils.MetaAccounts, splitFldName[1]}) + case strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaResources): // sample of fieldName : ~*resources.ResourceID.Field - splitFldName := strings.SplitN(*fieldName, utils.NestingSep, 3) + splitFldName := strings.SplitN(fieldName, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldName) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldName) } var reply *Resource if err := fS.resSConns.Call(utils.ResourceSv1GetResource, &utils.TenantID{Tenant: tenant, ID: splitFldName[1]}, &reply); err != nil { return nil, err } - dp = config.NewObjectDP(reply) - *fieldName = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaStats): - // sample of fieldName : ~*resources.ResourceID.Field - splitFldName := strings.SplitN(*fieldName, utils.NestingSep, 3) + dp = config.NewObjectDP(reply, []string{utils.MetaResources, reply.ID}) + case strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaStats): + // sample of fieldName : ~*stats.StatID.*acd + splitFldName := strings.SplitN(fieldName, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldName) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldName) } var statValues map[string]float64 @@ -541,26 +528,23 @@ func (fS *FilterS) getFieldNameDataProvider(initialDP config.DataProvider, &statValues); err != nil { return nil, err } - //convert statValues to map[string]interface{} - ifaceStatValues := make(map[string]interface{}) - for key, val := range statValues { - ifaceStatValues[key] = val + evNm := config.NewNavigableMap(nil) + for k, v := range statValues { + evNm.Set([]string{utils.MetaStats, splitFldName[1], k}, v, false, false) } - //convert ifaceStatValues into a NavigableMap - dp = config.NewNavigableMap(ifaceStatValues) - *fieldName = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaReq), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaVars), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaCgreq), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaCgrep), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaRep), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaCGRAReq), - strings.HasPrefix(*fieldName, utils.DynamicDataPrefix+utils.MetaAct): + dp = evNm + case strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaReq), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaVars), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaCgreq), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaCgrep), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaRep), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaCGRAReq), + strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaAct): dp = initialDP // don't need to take out the prefix because the navigable map have ~*req prefix - case *fieldName == utils.EmptyString: + case fieldName == utils.EmptyString: default: - return nil, utils.ErrPrefixNotFound(fmt.Sprintf(" data provider prefix for <%s>", *fieldName)) + return nil, utils.ErrPrefixNotFound(fmt.Sprintf(" data provider prefix for <%s>", fieldName)) } return } @@ -569,7 +553,7 @@ func (fS *FilterS) getFieldValuesDataProviders(initialDP config.DataProvider, values []string, tenant string) (dp []config.DataProvider, err error) { dp = make([]config.DataProvider, len(values)) for i := range values { - if dp[i], err = fS.getFieldValueDataProvider(initialDP, &values[i], tenant); err != nil { + if dp[i], err = fS.getFieldValueDataProvider(initialDP, values[i], tenant); err != nil { return } } @@ -577,15 +561,15 @@ func (fS *FilterS) getFieldValuesDataProviders(initialDP config.DataProvider, } func (fS *FilterS) getFieldValueDataProvider(initialDP config.DataProvider, - fieldValue *string, tenant string) (dp config.DataProvider, err error) { + fieldValue string, tenant string) (dp config.DataProvider, err error) { switch { - case strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaAccounts): + case strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaAccounts): // sample of fieldName : ~*accounts.1001.BalanceMap.*monetary[0].Value // split the field name in 3 parts // fieldNameType (~*accounts), accountID(1001) and quried part (BalanceMap.*monetary[0].Value) - splitFldName := strings.SplitN(*fieldValue, utils.NestingSep, 3) + splitFldName := strings.SplitN(fieldValue, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldValue) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldValue) } var account *Account if err = fS.ralSConns.Call(utils.ApierV2GetAccount, @@ -593,27 +577,24 @@ func (fS *FilterS) getFieldValueDataProvider(initialDP config.DataProvider, return } //construct dataProvider from account and set it furthder - dp = config.NewObjectDP(account) - // remove from fieldname the fielNameType and the AccountID - *fieldValue = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaResources): + dp = config.NewObjectDP(account, []string{utils.MetaAccounts, account.ID}) + case strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaResources): // sample of fieldName : ~*resources.ResourceID.Field - splitFldName := strings.SplitN(*fieldValue, utils.NestingSep, 3) + splitFldName := strings.SplitN(fieldValue, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldValue) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldValue) } var reply *Resource if err := fS.resSConns.Call(utils.ResourceSv1GetResource, &utils.TenantID{Tenant: tenant, ID: splitFldName[1]}, &reply); err != nil { return nil, err } - dp = config.NewObjectDP(reply) - *fieldValue = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaStats): + dp = config.NewObjectDP(reply, []string{utils.MetaResources, reply.ID}) + case strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaStats): // sample of fieldName : ~*resources.ResourceID.Field - splitFldName := strings.SplitN(*fieldValue, utils.NestingSep, 3) + splitFldName := strings.SplitN(fieldValue, utils.NestingSep, 3) if len(splitFldName) != 3 { - return nil, fmt.Errorf("invalid fieldname <%s>", *fieldValue) + return nil, fmt.Errorf("invalid fieldname <%s>", fieldValue) } var statValues map[string]float64 @@ -622,21 +603,20 @@ func (fS *FilterS) getFieldValueDataProvider(initialDP config.DataProvider, &statValues); err != nil { return nil, err } - //convert statValues to map[string]interface{} - ifaceStatValues := make(map[string]interface{}) - for key, val := range statValues { - ifaceStatValues[key] = val + ifaceMetric := make(map[string]interface{}) + for k, v := range statValues { + ifaceMetric[k] = v } - //convert ifaceStatValues into a NavigableMap - dp = config.NewNavigableMap(ifaceStatValues) - *fieldValue = utils.DynamicDataPrefix + splitFldName[2] - case strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaReq), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaVars), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaCgreq), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaCgrep), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaRep), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaCGRAReq), - strings.HasPrefix(*fieldValue, utils.DynamicDataPrefix+utils.MetaAct): + evNm := config.NewNavigableMap(nil) + evNm.Set([]string{utils.MetaStats, splitFldName[1]}, ifaceMetric, false, false) + dp = evNm + case strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaReq), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaVars), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaCgreq), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaCgrep), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaRep), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaCGRAReq), + strings.HasPrefix(fieldValue, utils.DynamicDataPrefix+utils.MetaAct): dp = initialDP default: // in case of constant we give an empty DataProvider ( empty navigable map ) dp = config.NewNavigableMap(nil) diff --git a/ers/filecsv.go b/ers/filecsv.go index 68d123a49..b451e4007 100644 --- a/ers/filecsv.go +++ b/ers/filecsv.go @@ -143,7 +143,7 @@ func (rdr *CSVFileER) processFile(fPath, fName string) (err error) { } rowNr++ // increment the rowNr after checking if it's not the end of file agReq := agents.NewAgentRequest( - config.NewSliceDP(record), reqVars, + config.NewSliceDP(record, utils.EmptyString), reqVars, nil, nil, rdr.Config().Tenant, rdr.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(rdr.Config().Timezone, diff --git a/general_tests/filters_it_test.go b/general_tests/filters_it_test.go index 29af53763..cc7734f0f 100644 --- a/general_tests/filters_it_test.go +++ b/general_tests/filters_it_test.go @@ -372,12 +372,8 @@ func testV1FltrGetThresholdForEvent2(t *testing.T) { func testV1FltrPopulateResources(t *testing.T) { //create a resourceProfile rlsConfig := &engine.ResourceProfile{ - Tenant: "cgrates.org", - ID: "ResTest", - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - }, + Tenant: "cgrates.org", + ID: "ResTest", UsageTTL: time.Duration(1) * time.Minute, Limit: 10, AllocationMessage: "MessageAllocation", @@ -442,10 +438,6 @@ func testV1FltrPopulateResources(t *testing.T) { Tenant: "cgrates.org", ID: "TH_ResTest", FilterIDs: []string{"FLTR_TH_Resource", "*string:~*req.Account:2020"}, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - }, MaxHits: -1, MinSleep: time.Duration(1 * time.Millisecond), Weight: 10.0, @@ -559,10 +551,6 @@ func testV1FltrAccounts(t *testing.T) { Tenant: "cgrates.org", ID: "TH_Account", FilterIDs: []string{"FLTR_TH_Accounts", "*string:~*req.Account:1001"}, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), - }, MaxHits: -1, MinSleep: time.Duration(1 * time.Millisecond), Weight: 90.0, diff --git a/general_tests/objectdp_test.go b/general_tests/objectdp_test.go index 0126c9fe1..6ae73c600 100644 --- a/general_tests/objectdp_test.go +++ b/general_tests/objectdp_test.go @@ -37,7 +37,7 @@ func TestAccountNewObjectDPFieldAsInterface(t *testing.T) { }, }, } - accDP := config.NewObjectDP(acc) + accDP := config.NewObjectDP(acc, nil) if data, err := accDP.FieldAsInterface([]string{"BalanceMap", "*monetary[0]", "Value"}); err != nil { t.Error(err) } else if data != 20. { @@ -65,7 +65,7 @@ func TestAccountNewObjectDPFieldAsInterfaceFromCache(t *testing.T) { }, }, } - accDP := config.NewObjectDP(acc) + accDP := config.NewObjectDP(acc, nil) if data, err := accDP.FieldAsInterface([]string{"BalanceMap", "*monetary[0]", "Value"}); err != nil { t.Error(err)