mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Finish updating integration test after modification
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user