mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-14 20:59:53 +05:00
Added *profileIgnoreFilters for rates
This commit is contained in:
committed by
Dan Christian Bogos
parent
9ed3888fd2
commit
e1701b314e
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -1187,6 +1187,9 @@ const CGRATES_CFG_JSON = `
|
||||
"*intervalStart": { //
|
||||
"*default": "0",
|
||||
},
|
||||
"*profileIgnoreFilters": { // if we should check the filters
|
||||
"*default": false,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user