diff --git a/apier/v1/suppliers_it_test.go b/apier/v1/suppliers_it_test.go index 149e98569c..429bee095b 100644 --- a/apier/v1/suppliers_it_test.go +++ b/apier/v1/suppliers_it_test.go @@ -67,10 +67,9 @@ var ( testV1SplSRemSupplierProfiles, testV1SplSGetSupplierForEvent, // reset the database and load the TP again - // testV1SplSInitDataDb, - // testV1SplSFromFolder, - // for the moment we decide to comment the tests - // testV1SplsOneSupplierWithoutDestination, + testV1SplSInitDataDb, + testV1SplSFromFolder, + testV1SplsOneSupplierWithoutDestination, testV1SplSupplierPing, testV1SplSStopEngine, } @@ -1085,7 +1084,6 @@ func testV1SplsOneSupplierWithoutDestination(t *testing.T) { utils.Usage: "2m", }, }, - IgnoreErrors: true, } eSpls := engine.SortedSuppliers{ ProfileID: "SPL_DESTINATION", @@ -1110,14 +1108,6 @@ func testV1SplsOneSupplierWithoutDestination(t *testing.T) { t.Errorf("Expecting: %s, received: %s", utils.ToJSON(eSpls), utils.ToJSON(suplsReply)) } - - //in case that we don't use ignore errors - //we get an error for the second supplier - ev.IgnoreErrors = false - if err := splSv1Rpc.Call(utils.SupplierSv1GetSuppliers, - ev, &suplsReply); err != nil { - t.Error(err) - } } func testV1SplSStopEngine(t *testing.T) { diff --git a/engine/filters.go b/engine/filters.go index ebd3ddf7a8..5de6b533d6 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -77,6 +77,70 @@ func (fS *FilterS) Pass(tenant string, filterIDs []string, return } +//verifyPrefixes verify the Element and the Values if has as prefix one of the prefixes +func verifyPrefixes(rule *FilterRule, prefixes []string) (hasPrefix bool) { + if strings.HasPrefix(rule.Element, utils.DynamicDataPrefix) { + for _, prefix := range prefixes { + if strings.HasPrefix(rule.Element, prefix) { + hasPrefix = true + break + } + } + if !hasPrefix { + return false + } + } + for _, value := range rule.Values { + if strings.HasPrefix(value, utils.DynamicDataPrefix) { + for _, prefix := range prefixes { + if strings.HasPrefix(value, prefix) { + hasPrefix = true + break + } + } + if !hasPrefix { + return false + } + } + } + return true +} + +//PartialPass is almost the same as Pass except that it verify if the +//Element of the Values from FilterRules has as prefix one of the pathPrfxs +func (fS *FilterS) PartialPass(tenant string, filterIDs []string, + ev config.DataProvider, pathPrfxs []string) (pass bool, err error) { + if len(filterIDs) == 0 { + return true, nil + } + pass = true + for _, fltrID := range filterIDs { + f, err := GetFilter(fS.dm, tenant, fltrID, + true, true, utils.NonTransactional) + if err != nil { + if err == utils.ErrNotFound { + err = utils.ErrPrefixNotFound(fltrID) + } + return false, err + } + if f.ActivationInterval != nil && + !f.ActivationInterval.IsActiveAtTime(time.Now()) { // not active + continue + } + + for _, rule := range f.Rules { + if !verifyPrefixes(rule, pathPrfxs) { + continue + } + dDP := newDynamicDP(fS.cfg, fS.connMgr, tenant, ev) + if pass, err = rule.Pass(dDP); err != nil || !pass { + return pass, err + } + } + } + return +} + // NewFilterFromInline parses an inline rule into a compiled Filter func NewFilterFromInline(tenant, inlnRule string) (f *Filter, err error) { ruleSplt := strings.SplitN(inlnRule, utils.InInFieldSep, 3) @@ -120,7 +184,7 @@ func (fltr *Filter) TenantID() string { return utils.ConcatenatedKey(fltr.Tenant, fltr.ID) } -// Compile will compile the underlaying request filters where necessary (ie. regexp rules) +// Compile will compile the underlying request filters where necessary (ie. regexp rules) func (fltr *Filter) Compile() (err error) { for _, rf := range fltr.Rules { if err = rf.CompileValues(); err != nil { @@ -174,7 +238,7 @@ func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error) } // FilterRule filters requests coming into various places -// Pass rule: default negative, one mathing rule should pass the filter +// Pass rule: default negative, one matching rule should pass the filter type FilterRule struct { Type string // Filter type (*string, *timing, *rsr_filters, *stats, *lt, *lte, *gt, *gte) Element string // Name of the field providing us the Values to check (used in case of some ) diff --git a/engine/libsuppliers.go b/engine/libsuppliers.go index 466ffe5d20..dfc2440156 100644 --- a/engine/libsuppliers.go +++ b/engine/libsuppliers.go @@ -108,7 +108,7 @@ func (sSpls *SortedSuppliers) SortQOS(params []string) { return true } return false - case utils.MetaPDD: //in case of pdd the smalles value if the best + case utils.MetaPDD: //in case of pdd the smallest value if the best if sSpls.SortedSuppliers[i].SortingData[param].(float64) < sSpls.SortedSuppliers[j].SortingData[param].(float64) { return true } @@ -213,5 +213,11 @@ func (ssd SupplierSortDispatcher) SortSuppliers(prflID, strategy string, if !has { return nil, fmt.Errorf("unsupported sorting strategy: %s", strategy) } - return sd.SortSuppliers(prflID, suppls, suplEv, extraOpts) + if sortedSuppls, err = sd.SortSuppliers(prflID, suppls, suplEv, extraOpts); err != nil { + return + } + if len(sortedSuppls.SortedSuppliers) == 0 { + return nil, utils.ErrNotFound + } + return } diff --git a/engine/spls_highestcost.go b/engine/spls_highestcost.go index deeb68b12b..b447dabd47 100755 --- a/engine/spls_highestcost.go +++ b/engine/spls_highestcost.go @@ -53,9 +53,6 @@ func (hcs *HightCostSorter) SortSuppliers(prflID string, suppls []*Supplier, sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl) } } - if len(sortedSuppls.SortedSuppliers) == 0 { - return nil, utils.ErrNotFound - } sortedSuppls.SortHighestCost() return } diff --git a/engine/spls_leastcost.go b/engine/spls_leastcost.go index 9a50a7138e..ca85e00050 100644 --- a/engine/spls_leastcost.go +++ b/engine/spls_leastcost.go @@ -53,9 +53,6 @@ func (lcs *LeastCostSorter) SortSuppliers(prflID string, suppls []*Supplier, sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl) } } - if len(sortedSuppls.SortedSuppliers) == 0 { - return nil, utils.ErrNotFound - } sortedSuppls.SortLeastCost() return } diff --git a/engine/spls_qos.go b/engine/spls_qos.go index 3c425cb03e..6ef375d668 100755 --- a/engine/spls_qos.go +++ b/engine/spls_qos.go @@ -45,9 +45,6 @@ func (qos *QOSSupplierSorter) SortSuppliers(prflID string, suppls []*Supplier, sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl) } } - if len(sortedSuppls.SortedSuppliers) == 0 { - return nil, utils.ErrNotFound - } sortedSuppls.SortQOS(extraOpts.sortingParameters) return } diff --git a/engine/suppliers.go b/engine/suppliers.go index f342275ed3..a7635e0928 100644 --- a/engine/suppliers.go +++ b/engine/suppliers.go @@ -491,8 +491,24 @@ func (spS *SupplierService) sortedSuppliersForEvent(args *ArgsGetSuppliers) (sor } extraOpts.sortingParameters = splPrfl.SortingParameters // populate sortingParameters in extraOpts extraOpts.sortingStragety = splPrfl.Sorting // populate sortinStrategy in extraOpts + + //construct the DP and pass it to filterS + nM := config.NewNavigableMap(nil) + nM.Set([]string{utils.MetaReq}, args.CGREvent.Event, false, false) + supplNew := make([]*Supplier, 0) + // apply filters for event + for _, suppl := range splPrfl.Suppliers { + if pass, err := spS.filterS.PartialPass(args.CGREvent.Tenant, suppl.FilterIDs, + nM, []string{utils.DynamicDataPrefix + utils.MetaReq}); err != nil { + return nil, err + } else if !pass { + continue + } + supplNew = append(supplNew, suppl) + } + sortedSuppliers, err := spS.sorter.SortSuppliers(splPrfl.ID, splPrfl.Sorting, - splPrfl.Suppliers, args.CGREvent, extraOpts) + supplNew, args.CGREvent, extraOpts) if err != nil { return nil, err } diff --git a/packages/debian/changelog b/packages/debian/changelog index 4724a5f9bd..5f041d579c 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -44,6 +44,8 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [SessionS] Move *cost as subflag in *rals for SessionSv1.ProcessEvent * [DiameterAgent] Added DPR support + * [SupplierS] Add verification for event filters before populating + data -- Alexandru Tripon Wed, 19 Feb 2020 13:25:52 +0200