Added *profileIgnoreFilters for rates

This commit is contained in:
Trial97
2021-10-11 08:51:57 +03:00
committed by Dan Christian Bogos
parent 9ed3888fd2
commit e1701b314e
12 changed files with 115 additions and 58 deletions

View File

@@ -318,6 +318,9 @@ func testCfgSetEmptyReload(t *testing.T) {
utils.MetaIntervalStartCfg: map[string]string{
utils.MetaDefault: decimal.New(0, 0).String(),
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}

View File

@@ -32,6 +32,7 @@ import (
"reflect"
"sort"
"testing"
"time"
"github.com/cgrates/birpc"
"github.com/cgrates/birpc/context"
@@ -77,16 +78,16 @@ func TestLoadConfig(t *testing.T) {
Name: "100",
User: "cgrates2",
Password: "toor",
Opts: map[string]interface{}{
utils.RedisSentinelNameCfg: "sentinel1",
utils.MongoQueryTimeoutCfg: "10s",
utils.RedisClusterSyncCfg: "5s",
utils.RedisClusterOnDownDelayCfg: "0",
utils.RedisClusterCfg: false,
utils.RedisTLSCfg: false,
utils.RedisClientCertificateCfg: "",
utils.RedisClientKeyCfg: "",
utils.RedisCACertificateCfg: "",
Opts: &config.DataDBOpts{
RedisSentinel: "sentinel1",
MongoQueryTimeout: 10 * time.Second,
RedisClusterSync: 5 * time.Second,
RedisClusterOndownDelay: 0,
RedisCluster: false,
RedisTLS: false,
RedisClientCertificate: "",
RedisClientKey: "",
RedisCACertificate: "",
},
RmtConns: []string{},
RplConns: []string{},
@@ -107,13 +108,13 @@ func TestLoadConfig(t *testing.T) {
Password: "toor",
StringIndexedFields: []string{},
PrefixIndexedFields: []string{},
Opts: map[string]interface{}{
utils.SQLConnMaxLifetimeCfg: 0.,
utils.MongoQueryTimeoutCfg: "10s",
utils.SQLMaxOpenConnsCfg: 100.,
utils.SQLMaxIdleConnsCfg: 10.,
utils.SSLModeCfg: "disable",
utils.MysqlLocation: "Local",
Opts: &config.StorDBOpts{
SQLConnMaxLifetime: 0.,
MongoQueryTimeout: 10 * time.Second,
SQLMaxOpenConns: 100.,
SQLMaxIdleConns: 10.,
SSLMode: "disable",
MySQLLocation: "Local",
},
}
// Loader

View File

@@ -158,7 +158,7 @@ func (attrOpts AttributesOpts) Clone() *AttributesOpts {
profileRuns = utils.CloneDynamicIntOpt(attrOpts.ProfileRuns)
}
var profileIgnoreFilters []*utils.DynamicBoolOpt
if attrOpts.ProfileRuns != nil {
if attrOpts.ProfileIgnoreFilters != nil {
profileIgnoreFilters = utils.CloneDynamicBoolOpt(attrOpts.ProfileIgnoreFilters)
}
return &AttributesOpts{

View File

@@ -1187,6 +1187,9 @@ const CGRATES_CFG_JSON = `
"*intervalStart": { //
"*default": "0",
},
"*profileIgnoreFilters": { // if we should check the filters
"*default": false,
}
},
},

View File

@@ -2047,6 +2047,9 @@ func TestDfRateSJsonCfg(t *testing.T) {
IntervalStart: map[string]string{
utils.MetaDefault: "0",
},
ProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON))

File diff suppressed because one or more lines are too long

View File

@@ -24,10 +24,11 @@ import (
)
type RatesOpts struct {
RateProfileIDs []*utils.DynamicStringSliceOpt
StartTime []*utils.DynamicStringOpt
Usage []*utils.DynamicDecimalBigOpt
IntervalStart []*utils.DynamicDecimalBigOpt
RateProfileIDs []*utils.DynamicStringSliceOpt
StartTime []*utils.DynamicStringOpt
Usage []*utils.DynamicDecimalBigOpt
IntervalStart []*utils.DynamicDecimalBigOpt
ProfileIgnoreFilters []*utils.DynamicBoolOpt
}
// RateSCfg the rates config section
@@ -80,6 +81,9 @@ func (rateOpts *RatesOpts) loadFromJSONCfg(jsnCfg *RatesOptsJson) (err error) {
}
rateOpts.IntervalStart = append(rateOpts.IntervalStart, intervalStart...)
}
if jsnCfg.ProfileIgnoreFilters != nil {
rateOpts.ProfileIgnoreFilters = append(rateOpts.ProfileIgnoreFilters, utils.MapToDynamicBoolOpts(jsnCfg.ProfileIgnoreFilters)...)
}
return
}
@@ -133,10 +137,11 @@ func (rCfg *RateSCfg) loadFromJSONCfg(jsnCfg *RateSJsonCfg) (err error) {
// AsMapInterface returns the config as a map[string]interface{}
func (rCfg RateSCfg) AsMapInterface(string) interface{} {
opts := map[string]interface{}{
utils.MetaRateProfileIDsCfg: utils.DynamicStringSliceOptsToMap(rCfg.Opts.RateProfileIDs),
utils.MetaStartTime: utils.DynamicStringOptsToMap(rCfg.Opts.StartTime),
utils.MetaUsage: utils.DynamicDecimalBigOptsToMap(rCfg.Opts.Usage),
utils.MetaIntervalStartCfg: utils.DynamicDecimalBigOptsToMap(rCfg.Opts.IntervalStart),
utils.MetaRateProfileIDsCfg: utils.DynamicStringSliceOptsToMap(rCfg.Opts.RateProfileIDs),
utils.MetaStartTime: utils.DynamicStringOptsToMap(rCfg.Opts.StartTime),
utils.MetaUsage: utils.DynamicDecimalBigOptsToMap(rCfg.Opts.Usage),
utils.MetaIntervalStartCfg: utils.DynamicDecimalBigOptsToMap(rCfg.Opts.IntervalStart),
utils.MetaProfileIgnoreFilters: utils.DynamicBoolOptsToMap(rCfg.Opts.ProfileIgnoreFilters),
}
mp := map[string]interface{}{
utils.EnabledCfg: rCfg.Enabled,
@@ -188,11 +193,16 @@ func (rateOpts *RatesOpts) Clone() *RatesOpts {
if rateOpts.IntervalStart != nil {
intervalStart = utils.CloneDynamicDecimalBigOpt(rateOpts.IntervalStart)
}
var profileIgnoreFilters []*utils.DynamicBoolOpt
if rateOpts.ProfileIgnoreFilters != nil {
profileIgnoreFilters = utils.CloneDynamicBoolOpt(rateOpts.ProfileIgnoreFilters)
}
return &RatesOpts{
RateProfileIDs: ratePrfIDs,
StartTime: startTime,
Usage: usage,
IntervalStart: intervalStart,
RateProfileIDs: ratePrfIDs,
StartTime: startTime,
Usage: usage,
IntervalStart: intervalStart,
ProfileIgnoreFilters: profileIgnoreFilters,
}
}
@@ -230,10 +240,11 @@ func (rCfg RateSCfg) Clone() (cln *RateSCfg) {
}
type RatesOptsJson struct {
RateProfileIDs map[string][]string `json:"*rateProfileIDs"`
StartTime map[string]string `json:"*startTime"`
Usage map[string]string `json:"*usage"`
IntervalStart map[string]string `json:"*intervalStart"`
RateProfileIDs map[string][]string `json:"*rateProfileIDs"`
StartTime map[string]string `json:"*startTime"`
Usage map[string]string `json:"*usage"`
IntervalStart map[string]string `json:"*intervalStart"`
ProfileIgnoreFilters map[string]bool `json:"*profileIgnoreFilters"`
}
type RateSJsonCfg struct {
@@ -268,6 +279,9 @@ func diffRatesOptsJsonCfg(d *RatesOptsJson, v1, v2 *RatesOpts) *RatesOptsJson {
if !utils.DynamicDecimalBigOptEqual(v1.IntervalStart, v2.IntervalStart) {
d.IntervalStart = utils.DynamicDecimalBigOptsToMap(v2.IntervalStart)
}
if !utils.DynamicBoolOptEqual(v1.ProfileIgnoreFilters, v2.ProfileIgnoreFilters) {
d.ProfileIgnoreFilters = utils.DynamicBoolOptsToMap(v2.ProfileIgnoreFilters)
}
return d
}

View File

@@ -80,6 +80,12 @@ func TestRateSConfigloadFromJsonCfg(t *testing.T) {
Value: decimal.New(0, 0),
},
},
ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
{
FilterIDs: []string{utils.MetaDefault},
Value: false,
},
},
},
}
jsonCfg := NewDefaultCGRConfig()
@@ -118,6 +124,9 @@ func TestRatesCfgAsMapInterface(t *testing.T) {
utils.MetaIntervalStartCfg: map[string]string{
utils.MetaDefault: decimal.New(0, 0).String(),
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {
@@ -169,6 +178,9 @@ func TestRatesCfgAsMapInterface1(t *testing.T) {
utils.MetaIntervalStartCfg: map[string]string{
utils.MetaDefault: decimal.New(0, 0).String(),
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {

View File

@@ -55,12 +55,10 @@ func (alS *AttributeService) Shutdown() {
}
// attributeProfileForEvent returns the matching attribute
func (alS *AttributeService) attributeProfileForEvent(ctx *context.Context, tnt string, attrsIDs []string,
func (alS *AttributeService) attributeProfileForEvent(ctx *context.Context, tnt string, attrIDs []string,
evNm utils.MapStorage, lastID string, processedPrfNo map[string]int, profileRuns int, ignoreFilters bool) (matchAttrPrfl *AttributeProfile, err error) {
var attrIDs []string
if len(attrsIDs) != 0 {
attrIDs = attrsIDs
} else {
if len(attrIDs) == 0 {
ignoreFilters = false
aPrflIDs, err := MatchingItemIDsForEvent(ctx, evNm,
alS.cgrcfg.AttributeSCfg().StringIndexedFields,
alS.cgrcfg.AttributeSCfg().PrefixIndexedFields,
@@ -84,7 +82,7 @@ func (alS *AttributeService) attributeProfileForEvent(ctx *context.Context, tnt
}
tntID := aPrfl.TenantIDInline()
(evNm[utils.MetaVars].(utils.MapStorage))[utils.MetaAttrPrfTenantID] = tntID
if len(attrsIDs) == 0 || !ignoreFilters {
if !ignoreFilters {
if pass, err := alS.filterS.Pass(ctx, tnt, aPrfl.FilterIDs,
evNm); err != nil {
return nil, err

View File

@@ -97,7 +97,7 @@ func TestStorDBit(t *testing.T) {
if storDB, err = NewPostgresStorage(cfg.StorDbCfg().Host,
cfg.StorDbCfg().Port, cfg.StorDbCfg().Name,
cfg.StorDbCfg().User, cfg.StorDbCfg().Password,
utils.IfaceAsString(cfg.StorDbCfg().Opts[utils.SSLModeCfg]),
cfg.StorDbCfg().Opts.SSLMode,
100, 10, 0); err != nil {
t.Fatal(err)
}

View File

@@ -67,12 +67,13 @@ func (rS *RateS) Shutdown() (err error) {
}
// matchingRateProfileForEvent returns the matched RateProfile for the given event
func (rS *RateS) matchingRateProfileForEvent(ctx *context.Context, tnt string, rPfIDs []string, args *utils.CGREvent) (rtPfl *utils.RateProfile, err error) {
func (rS *RateS) matchingRateProfileForEvent(ctx *context.Context, tnt string, rPfIDs []string, args *utils.CGREvent, ignoreFilters bool) (rtPfl *utils.RateProfile, err error) {
evNm := utils.MapStorage{
utils.MetaReq: args.Event,
utils.MetaOpts: args.APIOpts,
}
if len(rPfIDs) == 0 {
ignoreFilters = false
var rPfIDMp utils.StringSet
if rPfIDMp, err = engine.MatchingItemIDsForEvent(ctx,
evNm,
@@ -100,11 +101,13 @@ func (rS *RateS) matchingRateProfileForEvent(ctx *context.Context, tnt string, r
}
return
}
var pass bool
if pass, err = rS.filterS.Pass(ctx, tnt, rPf.FilterIDs, evNm); err != nil {
return
} else if !pass {
continue
if !ignoreFilters {
var pass bool
if pass, err = rS.filterS.Pass(ctx, tnt, rPf.FilterIDs, evNm); err != nil {
return
} else if !pass {
continue
}
}
var rPfWeight float64
if rPfWeight, err = engine.WeightFromDynamics(ctx, rPf.Weights,
@@ -217,8 +220,13 @@ func (rS *RateS) V1CostForEvent(ctx *context.Context, args *utils.CGREvent, rpCo
utils.OptsRatesRateProfileIDs); err != nil {
return
}
var ignFilters bool
if ignFilters, err = engine.GetBoolOpts(ctx, args.Tenant, args, rS.filterS, rS.cfg.RateSCfg().Opts.ProfileIgnoreFilters,
utils.MetaProfileIgnoreFilters); err != nil {
return
}
var rtPrl *utils.RateProfile
if rtPrl, err = rS.matchingRateProfileForEvent(ctx, args.Tenant, rPfIDs, args); err != nil {
if rtPrl, err = rS.matchingRateProfileForEvent(ctx, args.Tenant, rPfIDs, args, ignFilters); err != nil {
if err != utils.ErrNotFound {
err = utils.NewErrServerError(err)
}

View File

@@ -311,7 +311,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 1002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err != nil {
}, false); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rtPRf, rpp) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(rpp), utils.ToJSON(rtPRf))
@@ -326,7 +326,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 2002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err != utils.ErrNotFound {
}, false); err != utils.ErrNotFound {
t.Error(err)
}
if _, err := rate.matchingRateProfileForEvent(context.TODO(), "cgrates.org", []string{},
@@ -338,7 +338,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 2002,
utils.AnswerTime: t1.Add(10 * time.Second),
},
}); err != utils.ErrNotFound {
}, false); err != utils.ErrNotFound {
t.Error(err)
}
if _, err := rate.matchingRateProfileForEvent(context.TODO(), "cgrates.org", []string{},
@@ -350,7 +350,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 1002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err != utils.ErrNotFound {
}, false); err != utils.ErrNotFound {
t.Error(err)
}
@@ -363,7 +363,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 1002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err != utils.ErrNotFound {
}, false); err != utils.ErrNotFound {
t.Error(err)
}
rpp.FilterIDs = []string{"*string:~*req.Account:1001|1002|1003", "*gt:~*req.Cost{*:10"}
@@ -376,7 +376,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Cost: 1002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err.Error() != "invalid converter terminator in rule: <~*req.Cost{*>" {
}, false); err.Error() != "invalid converter terminator in rule: <~*req.Cost{*>" {
t.Error(err)
}
rpp.FilterIDs = []string{"*string:~*req.Account:1001|1002|1003"}
@@ -391,7 +391,7 @@ func TestMatchingRateProfileEvent(t *testing.T) {
utils.Destination: 1002,
utils.AnswerTime: t1.Add(-10 * time.Second),
},
}); err != utils.ErrNoDatabaseConn {
}, false); err != utils.ErrNoDatabaseConn {
t.Error(err)
}
@@ -920,7 +920,7 @@ func TestRateSMatchingRateProfileForEventErrFltr(t *testing.T) {
utils.Destination: 1002,
utils.AnswerTime: time.Date(9999, 7, 21, 10, 0, 0, 0, time.UTC).Add(-10 * time.Second),
},
})
}, false)
expectedErr := "NOT_FOUND"
if err == nil || err.Error() != expectedErr {
t.Errorf("\nExpected <%+v>, \nReceived <%+v>", expectedErr, err)