diff --git a/config/config.go b/config/config.go index e8dcfc582..72a1bf98c 100644 --- a/config/config.go +++ b/config/config.go @@ -167,88 +167,89 @@ func NewCGRConfigFromFolder(cfgDir string) (*CGRConfig, error) { // Holds system configuration, defaults are overwritten with values from config file if found type CGRConfig struct { - TpDbType string - TpDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets. - TpDbPort string // The port to bind to. - TpDbName string // The name of the database to connect to. - TpDbUser string // The user to sign in as. - TpDbPass string // The user's password. - DataDbType string - DataDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets. - DataDbPort string // The port to bind to. - DataDbName string // The name of the database to connect to. - DataDbUser string // The user to sign in as. - DataDbPass string // The user's password. - LoadHistorySize int // Maximum number of records to archive in load history - StorDBType string // Should reflect the database type used to store logs - StorDBHost string // The host to connect to. Values that start with / are for UNIX domain sockets. - StorDBPort string // Th e port to bind to. - StorDBName string // The name of the database to connect to. - StorDBUser string // The user to sign in as. - StorDBPass string // The user's password. - StorDBMaxOpenConns int // Maximum database connections opened - StorDBMaxIdleConns int // Maximum idle connections to keep opened - StorDBCDRSIndexes []string - DBDataEncoding string // The encoding used to store object data in strings: - RPCJSONListen string // RPC JSON listening address - RPCGOBListen string // RPC GOB listening address - HTTPListen string // HTTP listening address - DefaultReqType string // Use this request type if not defined on top - DefaultCategory string // set default type of record - DefaultTenant string // set default tenant - DefaultSubject string // set default rating subject, useful in case of fallback - DefaultTimezone string // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> - Reconnects int // number of recconect attempts in case of connection lost <-1 for infinite | nb> - ConnectAttempts int // number of initial connection attempts before giving up - ResponseCacheTTL time.Duration // the life span of a cached response - InternalTtl time.Duration // maximum duration to wait for internal connections before giving up - RoundingDecimals int // Number of decimals to round end prices at - HttpSkipTlsVerify bool // If enabled Http Client will accept any TLS certificate - TpExportPath string // Path towards export folder for offline Tariff Plans - HttpFailedDir string // Directory path where we store failed http requests - MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file - RaterEnabled bool // start standalone server (no balancer) - RaterBalancer string // balancer address host:port - RaterCdrStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234> - RaterHistoryServer string - RaterPubSubServer string - RaterUserServer string - RaterAliasesServer string - BalancerEnabled bool - SchedulerEnabled bool - CDRSEnabled bool // Enable CDR Server service - CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs - CDRSStoreCdrs bool // store cdrs in storDb - CDRSRater string // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234> - CDRSPubSub string // address where to reach the pubsub service: <""|internal|x.y.z.y:1234> - CDRSUsers string // address where to reach the users service: <""|internal|x.y.z.y:1234> - CDRSAliases string // address where to reach the aliases service: <""|internal|x.y.z.y:1234> - CDRSStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234> - CDRSCdrReplication []*CdrReplicationCfg // Replicate raw CDRs to a number of servers - CDRStatsEnabled bool // Enable CDR Stats service - CDRStatsSaveInterval time.Duration // Save interval duration - CdreProfiles map[string]*CdreConfig - CdrcProfiles map[string]map[string]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath]map[instanceName]{Configs} - SmGenericConfig *SmGenericConfig - SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration - SmKamConfig *SmKamConfig // SM-Kamailio Configuration - SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration - diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration - HistoryServer string // Address where to reach the master history server: - HistoryServerEnabled bool // Starts History as server: . - HistoryDir string // Location on disk where to store history files. - HistorySaveInterval time.Duration // The timout duration between pubsub writes - PubSubServerEnabled bool // Starts PubSub as server: . - AliasesServerEnabled bool // Starts PubSub as server: . - UserServerEnabled bool // Starts User as server: - UserServerIndexes []string // List of user profile field indexes - MailerServer string // The server to use when sending emails out - MailerAuthUser string // Authenticate to email server using this user - MailerAuthPass string // Authenticate to email server with this password - MailerFromAddr string // From address used when sending emails out - DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options - sureTaxCfg *SureTaxCfg // Load here SureTax configuration, as pointer so we can have runtime reloads in the future - ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur + TpDbType string + TpDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets. + TpDbPort string // The port to bind to. + TpDbName string // The name of the database to connect to. + TpDbUser string // The user to sign in as. + TpDbPass string // The user's password. + DataDbType string + DataDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets. + DataDbPort string // The port to bind to. + DataDbName string // The name of the database to connect to. + DataDbUser string // The user to sign in as. + DataDbPass string // The user's password. + LoadHistorySize int // Maximum number of records to archive in load history + StorDBType string // Should reflect the database type used to store logs + StorDBHost string // The host to connect to. Values that start with / are for UNIX domain sockets. + StorDBPort string // Th e port to bind to. + StorDBName string // The name of the database to connect to. + StorDBUser string // The user to sign in as. + StorDBPass string // The user's password. + StorDBMaxOpenConns int // Maximum database connections opened + StorDBMaxIdleConns int // Maximum idle connections to keep opened + StorDBCDRSIndexes []string + DBDataEncoding string // The encoding used to store object data in strings: + RPCJSONListen string // RPC JSON listening address + RPCGOBListen string // RPC GOB listening address + HTTPListen string // HTTP listening address + DefaultReqType string // Use this request type if not defined on top + DefaultCategory string // set default type of record + DefaultTenant string // set default tenant + DefaultSubject string // set default rating subject, useful in case of fallback + DefaultTimezone string // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> + Reconnects int // number of recconect attempts in case of connection lost <-1 for infinite | nb> + ConnectAttempts int // number of initial connection attempts before giving up + ResponseCacheTTL time.Duration // the life span of a cached response + InternalTtl time.Duration // maximum duration to wait for internal connections before giving up + RoundingDecimals int // Number of decimals to round end prices at + HttpSkipTlsVerify bool // If enabled Http Client will accept any TLS certificate + TpExportPath string // Path towards export folder for offline Tariff Plans + HttpFailedDir string // Directory path where we store failed http requests + MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file + RaterEnabled bool // start standalone server (no balancer) + RaterBalancer string // balancer address host:port + RaterCdrStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234> + RaterHistoryServer string + RaterPubSubServer string + RaterUserServer string + RaterAliasesServer string + RpSubjectPrefixMatching bool // enables prefix matching for the rating profile subject + BalancerEnabled bool + SchedulerEnabled bool + CDRSEnabled bool // Enable CDR Server service + CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs + CDRSStoreCdrs bool // store cdrs in storDb + CDRSRater string // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234> + CDRSPubSub string // address where to reach the pubsub service: <""|internal|x.y.z.y:1234> + CDRSUsers string // address where to reach the users service: <""|internal|x.y.z.y:1234> + CDRSAliases string // address where to reach the aliases service: <""|internal|x.y.z.y:1234> + CDRSStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234> + CDRSCdrReplication []*CdrReplicationCfg // Replicate raw CDRs to a number of servers + CDRStatsEnabled bool // Enable CDR Stats service + CDRStatsSaveInterval time.Duration // Save interval duration + CdreProfiles map[string]*CdreConfig + CdrcProfiles map[string]map[string]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath]map[instanceName]{Configs} + SmGenericConfig *SmGenericConfig + SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration + SmKamConfig *SmKamConfig // SM-Kamailio Configuration + SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration + diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration + HistoryServer string // Address where to reach the master history server: + HistoryServerEnabled bool // Starts History as server: . + HistoryDir string // Location on disk where to store history files. + HistorySaveInterval time.Duration // The timout duration between pubsub writes + PubSubServerEnabled bool // Starts PubSub as server: . + AliasesServerEnabled bool // Starts PubSub as server: . + UserServerEnabled bool // Starts User as server: + UserServerIndexes []string // List of user profile field indexes + MailerServer string // The server to use when sending emails out + MailerAuthUser string // Authenticate to email server using this user + MailerAuthPass string // Authenticate to email server with this password + MailerFromAddr string // From address used when sending emails out + DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options + sureTaxCfg *SureTaxCfg // Load here SureTax configuration, as pointer so we can have runtime reloads in the future + ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur // Cache defaults loaded from json and needing clones dfltCdreProfile *CdreConfig // Default cdreConfig profile dfltCdrcProfile *CdrcConfig // Default cdrcConfig profile @@ -666,6 +667,9 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { if jsnRaterCfg.Users != nil { self.RaterUserServer = *jsnRaterCfg.Users } + if jsnRaterCfg.Rp_subject_prefix_matching != nil { + self.RpSubjectPrefixMatching = *jsnRaterCfg.Rp_subject_prefix_matching + } } if jsnBalancerCfg != nil && jsnBalancerCfg.Enabled != nil { diff --git a/config/config_defaults.go b/config/config_defaults.go index 0ef467e70..af1fdd041 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -99,6 +99,7 @@ const CGRATES_CFG_JSON = ` "pubsubs": "", // address where to reach the pubusb service, empty to disable pubsub functionality: <""|internal|x.y.z.y:1234> "users": "", // address where to reach the user service, empty to disable user profile functionality: <""|internal|x.y.z.y:1234> "aliases": "", // address where to reach the aliases service, empty to disable aliases functionality: <""|internal|x.y.z.y:1234> + "rp_subject_prefix_matching": false // enables prefix matching for the rating profile subject }, diff --git a/config/config_json_test.go b/config/config_json_test.go index e7ac7e927..462597e1f 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -56,7 +56,7 @@ func TestDfGeneralJsonCfg(t *testing.T) { if gCfg, err := dfCgrJsonCfg.GeneralJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, gCfg) { - t.Error("Received: ", gCfg) + t.Error("Received: ", utils.ToIJSON(gCfg)) } } @@ -129,7 +129,7 @@ func TestDfBalancerJsonCfg(t *testing.T) { func TestDfRaterJsonCfg(t *testing.T) { eCfg := &RaterJsonCfg{Enabled: utils.BoolPointer(false), Balancer: utils.StringPointer(""), Cdrstats: utils.StringPointer(""), - Historys: utils.StringPointer(""), Pubsubs: utils.StringPointer(""), Users: utils.StringPointer(""), Aliases: utils.StringPointer("")} + Historys: utils.StringPointer(""), Pubsubs: utils.StringPointer(""), Users: utils.StringPointer(""), Aliases: utils.StringPointer(""), Rp_subject_prefix_matching: utils.BoolPointer(false)} if cfg, err := dfCgrJsonCfg.RaterJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, cfg) { diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 7ab6b093a..58f25c529 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -64,13 +64,14 @@ type BalancerJsonCfg struct { // Rater config section type RaterJsonCfg struct { - Enabled *bool - Balancer *string - Cdrstats *string - Historys *string - Pubsubs *string - Aliases *string - Users *string + Enabled *bool + Balancer *string + Cdrstats *string + Historys *string + Pubsubs *string + Aliases *string + Users *string + Rp_subject_prefix_matching *bool } // Scheduler config section diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index e35dd57c7..8eec665c9 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -77,6 +77,7 @@ // "pubsubs": "", // address where to reach the pubusb service, empty to disable pubsub functionality: <""|internal|x.y.z.y:1234> // "users": "", // address where to reach the user service, empty to disable user profile functionality: <""|internal|x.y.z.y:1234> // "aliases": "", // address where to reach the aliases service, empty to disable aliases functionality: <""|internal|x.y.z.y:1234> +// "rp_subject_prefix_matching": false // enables prefix matching for the rating profile subject //}, @@ -334,4 +335,4 @@ // "tax_exemption_code_list": "", // template extracting tax exemption code list out of StoredCdr; <$RSRFields> //}, -} \ No newline at end of file +} diff --git a/engine/calldesc.go b/engine/calldesc.go index a7a033393..b5d2caffe 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -70,17 +70,17 @@ func init() { } var ( - ratingStorage RatingStorage - accountingStorage AccountingStorage - storageLogger LogStorage - cdrStorage CdrStorage - debitPeriod = 10 * time.Second - globalRoundingDecimals = 6 - historyScribe history.Scribe - pubSubServer rpcclient.RpcClientConnection - userService UserService - aliasService AliasService - prefixMatchingRatingProfile bool + ratingStorage RatingStorage + accountingStorage AccountingStorage + storageLogger LogStorage + cdrStorage CdrStorage + debitPeriod = 10 * time.Second + globalRoundingDecimals = 6 + historyScribe history.Scribe + pubSubServer rpcclient.RpcClientConnection + userService UserService + aliasService AliasService + rpSubjectPrefixMatching bool ) // Exported method to set the storage getter. @@ -97,8 +97,8 @@ func SetRoundingDecimals(rd int) { globalRoundingDecimals = rd } -func SetPrefixmatchingRatingProfile(flag bool) { - prefixMatchingRatingProfile = flag +func SetRpSubjectPrefixMatching(flag bool) { + rpSubjectPrefixMatching = flag } /* @@ -224,7 +224,7 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int if recursionDepth > RECURSION_MAX_DEPTH { return utils.ErrMaxRecursionDepth, recursionDepth } - rpf, err := PrefixMatchRatingProfileSubject(key) + rpf, err := RatingProfileSubjectPrefixMatching(key) if err != nil || rpf == nil { return utils.ErrNotFound, recursionDepth } @@ -1039,7 +1039,7 @@ func (cd *CallDescriptor) GetLCR(stats StatsInterface, p *utils.Paginator) (*LCR continue } rpfKey := utils.ConcatenatedKey(ratingProfileSearchKey, supplier) - if rpf, err := PrefixMatchRatingProfileSubject(rpfKey); err != nil { + if rpf, err := RatingProfileSubjectPrefixMatching(rpfKey); err != nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("Rating plan error: %s", err.Error()), diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 059ccf6f1..9ef1cfd27 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -246,8 +246,8 @@ type TenantRatingSubject struct { Tenant, Subject string } -func PrefixMatchRatingProfileSubject(key string) (rp *RatingProfile, err error) { - if !prefixMatchingRatingProfile { +func RatingProfileSubjectPrefixMatching(key string) (rp *RatingProfile, err error) { + if !rpSubjectPrefixMatching || strings.HasSuffix(key, utils.ANY) { return ratingStorage.GetRatingProfile(key, false) } if rp, err = ratingStorage.GetRatingProfile(key, false); err == nil { diff --git a/engine/ratingprofile_test.go b/engine/ratingprofile_test.go index a94598ad0..4f929029a 100644 --- a/engine/ratingprofile_test.go +++ b/engine/ratingprofile_test.go @@ -250,16 +250,16 @@ func TestRatingProfileRIforTSMidnight(t *testing.T) { } } -func TestPrefixMatchRatingProfileSubject(t *testing.T) { - prefixMatchingRatingProfile = true - rp, err := PrefixMatchRatingProfileSubject("*out:cgrates.org:data:rif") +func TestRatingProfileSubjectPrefixMatching(t *testing.T) { + rpSubjectPrefixMatching = true + rp, err := RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rif") if rp == nil || err != nil { t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) } - rp, err = PrefixMatchRatingProfileSubject("*out:cgrates.org:data:rifescu") + rp, err = RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rifescu") if rp == nil || err != nil { t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) } - prefixMatchingRatingProfile = false + rpSubjectPrefixMatching = false }