Added separate config structures for: Cdrs config, CdrStatscfg config

This commit is contained in:
Trial97
2018-10-24 16:29:48 +03:00
committed by Dan Christian Bogos
parent 97ff5fabc5
commit 26cbbdd618
11 changed files with 664 additions and 399 deletions

View File

@@ -470,13 +470,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
utils.Logger.Info("Starting CGRateS CDRS service.")
var ralConn, pubSubConn, usersConn, attrSConn, aliasesConn, cdrstatsConn,
thresholdSConn, statsConn, chargerSConn *rpcclient.RpcClientPool
if len(cfg.CDRSChargerSConns) != 0 { // Conn pool towards RAL
if len(cfg.CdrsCfg().CDRSChargerSConns) != 0 { // Conn pool towards RAL
chargerSConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSChargerSConns, internalChargerSChan,
cfg.CdrsCfg().CDRSChargerSConns, internalChargerSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to %s: %s",
@@ -485,13 +485,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSRaterConns) != 0 { // Conn pool towards RAL
if len(cfg.CdrsCfg().CDRSRaterConns) != 0 { // Conn pool towards RAL
ralConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSRaterConns, internalRaterChan,
cfg.CdrsCfg().CDRSRaterConns, internalRaterChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to RAL: %s", err.Error()))
@@ -499,13 +499,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSPubSubSConns) != 0 { // Pubsub connection init
if len(cfg.CdrsCfg().CDRSPubSubSConns) != 0 { // Pubsub connection init
pubSubConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSPubSubSConns, internalPubSubSChan,
cfg.CdrsCfg().CDRSPubSubSConns, internalPubSubSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to PubSubSystem: %s", err.Error()))
@@ -513,13 +513,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSAttributeSConns) != 0 { // Users connection init
if len(cfg.CdrsCfg().CDRSAttributeSConns) != 0 { // Users connection init
attrSConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSAttributeSConns, internalAttributeSChan,
cfg.CdrsCfg().CDRSAttributeSConns, internalAttributeSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to %s: %s",
@@ -528,13 +528,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSUserSConns) != 0 { // Users connection init
if len(cfg.CdrsCfg().CDRSUserSConns) != 0 { // Users connection init
usersConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSUserSConns, internalUserSChan,
cfg.CdrsCfg().CDRSUserSConns, internalUserSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to UserS: %s", err.Error()))
@@ -542,13 +542,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSAliaseSConns) != 0 { // Aliases connection init
if len(cfg.CdrsCfg().CDRSAliaseSConns) != 0 { // Aliases connection init
aliasesConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSAliaseSConns, internalAliaseSChan,
cfg.CdrsCfg().CDRSAliaseSConns, internalAliaseSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to AliaseS: %s", err.Error()))
@@ -556,13 +556,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSCDRStatSConns) != 0 { // Stats connection init
if len(cfg.CdrsCfg().CDRSCDRStatSConns) != 0 { // Stats connection init
cdrstatsConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSCDRStatSConns, internalCdrStatSChan,
cfg.CdrsCfg().CDRSCDRStatSConns, internalCdrStatSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to CDRStatS: %s", err.Error()))
@@ -570,13 +570,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSThresholdSConns) != 0 { // Stats connection init
if len(cfg.CdrsCfg().CDRSThresholdSConns) != 0 { // Stats connection init
thresholdSConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSThresholdSConns, internalThresholdSChan,
cfg.CdrsCfg().CDRSThresholdSConns, internalThresholdSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to ThresholdS: %s", err.Error()))
@@ -584,13 +584,13 @@ func startCDRS(internalCdrSChan chan rpcclient.RpcClientConnection,
return
}
}
if len(cfg.CDRSStatSConns) != 0 { // Stats connection init
if len(cfg.CdrsCfg().CDRSStatSConns) != 0 { // Stats connection init
statsConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
cfg.TlsCfg().ClientKey,
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
cfg.CDRSStatSConns, internalStatSChan,
cfg.CdrsCfg().CDRSStatSConns, internalStatSChan,
cfg.GeneralCfg().InternalTtl)
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<CDRS> Could not connect to StatS: %s", err.Error()))
@@ -626,7 +626,7 @@ func startScheduler(internalSchedulerChan chan *scheduler.Scheduler, cacheDoneCh
}
func startCdrStats(internalCdrStatSChan chan rpcclient.RpcClientConnection, dm *engine.DataManager, server *utils.Server) {
cdrStats := engine.NewStats(dm, cfg.CDRStatsSaveInterval)
cdrStats := engine.NewStats(dm, cfg.CdrStatsCfg().CDRStatsSaveInterval)
server.RpcRegister(cdrStats)
server.RpcRegister(&v1.CDRStatsV1{CdrStats: cdrStats}) // Public APIs
internalCdrStatSChan <- cdrStats
@@ -1350,7 +1350,7 @@ func main() {
var loadDb engine.LoadStorage
var cdrDb engine.CdrStorage
var dm *engine.DataManager
if cfg.RalsCfg().RALsEnabled || cfg.CDRStatsEnabled || cfg.PubSubServerEnabled ||
if cfg.RalsCfg().RALsEnabled || cfg.CdrStatsCfg().CDRStatsEnabled || cfg.PubSubServerEnabled ||
cfg.AliasesServerEnabled || cfg.UserServerEnabled || cfg.SchedulerCfg().Enabled ||
cfg.AttributeSCfg().Enabled || cfg.ResourceSCfg().Enabled || cfg.StatSCfg().Enabled ||
cfg.ThresholdSCfg().Enabled || cfg.SupplierSCfg().Enabled { // Some services can run without db, ie: SessionS or CDRC
@@ -1370,7 +1370,7 @@ func main() {
return
}
}
if cfg.RalsCfg().RALsEnabled || cfg.CDRSEnabled {
if cfg.RalsCfg().RALsEnabled || cfg.CdrsCfg().CDRSEnabled {
storDb, err := engine.ConfigureStorStorage(cfg.StorDbCfg().StorDBType,
cfg.StorDbCfg().StorDBHost, cfg.StorDbCfg().StorDBPort,
cfg.StorDbCfg().StorDBName, cfg.StorDbCfg().StorDBUser,
@@ -1450,7 +1450,7 @@ func main() {
}
// Start CDR Server
if cfg.CDRSEnabled {
if cfg.CdrsCfg().CDRSEnabled {
go startCDRS(internalCdrSChan, cdrDb, dm,
internalRaterChan, internalPubSubSChan, internalAttributeSChan,
internalUserSChan, internalAliaseSChan, internalCdrStatSChan,
@@ -1464,7 +1464,7 @@ func main() {
}
// Start CDR Stats server
if cfg.CDRStatsEnabled {
if cfg.CdrStatsCfg().CDRStatsEnabled {
go startCdrStats(internalCdrStatSChan, dm, server)
}

131
config/cdrscfg.go Normal file
View File

@@ -0,0 +1,131 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"github.com/cgrates/cgrates/utils"
)
type CdrsCfg struct {
CDRSEnabled bool // Enable CDR Server service
CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs
CDRSStoreCdrs bool // store cdrs in storDb
CDRSSMCostRetries int
CDRSChargerSConns []*HaPoolConfig
CDRSRaterConns []*HaPoolConfig // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
CDRSPubSubSConns []*HaPoolConfig // address where to reach the pubsub service: <""|internal|x.y.z.y:1234>
CDRSAttributeSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSUserSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSAliaseSConns []*HaPoolConfig // address where to reach the aliases service: <""|internal|x.y.z.y:1234>
CDRSCDRStatSConns []*HaPoolConfig // address where to reach the cdrstats service. Empty to disable cdrstats gathering <""|internal|x.y.z.y:1234>
CDRSThresholdSConns []*HaPoolConfig // address where to reach the thresholds service
CDRSStatSConns []*HaPoolConfig
CDRSOnlineCDRExports []string // list of CDRE templates to use for real-time CDR exports
}
//loadFromJsonCfg loads Cdrs config from JsonCfg
func (cdrscfg *CdrsCfg) loadFromJsonCfg(jsnCdrsCfg *CdrsJsonCfg) (err error) {
if jsnCdrsCfg == nil {
return nil
}
if jsnCdrsCfg.Enabled != nil {
cdrscfg.CDRSEnabled = *jsnCdrsCfg.Enabled
}
if jsnCdrsCfg.Extra_fields != nil {
if cdrscfg.CDRSExtraFields, err = utils.ParseRSRFieldsFromSlice(*jsnCdrsCfg.Extra_fields); err != nil {
return err
}
}
if jsnCdrsCfg.Store_cdrs != nil {
cdrscfg.CDRSStoreCdrs = *jsnCdrsCfg.Store_cdrs
}
if jsnCdrsCfg.Sessions_cost_retries != nil {
cdrscfg.CDRSSMCostRetries = *jsnCdrsCfg.Sessions_cost_retries
}
if jsnCdrsCfg.Chargers_conns != nil {
cdrscfg.CDRSChargerSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Chargers_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Chargers_conns {
cdrscfg.CDRSChargerSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSChargerSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Rals_conns != nil {
cdrscfg.CDRSRaterConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Rals_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Rals_conns {
cdrscfg.CDRSRaterConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSRaterConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Pubsubs_conns != nil {
cdrscfg.CDRSPubSubSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Pubsubs_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Pubsubs_conns {
cdrscfg.CDRSPubSubSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSPubSubSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Attributes_conns != nil {
cdrscfg.CDRSAttributeSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Attributes_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Attributes_conns {
cdrscfg.CDRSAttributeSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSAttributeSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Users_conns != nil {
cdrscfg.CDRSUserSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Users_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Users_conns {
cdrscfg.CDRSUserSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSUserSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Aliases_conns != nil {
cdrscfg.CDRSAliaseSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Aliases_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Aliases_conns {
cdrscfg.CDRSAliaseSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSAliaseSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Cdrstats_conns != nil {
cdrscfg.CDRSCDRStatSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Cdrstats_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Cdrstats_conns {
cdrscfg.CDRSCDRStatSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSCDRStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Thresholds_conns != nil {
cdrscfg.CDRSThresholdSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Thresholds_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Thresholds_conns {
cdrscfg.CDRSThresholdSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSThresholdSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Stats_conns != nil {
cdrscfg.CDRSStatSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Stats_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Stats_conns {
cdrscfg.CDRSStatSConns[idx] = NewDfltHaPoolConfig()
cdrscfg.CDRSStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Online_cdr_exports != nil {
for _, expProfile := range *jsnCdrsCfg.Online_cdr_exports {
cdrscfg.CDRSOnlineCDRExports = append(cdrscfg.CDRSOnlineCDRExports, expProfile)
}
}
return nil
}

82
config/cdrscfg_test.go Normal file
View File

@@ -0,0 +1,82 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"reflect"
"strings"
"testing"
"github.com/cgrates/cgrates/utils"
)
func TestCdrsCfgloadFromJsonCfg(t *testing.T) {
var cdrscfg, expected CdrsCfg
if err := cdrscfg.loadFromJsonCfg(nil); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(cdrscfg, expected) {
t.Errorf("Expected: %+v ,recived: %+v", expected, cdrscfg)
}
if err := cdrscfg.loadFromJsonCfg(new(CdrsJsonCfg)); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(cdrscfg, expected) {
t.Errorf("Expected: %+v ,recived: %+v", expected, cdrscfg)
}
cfgJSONStr := `{
"cdrs": {
"enabled": false, // start the CDR Server service: <true|false>
"extra_fields": [], // extra fields to store in CDRs for non-generic CDRs
"store_cdrs": true, // store cdrs in storDb
"sessions_cost_retries": 5, // number of queries to sessions_costs before recalculating CDR
"chargers_conns": [], // address where to reach the charger service, empty to disable charger functionality: <""|*internal|x.y.z.y:1234>
"rals_conns": [
{"address": "*internal"} // address where to reach the Rater for cost calculation, empty to disable functionality: <""|*internal|x.y.z.y:1234>
],
"pubsubs_conns": [], // address where to reach the pubusb service, empty to disable pubsub functionality: <""|*internal|x.y.z.y:1234>
"attributes_conns": [], // address where to reach the attribute service, empty to disable attributes functionality: <""|*internal|x.y.z.y:1234>
"users_conns": [], // address where to reach the user service, empty to disable user profile functionality: <""|*internal|x.y.z.y:1234>
"aliases_conns": [], // address where to reach the aliases service, empty to disable aliases functionality: <""|*internal|x.y.z.y:1234>
"cdrstats_conns": [], // address where to reach the cdrstats service, empty to disable cdrstats functionality: <""|*internal|x.y.z.y:1234>
"thresholds_conns": [], // address where to reach the thresholds service, empty to disable thresholds functionality: <""|*internal|x.y.z.y:1234>
"stats_conns": [], // address where to reach the stat service, empty to disable stats functionality: <""|*internal|x.y.z.y:1234>
"online_cdr_exports":[], // list of CDRE profiles to use for real-time CDR exports
},
}`
expected = CdrsCfg{
CDRSStoreCdrs: true,
CDRSSMCostRetries: 5,
CDRSChargerSConns: []*HaPoolConfig{},
CDRSRaterConns: []*HaPoolConfig{{Address: utils.MetaInternal}},
CDRSPubSubSConns: []*HaPoolConfig{},
CDRSAttributeSConns: []*HaPoolConfig{},
CDRSUserSConns: []*HaPoolConfig{},
CDRSAliaseSConns: []*HaPoolConfig{},
CDRSCDRStatSConns: []*HaPoolConfig{},
CDRSThresholdSConns: []*HaPoolConfig{},
CDRSStatSConns: []*HaPoolConfig{},
}
if jsnCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(cfgJSONStr)); err != nil {
t.Error(err)
} else if jsnCdrsCfg, err := jsnCfg.CdrsJsonCfg(); err != nil {
t.Error(err)
} else if err = cdrscfg.loadFromJsonCfg(jsnCdrsCfg); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, cdrscfg) {
t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(cdrscfg))
}
}

48
config/cdrstatscfg.go Normal file
View File

@@ -0,0 +1,48 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"time"
"github.com/cgrates/cgrates/utils"
)
// Cdrstats config section
type CdrStatsCfg struct {
CDRStatsEnabled bool // Enable CDR Stats service
CDRStatsSaveInterval time.Duration // Save interval duration
}
//loadFromJsonCfg loads CdrStatsconfig from JsonCfg
func (cdrstsCfg *CdrStatsCfg) loadFromJsonCfg(jsnCdrstatsCfg *CdrStatsJsonCfg) (err error) {
if jsnCdrstatsCfg == nil {
return nil
}
if jsnCdrstatsCfg.Enabled != nil {
cdrstsCfg.CDRStatsEnabled = *jsnCdrstatsCfg.Enabled
}
if jsnCdrstatsCfg.Save_Interval != nil {
if cdrstsCfg.CDRStatsSaveInterval, err = utils.ParseDurationWithNanosecs(*jsnCdrstatsCfg.Save_Interval); err != nil {
return err
}
}
return nil
}

View File

@@ -139,6 +139,9 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
cfg.filterSCfg = new(FilterSCfg)
cfg.ralsCfg = new(RalsCfg)
cfg.ralsCfg.RALsMaxComputedUsage = make(map[string]time.Duration)
cfg.schedulerCfg = new(SchedulerCfg)
cfg.cdrsCfg = new(CdrsCfg)
cfg.cdrStatsCfg = new(CdrStatsCfg)
cfg.analyzerSCfg = new(AnalyzerSCfg)
cfg.sessionSCfg = new(SessionSCfg)
@@ -149,7 +152,6 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
cfg.diameterAgentCfg = new(DiameterAgentCfg)
cfg.radiusAgentCfg = new(RadiusAgentCfg)
cfg.dispatcherSCfg = new(DispatcherSCfg)
cfg.schedulerCfg = new(SchedulerCfg)
cfg.ConfigReloads = make(map[string]chan struct{})
cfg.ConfigReloads[utils.CDRC] = make(chan struct{}, 1)
cfg.ConfigReloads[utils.CDRC] <- struct{}{} // Unlock the channel
@@ -248,156 +250,173 @@ func NewCGRConfigFromFolder(cfgDir string) (*CGRConfig, error) {
// Holds system configuration, defaults are overwritten with values from config file if found
type CGRConfig struct {
MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file
CDRSEnabled bool // Enable CDR Server service
CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs
CDRSStoreCdrs bool // store cdrs in storDb
CDRScdrAccountSummary bool
CDRSSMCostRetries int
CDRSChargerSConns []*HaPoolConfig
CDRSRaterConns []*HaPoolConfig // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
CDRSPubSubSConns []*HaPoolConfig // address where to reach the pubsub service: <""|internal|x.y.z.y:1234>
CDRSAttributeSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSUserSConns []*HaPoolConfig // address where to reach the users service: <""|internal|x.y.z.y:1234>
CDRSAliaseSConns []*HaPoolConfig // address where to reach the aliases service: <""|internal|x.y.z.y:1234>
CDRSCDRStatSConns []*HaPoolConfig // address where to reach the cdrstats service. Empty to disable cdrstats gathering <""|internal|x.y.z.y:1234>
CDRSThresholdSConns []*HaPoolConfig // address where to reach the thresholds service
CDRSStatSConns []*HaPoolConfig
CDRSOnlineCDRExports []string // list of CDRE templates to use for real-time CDR exports
CDRStatsEnabled bool // Enable CDR Stats service
CDRStatsSaveInterval time.Duration // Save interval duration
CdreProfiles map[string]*CdreConfig
CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs}
sessionSCfg *SessionSCfg
fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
PubSubServerEnabled bool // Starts PubSub as server: <true|false>.
AliasesServerEnabled bool // Starts PubSub as server: <true|false>.
UserServerEnabled bool // Starts User as server: <true|false>
UserServerIndexes []string // List of user profile field indexes
attributeSCfg *AttributeSCfg // Attribute service configuration
chargerSCfg *ChargerSCfg
resourceSCfg *ResourceSConfig // Configuration for resource limiter
statsCfg *StatSCfg // Configuration for StatS
thresholdSCfg *ThresholdSCfg // configuration for ThresholdS
supplierSCfg *SupplierSCfg // configuration for SupplierS
loaderCfg []*LoaderSConfig // configuration for Loader
dispatcherSCfg *DispatcherSCfg // configuration for Dispatcher
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
LoaderCgrConfig *LoaderCgrCfg
MigratorCgrConfig *MigratorCgrCfg
schedulerCfg *SchedulerCfg
MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file
CdreProfiles map[string]*CdreConfig
CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs}
sessionSCfg *SessionSCfg
fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
PubSubServerEnabled bool // Starts PubSub as server: <true|false>.
AliasesServerEnabled bool // Starts PubSub as server: <true|false>.
UserServerEnabled bool // Starts User as server: <true|false>
UserServerIndexes []string // List of user profile field indexes
attributeSCfg *AttributeSCfg // Attribute service configuration
chargerSCfg *ChargerSCfg
resourceSCfg *ResourceSConfig // Configuration for resource limiter
statsCfg *StatSCfg // Configuration for StatS
thresholdSCfg *ThresholdSCfg // configuration for ThresholdS
supplierSCfg *SupplierSCfg // configuration for SupplierS
loaderCfg []*LoaderSConfig // configuration for Loader
dispatcherSCfg *DispatcherSCfg // configuration for Dispatcher
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
LoaderCgrConfig *LoaderCgrCfg
MigratorCgrConfig *MigratorCgrCfg
// Cache defaults loaded from json and needing clones
dfltCdreProfile *CdreConfig // Default cdreConfig profile
dfltCdrcProfile *CdrcConfig // Default cdrcConfig profile
generalCfg *GeneralCfg // General config
dataDbCfg *DataDbCfg // Database config
storDbCfg *StorDbCfg // StroreDb config
tlsCfg *TlsCfg // TLS config
cacheCfg CacheCfg // Cache config
listenCfg *ListenCfg // Listen config
httpCfg *HTTPCfg // HTTP config
filterSCfg *FilterSCfg // FilterS config
ralsCfg *RalsCfg // Rals config
generalCfg *GeneralCfg // General config
dataDbCfg *DataDbCfg // Database config
storDbCfg *StorDbCfg // StroreDb config
tlsCfg *TlsCfg // TLS config
cacheCfg CacheCfg // Cache config
listenCfg *ListenCfg // Listen config
httpCfg *HTTPCfg // HTTP config
filterSCfg *FilterSCfg // FilterS config
ralsCfg *RalsCfg // Rals config
schedulerCfg *SchedulerCfg // Scheduler config
cdrsCfg *CdrsCfg // Cdrs config
cdrStatsCfg *CdrStatsCfg // CdrStats config - deprecated
analyzerSCfg *AnalyzerSCfg
}
func (self *CGRConfig) checkConfigSanity() error {
// Rater checks
if self.ralsCfg.RALsEnabled {
for _, connCfg := range self.ralsCfg.RALsCDRStatSConns {
if connCfg.Address == utils.MetaInternal && !self.CDRStatsEnabled {
return errors.New("CDRStats not enabled but requested by RALs component.")
if !self.cdrStatsCfg.CDRStatsEnabled {
for _, connCfg := range self.ralsCfg.RALsCDRStatSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("CDRStats not enabled but requested by RALs component.")
}
}
}
for _, connCfg := range self.ralsCfg.RALsStatSConns {
if connCfg.Address == utils.MetaInternal && !self.statsCfg.Enabled {
return errors.New("StatS not enabled but requested by RALs component.")
if !self.statsCfg.Enabled {
for _, connCfg := range self.ralsCfg.RALsStatSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("StatS not enabled but requested by RALs component.")
}
}
}
for _, connCfg := range self.ralsCfg.RALsPubSubSConns {
if connCfg.Address == utils.MetaInternal && !self.PubSubServerEnabled {
return errors.New("PubSub server not enabled but requested by RALs component.")
if !self.PubSubServerEnabled {
for _, connCfg := range self.ralsCfg.RALsPubSubSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("PubSub server not enabled but requested by RALs component.")
}
}
}
for _, connCfg := range self.ralsCfg.RALsAliasSConns {
if connCfg.Address == utils.MetaInternal && !self.AliasesServerEnabled {
return errors.New("Alias server not enabled but requested by RALs component.")
if !self.AliasesServerEnabled {
for _, connCfg := range self.ralsCfg.RALsAliasSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("Alias server not enabled but requested by RALs component.")
}
}
}
for _, connCfg := range self.ralsCfg.RALsUserSConns {
if connCfg.Address == utils.MetaInternal && !self.UserServerEnabled {
return errors.New("User service not enabled but requested by RALs component.")
if !self.UserServerEnabled {
for _, connCfg := range self.ralsCfg.RALsUserSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("User service not enabled but requested by RALs component.")
}
}
}
for _, connCfg := range self.ralsCfg.RALsThresholdSConns {
if connCfg.Address == utils.MetaInternal && !self.thresholdSCfg.Enabled {
return errors.New("ThresholdS not enabled but requested by RALs component.")
if !self.thresholdSCfg.Enabled {
for _, connCfg := range self.ralsCfg.RALsThresholdSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("ThresholdS not enabled but requested by RALs component.")
}
}
}
}
// CDRServer checks
if self.CDRSEnabled {
for _, conn := range self.CDRSChargerSConns {
if conn.Address == utils.MetaInternal && !self.chargerSCfg.Enabled {
return errors.New("ChargerS not enabled but requested by CDRS component.")
if self.cdrsCfg.CDRSEnabled {
if !self.chargerSCfg.Enabled {
for _, conn := range self.cdrsCfg.CDRSChargerSConns {
if conn.Address == utils.MetaInternal {
return errors.New("ChargerS not enabled but requested by CDRS component.")
}
}
}
for _, cdrsRaterConn := range self.CDRSRaterConns {
if cdrsRaterConn.Address == utils.MetaInternal && !self.ralsCfg.RALsEnabled {
return errors.New("RALs not enabled but requested by CDRS component.")
if !self.ralsCfg.RALsEnabled {
for _, cdrsRaterConn := range self.cdrsCfg.CDRSRaterConns {
if cdrsRaterConn.Address == utils.MetaInternal {
return errors.New("RALs not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSPubSubSConns {
if connCfg.Address == utils.MetaInternal && !self.PubSubServerEnabled {
return errors.New("PubSubS not enabled but requested by CDRS component.")
if !self.PubSubServerEnabled {
for _, connCfg := range self.cdrsCfg.CDRSPubSubSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("PubSubS not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSAttributeSConns {
if connCfg.Address == utils.MetaInternal && !self.attributeSCfg.Enabled {
return errors.New("AttributeS not enabled but requested by CDRS component.")
if !self.attributeSCfg.Enabled {
for _, connCfg := range self.cdrsCfg.CDRSAttributeSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("AttributeS not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSUserSConns {
if connCfg.Address == utils.MetaInternal && !self.UserServerEnabled {
return errors.New("UserS not enabled but requested by CDRS component.")
if !self.UserServerEnabled {
for _, connCfg := range self.cdrsCfg.CDRSUserSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("UserS not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSAliaseSConns {
if connCfg.Address == utils.MetaInternal && !self.AliasesServerEnabled {
return errors.New("AliaseS not enabled but requested by CDRS component.")
if !self.AliasesServerEnabled {
for _, connCfg := range self.cdrsCfg.CDRSAliaseSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("AliaseS not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSCDRStatSConns {
if connCfg.Address == utils.MetaInternal && !self.CDRStatsEnabled {
return errors.New("CDRStatS not enabled but requested by CDRS component.")
if !self.cdrStatsCfg.CDRStatsEnabled {
for _, connCfg := range self.cdrsCfg.CDRSCDRStatSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("CDRStatS not enabled but requested by CDRS component.")
}
}
}
for _, connCfg := range self.CDRSStatSConns {
if connCfg.Address == utils.MetaInternal && !self.statsCfg.Enabled {
return errors.New("StatS not enabled but requested by CDRS component.")
if !self.statsCfg.Enabled {
for _, connCfg := range self.cdrsCfg.CDRSStatSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("StatS not enabled but requested by CDRS component.")
}
}
}
for _, cdrePrfl := range self.CDRSOnlineCDRExports {
for _, cdrePrfl := range self.cdrsCfg.CDRSOnlineCDRExports {
if _, hasIt := self.CdreProfiles[cdrePrfl]; !hasIt {
return fmt.Errorf("<CDRS> Cannot find CDR export template with ID: <%s>", cdrePrfl)
}
}
for _, connCfg := range self.CDRSThresholdSConns {
if connCfg.Address == utils.MetaInternal && !self.thresholdSCfg.Enabled {
return errors.New("ThresholdS not enabled but requested by CDRS component.")
if !self.thresholdSCfg.Enabled {
for _, connCfg := range self.cdrsCfg.CDRSThresholdSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("ThresholdS not enabled but requested by CDRS component.")
}
}
}
}
@@ -410,9 +429,11 @@ func (self *CGRConfig) checkConfigSanity() error {
if len(cdrcInst.CdrsConns) == 0 {
return fmt.Errorf("<CDRC> Instance: %s, CdrC enabled but no CDRS defined!", cdrcInst.ID)
}
for _, conn := range cdrcInst.CdrsConns {
if conn.Address == utils.MetaInternal && !self.CDRSEnabled {
return errors.New("CDRS not enabled but referenced from CDRC")
if !self.cdrsCfg.CDRSEnabled {
for _, conn := range cdrcInst.CdrsConns {
if conn.Address == utils.MetaInternal {
return errors.New("CDRS not enabled but referenced from CDRC")
}
}
}
if len(cdrcInst.ContentFields) == 0 {
@@ -460,47 +481,63 @@ func (self *CGRConfig) checkConfigSanity() error {
if len(self.sessionSCfg.RALsConns) == 0 {
return errors.New("<SessionS> RALs definition is mandatory!")
}
for _, conn := range self.sessionSCfg.ChargerSConns {
if conn.Address == utils.MetaInternal && !self.chargerSCfg.Enabled {
return errors.New("<SessionS> ChargerS not enabled but requested")
if !self.chargerSCfg.Enabled {
for _, conn := range self.sessionSCfg.ChargerSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> ChargerS not enabled but requested")
}
}
}
for _, smgRALsConn := range self.sessionSCfg.RALsConns {
if smgRALsConn.Address == utils.MetaInternal && !self.ralsCfg.RALsEnabled {
return errors.New("<SessionS> RALs not enabled but requested by SMGeneric component.")
if !self.ralsCfg.RALsEnabled {
for _, smgRALsConn := range self.sessionSCfg.RALsConns {
if smgRALsConn.Address == utils.MetaInternal {
return errors.New("<SessionS> RALs not enabled but requested by SMGeneric component.")
}
}
}
for _, conn := range self.sessionSCfg.ResSConns {
if conn.Address == utils.MetaInternal && !self.resourceSCfg.Enabled {
return errors.New("<SessionS> ResourceS not enabled but requested by SMGeneric component.")
if !self.resourceSCfg.Enabled {
for _, conn := range self.sessionSCfg.ResSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> ResourceS not enabled but requested by SMGeneric component.")
}
}
}
for _, conn := range self.sessionSCfg.ThreshSConns {
if conn.Address == utils.MetaInternal && !self.thresholdSCfg.Enabled {
return errors.New("<SessionS> ThresholdS not enabled but requested by SMGeneric component.")
if !self.thresholdSCfg.Enabled {
for _, conn := range self.sessionSCfg.ThreshSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> ThresholdS not enabled but requested by SMGeneric component.")
}
}
}
for _, conn := range self.sessionSCfg.StatSConns {
if conn.Address == utils.MetaInternal && !self.statsCfg.Enabled {
return errors.New("<SessionS> StatS not enabled but requested by SMGeneric component.")
if !self.statsCfg.Enabled {
for _, conn := range self.sessionSCfg.StatSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> StatS not enabled but requested by SMGeneric component.")
}
}
}
for _, conn := range self.sessionSCfg.SupplSConns {
if conn.Address == utils.MetaInternal && !self.supplierSCfg.Enabled {
return errors.New("<SessionS> SupplierS not enabled but requested by SMGeneric component.")
if !self.supplierSCfg.Enabled {
for _, conn := range self.sessionSCfg.SupplSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> SupplierS not enabled but requested by SMGeneric component.")
}
}
}
for _, conn := range self.sessionSCfg.AttrSConns {
if conn.Address == utils.MetaInternal && !self.attributeSCfg.Enabled {
return errors.New("<SessionS> AttributeS not enabled but requested by SMGeneric component.")
if !self.attributeSCfg.Enabled {
for _, conn := range self.sessionSCfg.AttrSConns {
if conn.Address == utils.MetaInternal {
return errors.New("<SessionS> AttributeS not enabled but requested by SMGeneric component.")
}
}
}
if len(self.sessionSCfg.CDRsConns) == 0 {
return errors.New("<SessionS> CDRs definition is mandatory!")
}
for _, smgCDRSConn := range self.sessionSCfg.CDRsConns {
if smgCDRSConn.Address == utils.MetaInternal && !self.CDRSEnabled {
return errors.New("<SessionS> CDRS not enabled but referenced by SMGeneric component")
if !self.cdrsCfg.CDRSEnabled {
for _, smgCDRSConn := range self.sessionSCfg.CDRsConns {
if smgCDRSConn.Address == utils.MetaInternal {
return errors.New("<SessionS> CDRS not enabled but referenced by SMGeneric component")
}
}
}
}
@@ -533,18 +570,21 @@ func (self *CGRConfig) checkConfigSanity() error {
if len(self.SmOsipsConfig.RALsConns) == 0 {
return errors.New("<SMOpenSIPS> Rater definition is mandatory!")
}
for _, smOsipsRaterConn := range self.SmOsipsConfig.RALsConns {
if smOsipsRaterConn.Address == utils.MetaInternal && !self.ralsCfg.RALsEnabled {
return errors.New("<SMOpenSIPS> RALs not enabled.")
if !self.ralsCfg.RALsEnabled {
for _, smOsipsRaterConn := range self.SmOsipsConfig.RALsConns {
if smOsipsRaterConn.Address == utils.MetaInternal {
return errors.New("<SMOpenSIPS> RALs not enabled.")
}
}
}
if len(self.SmOsipsConfig.CDRsConns) == 0 {
return errors.New("<SMOpenSIPS> CDRs definition is mandatory!")
}
for _, smOsipsCDRSConn := range self.SmOsipsConfig.CDRsConns {
if smOsipsCDRSConn.Address == utils.MetaInternal && !self.CDRSEnabled {
return errors.New("<SMOpenSIPS> CDRS not enabled.")
if !self.cdrsCfg.CDRSEnabled {
for _, smOsipsCDRSConn := range self.SmOsipsConfig.CDRsConns {
if smOsipsCDRSConn.Address == utils.MetaInternal {
return errors.New("<SMOpenSIPS> CDRS not enabled.")
}
}
}
}
@@ -564,36 +604,37 @@ func (self *CGRConfig) checkConfigSanity() error {
}
}
// DAgent checks
if self.diameterAgentCfg.Enabled {
if self.diameterAgentCfg.Enabled && !self.sessionSCfg.Enabled {
for _, daSMGConn := range self.diameterAgentCfg.SessionSConns {
if daSMGConn.Address == utils.MetaInternal && !self.sessionSCfg.Enabled {
if daSMGConn.Address == utils.MetaInternal {
return fmt.Errorf("%s not enabled but referenced by %s component",
utils.SessionS, utils.DiameterAgent)
}
}
}
if self.radiusAgentCfg.Enabled {
if self.radiusAgentCfg.Enabled && !self.sessionSCfg.Enabled {
for _, raSMGConn := range self.radiusAgentCfg.SessionSConns {
if raSMGConn.Address == utils.MetaInternal && !self.sessionSCfg.Enabled {
if raSMGConn.Address == utils.MetaInternal {
return errors.New("SMGeneric not enabled but referenced by RadiusAgent component")
}
}
}
for _, httpAgentCfg := range self.httpAgentCfg {
// httpAgent checks
for _, sSConn := range httpAgentCfg.SessionSConns {
if sSConn.Address == utils.MetaInternal &&
!self.sessionSCfg.Enabled {
return errors.New("SessionS not enabled but referenced by HttpAgent component")
if self.sessionSCfg.Enabled {
for _, httpAgentCfg := range self.httpAgentCfg {
// httpAgent checks
for _, sSConn := range httpAgentCfg.SessionSConns {
if sSConn.Address == utils.MetaInternal {
return errors.New("SessionS not enabled but referenced by HttpAgent component")
}
}
}
}
if self.attributeSCfg != nil && self.attributeSCfg.Enabled {
if self.attributeSCfg.Enabled {
if self.attributeSCfg.ProcessRuns < 1 {
return fmt.Errorf("<%s> process_runs needs to be bigger than 0", utils.AttributeS)
}
}
if self.chargerSCfg != nil && self.chargerSCfg.Enabled {
if self.chargerSCfg.Enabled {
for _, connCfg := range self.chargerSCfg.AttributeSConns {
if connCfg.Address == utils.MetaInternal &&
(self.attributeSCfg == nil || !self.attributeSCfg.Enabled) {
@@ -602,23 +643,23 @@ func (self *CGRConfig) checkConfigSanity() error {
}
}
// ResourceLimiter checks
if self.resourceSCfg != nil && self.resourceSCfg.Enabled {
if self.resourceSCfg.Enabled && !self.thresholdSCfg.Enabled {
for _, connCfg := range self.resourceSCfg.ThresholdSConns {
if connCfg.Address == utils.MetaInternal && !self.thresholdSCfg.Enabled {
if connCfg.Address == utils.MetaInternal {
return errors.New("ThresholdS not enabled but requested by ResourceS component.")
}
}
}
// StatS checks
if self.statsCfg != nil && self.statsCfg.Enabled {
if self.statsCfg.Enabled && !self.thresholdSCfg.Enabled {
for _, connCfg := range self.statsCfg.ThresholdSConns {
if connCfg.Address == utils.MetaInternal && !self.thresholdSCfg.Enabled {
if connCfg.Address == utils.MetaInternal {
return errors.New("ThresholdS not enabled but requested by StatS component.")
}
}
}
// SupplierS checks
if self.supplierSCfg != nil && self.supplierSCfg.Enabled {
if self.supplierSCfg.Enabled {
for _, connCfg := range self.supplierSCfg.RALsConns {
if connCfg.Address != utils.MetaInternal {
return errors.New("Only <*internal> RALs connectivity allowed in SupplierS for now")
@@ -627,24 +668,30 @@ func (self *CGRConfig) checkConfigSanity() error {
return errors.New("RALs not enabled but requested by SupplierS component.")
}
}
for _, connCfg := range self.supplierSCfg.ResourceSConns {
if connCfg.Address == utils.MetaInternal && !self.resourceSCfg.Enabled {
return errors.New("ResourceS not enabled but requested by SupplierS component.")
if !self.resourceSCfg.Enabled {
for _, connCfg := range self.supplierSCfg.ResourceSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("ResourceS not enabled but requested by SupplierS component.")
}
}
}
for _, connCfg := range self.supplierSCfg.StatSConns {
if connCfg.Address == utils.MetaInternal && !self.resourceSCfg.Enabled {
return errors.New("StatS not enabled but requested by SupplierS component.")
if !self.resourceSCfg.Enabled {
for _, connCfg := range self.supplierSCfg.StatSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("StatS not enabled but requested by SupplierS component.")
}
}
}
for _, connCfg := range self.supplierSCfg.AttributeSConns {
if connCfg.Address == utils.MetaInternal && !self.attributeSCfg.Enabled {
return errors.New("AttributeS not enabled but requested by SupplierS component.")
if !self.attributeSCfg.Enabled {
for _, connCfg := range self.supplierSCfg.AttributeSConns {
if connCfg.Address == utils.MetaInternal {
return errors.New("AttributeS not enabled but requested by SupplierS component.")
}
}
}
}
// DispaterS checks
if self.dispatcherSCfg != nil && self.dispatcherSCfg.Enabled {
if self.dispatcherSCfg.Enabled {
if !utils.IsSliceMember([]string{utils.MetaFirst, utils.MetaRandom, utils.MetaNext,
utils.MetaBroadcast}, self.dispatcherSCfg.DispatchingStrategy) {
return fmt.Errorf("<%s> unsupported dispatching strategy %s",
@@ -652,9 +699,9 @@ func (self *CGRConfig) checkConfigSanity() error {
}
}
// Scheduler check connection with CDR Server
if len(self.schedulerCfg.CDRsConns) != 0 {
if !self.cdrsCfg.CDRSEnabled {
for _, connCfg := range self.schedulerCfg.CDRsConns {
if connCfg.Address == utils.MetaInternal && !self.CDRSEnabled {
if connCfg.Address == utils.MetaInternal {
return errors.New("CDR Server not enabled but requested by Scheduler")
}
}
@@ -669,57 +716,89 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
if err != nil {
return err
}
if err := self.generalCfg.loadFromJsonCfg(jsnGeneralCfg); err != nil {
return err
}
// Load sections out of JSON config, stop on error
jsnCacheCfg, err := jsnCfg.CacheJsonCfg()
if err != nil {
return err
}
if err := self.cacheCfg.loadFromJsonCfg(jsnCacheCfg); err != nil {
return err
}
jsnListenCfg, err := jsnCfg.ListenJsonCfg()
if err != nil {
return err
}
if err := self.listenCfg.loadFromJsonCfg(jsnListenCfg); err != nil {
return err
}
jsnHttpCfg, err := jsnCfg.HttpJsonCfg()
if err != nil {
return err
}
if err := self.httpCfg.loadFromJsonCfg(jsnHttpCfg); err != nil {
return err
}
jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN)
if err != nil {
return err
}
if err := self.dataDbCfg.loadFromJsonCfg(jsnDataDbCfg); err != nil {
return err
}
jsnStorDbCfg, err := jsnCfg.DbJsonCfg(STORDB_JSN)
if err != nil {
return err
}
if err := self.storDbCfg.loadFromJsonCfg(jsnStorDbCfg); err != nil {
return err
}
jsnFilterSCfg, err := jsnCfg.FilterSJsonCfg()
if err != nil {
return err
}
if err = self.filterSCfg.loadFromJsonCfg(jsnFilterSCfg); err != nil {
return
}
jsnRALsCfg, err := jsnCfg.RalsJsonCfg()
if err != nil {
return err
}
if err = self.ralsCfg.loadFromJsonCfg(jsnRALsCfg); err != nil {
return
}
jsnSchedCfg, err := jsnCfg.SchedulerJsonCfg()
if err != nil {
return err
}
if err := self.schedulerCfg.loadFromJsonCfg(jsnSchedCfg); err != nil {
return err
}
jsnCdrsCfg, err := jsnCfg.CdrsJsonCfg()
if err != nil {
return err
}
if err := self.cdrsCfg.loadFromJsonCfg(jsnCdrsCfg); err != nil {
return err
}
jsnCdrstatsCfg, err := jsnCfg.CdrStatsJsonCfg()
if err != nil {
return err
}
if err := self.cdrStatsCfg.loadFromJsonCfg(jsnCdrstatsCfg); err != nil {
return err
}
jsnCdreCfg, err := jsnCfg.CdreJsonCfgs()
if err != nil {
@@ -845,154 +924,17 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
if err != nil {
return nil
}
jsnAnalyzerCgrCfg, err := jsnCfg.AnalyzerCfgJson()
if err != nil {
return nil
}
if err := self.dataDbCfg.loadFromJsonCfg(jsnDataDbCfg); err != nil {
return err
}
if err := self.storDbCfg.loadFromJsonCfg(jsnStorDbCfg); err != nil {
return err
}
if err := self.generalCfg.loadFromJsonCfg(jsnGeneralCfg); err != nil {
return err
}
if err := self.tlsCfg.loadFromJsonCfg(jsnTlsCgrCfg); err != nil {
return err
}
if err := self.cacheCfg.loadFromJsonCfg(jsnCacheCfg); err != nil {
return err
}
if err := self.analyzerSCfg.loadFromJsonCfg(jsnAnalyzerCgrCfg); err != nil {
return err
}
if err := self.listenCfg.loadFromJsonCfg(jsnListenCfg); err != nil {
return err
}
if err := self.httpCfg.loadFromJsonCfg(jsnHttpCfg); err != nil {
return err
}
if err = self.filterSCfg.loadFromJsonCfg(jsnFilterSCfg); err != nil {
return
}
if err = self.ralsCfg.loadFromJsonCfg(jsnRALsCfg); err != nil {
return
}
if jsnSchedCfg != nil {
if err := self.schedulerCfg.loadFromJsonCfg(jsnSchedCfg); err != nil {
return err
}
}
if jsnCdrsCfg != nil {
if jsnCdrsCfg.Enabled != nil {
self.CDRSEnabled = *jsnCdrsCfg.Enabled
}
if jsnCdrsCfg.Extra_fields != nil {
if self.CDRSExtraFields, err = utils.ParseRSRFieldsFromSlice(*jsnCdrsCfg.Extra_fields); err != nil {
return err
}
}
if jsnCdrsCfg.Store_cdrs != nil {
self.CDRSStoreCdrs = *jsnCdrsCfg.Store_cdrs
}
if jsnCdrsCfg.Sessions_cost_retries != nil {
self.CDRSSMCostRetries = *jsnCdrsCfg.Sessions_cost_retries
}
if jsnCdrsCfg.Chargers_conns != nil {
self.CDRSChargerSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Chargers_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Chargers_conns {
self.CDRSChargerSConns[idx] = NewDfltHaPoolConfig()
self.CDRSChargerSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Rals_conns != nil {
self.CDRSRaterConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Rals_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Rals_conns {
self.CDRSRaterConns[idx] = NewDfltHaPoolConfig()
self.CDRSRaterConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Pubsubs_conns != nil {
self.CDRSPubSubSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Pubsubs_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Pubsubs_conns {
self.CDRSPubSubSConns[idx] = NewDfltHaPoolConfig()
self.CDRSPubSubSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Attributes_conns != nil {
self.CDRSAttributeSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Attributes_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Attributes_conns {
self.CDRSAttributeSConns[idx] = NewDfltHaPoolConfig()
self.CDRSAttributeSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Users_conns != nil {
self.CDRSUserSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Users_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Users_conns {
self.CDRSUserSConns[idx] = NewDfltHaPoolConfig()
self.CDRSUserSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Aliases_conns != nil {
self.CDRSAliaseSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Aliases_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Aliases_conns {
self.CDRSAliaseSConns[idx] = NewDfltHaPoolConfig()
self.CDRSAliaseSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Cdrstats_conns != nil {
self.CDRSCDRStatSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Cdrstats_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Cdrstats_conns {
self.CDRSCDRStatSConns[idx] = NewDfltHaPoolConfig()
self.CDRSCDRStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Thresholds_conns != nil {
self.CDRSThresholdSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Thresholds_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Thresholds_conns {
self.CDRSThresholdSConns[idx] = NewDfltHaPoolConfig()
self.CDRSThresholdSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Stats_conns != nil {
self.CDRSStatSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Stats_conns))
for idx, jsnHaCfg := range *jsnCdrsCfg.Stats_conns {
self.CDRSStatSConns[idx] = NewDfltHaPoolConfig()
self.CDRSStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCdrsCfg.Online_cdr_exports != nil {
for _, expProfile := range *jsnCdrsCfg.Online_cdr_exports {
self.CDRSOnlineCDRExports = append(self.CDRSOnlineCDRExports, expProfile)
}
}
}
if jsnCdrstatsCfg != nil {
if jsnCdrstatsCfg.Enabled != nil {
self.CDRStatsEnabled = *jsnCdrstatsCfg.Enabled
if jsnCdrstatsCfg.Save_Interval != nil {
if self.CDRStatsSaveInterval, err = utils.ParseDurationWithNanosecs(*jsnCdrstatsCfg.Save_Interval); err != nil {
return err
}
}
}
}
if jsnCdreCfg != nil {
if self.CdreProfiles == nil {
self.CdreProfiles = make(map[string]*CdreConfig)
@@ -1357,6 +1299,14 @@ func (cfg *CGRConfig) RalsCfg() *RalsCfg {
return cfg.ralsCfg
}
func (cfg *CGRConfig) CdrsCfg() *CdrsCfg {
return cfg.cdrsCfg
}
func (cfg *CGRConfig) CdrStatsCfg() *CdrStatsCfg {
return cfg.cdrStatsCfg
}
func (cfg *CGRConfig) AnalyzerSCfg() *AnalyzerSCfg {
return cfg.analyzerSCfg
}

View File

@@ -508,50 +508,47 @@ func TestCgrCfgJSONDefaultsScheduler(t *testing.T) {
func TestCgrCfgJSONDefaultsCDRS(t *testing.T) {
eHaPoolCfg := []*HaPoolConfig{}
var eCdrExtr []*utils.RSRField
if cgrCfg.CDRSEnabled != false {
t.Error(cgrCfg.CDRSEnabled)
if cgrCfg.CdrsCfg().CDRSEnabled != false {
t.Errorf("Expecting: false , received: %+v", cgrCfg.CdrsCfg().CDRSEnabled)
}
if !reflect.DeepEqual(eCdrExtr, cgrCfg.CDRSExtraFields) {
t.Errorf(" expecting: %+v, received: %+v", eCdrExtr, cgrCfg.CDRSExtraFields)
if !reflect.DeepEqual(eCdrExtr, cgrCfg.CdrsCfg().CDRSExtraFields) {
t.Errorf("Expecting: %+v , received: %+v", eCdrExtr, cgrCfg.CdrsCfg().CDRSExtraFields)
}
if cgrCfg.CDRSStoreCdrs != true {
t.Error(cgrCfg.CDRSStoreCdrs)
if cgrCfg.CdrsCfg().CDRSStoreCdrs != true {
t.Errorf("Expecting: true , received: %+v", cgrCfg.CdrsCfg().CDRSStoreCdrs)
}
if cgrCfg.CDRScdrAccountSummary != false {
t.Error(cgrCfg.CDRScdrAccountSummary)
if cgrCfg.CdrsCfg().CDRSSMCostRetries != 5 {
t.Errorf("Expecting: 5 , received: %+v", cgrCfg.CdrsCfg().CDRSSMCostRetries)
}
if cgrCfg.CDRSSMCostRetries != 5 {
t.Error(cgrCfg.CDRSSMCostRetries)
if expected := []*HaPoolConfig{{Address: utils.MetaInternal}}; !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSRaterConns, expected) {
t.Errorf("Expecting: %+v , received: %+v", expected, cgrCfg.CdrsCfg().CDRSRaterConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSRaterConns, []*HaPoolConfig{{Address: "*internal"}}) {
t.Error(cgrCfg.CDRSRaterConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSChargerSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSChargerSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSChargerSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSChargerSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSPubSubSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSPubSubSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSPubSubSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSPubSubSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSAttributeSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSAttributeSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSAttributeSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSAttributeSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSUserSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSUserSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSUserSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSUserSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSAliaseSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSAliaseSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSAliaseSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSAliaseSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSCDRStatSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSCDRStatSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSCDRStatSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSCDRStatSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSThresholdSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSThresholdSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSThresholdSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSThresholdSConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSStatSConns, eHaPoolCfg) {
t.Errorf("Expecting: %+v , received: %+v", eHaPoolCfg, cgrCfg.CdrsCfg().CDRSStatSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSStatSConns, eHaPoolCfg) {
t.Error(cgrCfg.CDRSStatSConns)
}
if cgrCfg.CDRSOnlineCDRExports != nil {
t.Error(cgrCfg.CDRSOnlineCDRExports)
if cgrCfg.CdrsCfg().CDRSOnlineCDRExports != nil {
t.Errorf("Expecting: nil , received: %+v", cgrCfg.CdrsCfg().CDRSOnlineCDRExports)
}
}
@@ -573,25 +570,24 @@ func TestCgrCfgJSONLoadCDRS(t *testing.T) {
if err != nil {
t.Error(err)
}
if !cgrCfg.CDRSEnabled {
t.Error(cgrCfg.CDRSEnabled)
if !cgrCfg.CdrsCfg().CDRSEnabled {
t.Errorf("Expecting: true , received: %+v", cgrCfg.CdrsCfg().CDRSEnabled)
}
if !reflect.DeepEqual(cgrCfg.CDRSChargerSConns,
[]*HaPoolConfig{{Address: utils.MetaInternal}}) {
t.Error(cgrCfg.CDRSChargerSConns)
expected := []*HaPoolConfig{{Address: utils.MetaInternal}}
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSChargerSConns, expected) {
t.Errorf("Expecting: %+v , received: %+v", expected, cgrCfg.CdrsCfg().CDRSChargerSConns)
}
if !reflect.DeepEqual(cgrCfg.CDRSRaterConns,
[]*HaPoolConfig{{Address: utils.MetaInternal}}) {
t.Error(cgrCfg.CDRSRaterConns)
if !reflect.DeepEqual(cgrCfg.CdrsCfg().CDRSRaterConns, expected) {
t.Errorf("Expecting: %+v , received: %+v", expected, cgrCfg.CdrsCfg().CDRSRaterConns)
}
}
func TestCgrCfgJSONDefaultsCDRStats(t *testing.T) {
if cgrCfg.CDRStatsEnabled != false {
t.Error(cgrCfg.CDRStatsEnabled)
if cgrCfg.CdrStatsCfg().CDRStatsEnabled != false {
t.Error(cgrCfg.CdrStatsCfg().CDRStatsEnabled)
}
if cgrCfg.CDRStatsSaveInterval != 1*time.Minute {
t.Error(cgrCfg.CDRStatsSaveInterval)
if cgrCfg.CdrStatsCfg().CDRStatsSaveInterval != 1*time.Minute {
t.Error(cgrCfg.CdrStatsCfg().CDRStatsSaveInterval)
}
}

View File

@@ -23,19 +23,19 @@ type SchedulerCfg struct {
CDRsConns []*HaPoolConfig
}
func (self *SchedulerCfg) loadFromJsonCfg(jsnCfg *SchedulerJsonCfg) error {
func (schdcfg *SchedulerCfg) loadFromJsonCfg(jsnCfg *SchedulerJsonCfg) error {
if jsnCfg == nil {
return nil
}
if jsnCfg.Enabled != nil {
self.Enabled = *jsnCfg.Enabled
schdcfg.Enabled = *jsnCfg.Enabled
}
if jsnCfg.Cdrs_conns != nil {
self.CDRsConns = make([]*HaPoolConfig, len(*jsnCfg.Cdrs_conns))
schdcfg.CDRsConns = make([]*HaPoolConfig, len(*jsnCfg.Cdrs_conns))
for idx, jsnHaCfg := range *jsnCfg.Cdrs_conns {
self.CDRsConns[idx] = NewDfltHaPoolConfig()
self.CDRsConns[idx].loadFromJsonCfg(jsnHaCfg)
schdcfg.CDRsConns[idx] = NewDfltHaPoolConfig()
schdcfg.CDRsConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
return nil

View File

@@ -0,0 +1,57 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package config
import (
"reflect"
"strings"
"testing"
)
func TestSchedulerCfgloadFromJsonCfg(t *testing.T) {
var schdcfg, expected SchedulerCfg
if err := schdcfg.loadFromJsonCfg(nil); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(schdcfg, expected) {
t.Errorf("Expected: %+v ,recived: %+v", expected, schdcfg)
}
if err := schdcfg.loadFromJsonCfg(new(SchedulerJsonCfg)); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(schdcfg, expected) {
t.Errorf("Expected: %+v ,recived: %+v", expected, schdcfg)
}
cfgJSONStr := `{
"scheduler": {
"enabled": true, // start Scheduler service: <true|false>
"cdrs_conns": [], // address where to reach CDR Server, empty to disable CDR capturing <*internal|x.y.z.y:1234>
},
}`
expected = SchedulerCfg{
Enabled: true,
CDRsConns: []*HaPoolConfig{},
}
if jsnCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(cfgJSONStr)); err != nil {
t.Error(err)
} else if jsnSchCfg, err := jsnCfg.SchedulerJsonCfg(); err != nil {
t.Error(err)
} else if err = schdcfg.loadFromJsonCfg(jsnSchCfg); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, schdcfg) {
t.Errorf("Expected: %+v , recived: %+v", expected, schdcfg)
}
}

View File

@@ -194,7 +194,7 @@ func (self *CdrServer) processCdr(cdr *CDR) (err error) {
if cdr.RunID == utils.MetaRaw {
cdr.Cost = -1.0
}
if self.cgrCfg.CDRSStoreCdrs { // Store RawCDRs, this we do sync so we can reply with the status
if self.cgrCfg.CdrsCfg().CDRSStoreCdrs { // Store RawCDRs, this we do sync so we can reply with the status
if err := self.cdrDb.SetCDR(cdr, false); err != nil {
utils.Logger.Err(fmt.Sprintf("<CDRS> Storing primary CDR %+v, got error: %s", cdr, err.Error()))
return err // Error is propagated back and we don't continue processing the CDR if we cannot store it
@@ -214,12 +214,12 @@ func (self *CdrServer) processCdr(cdr *CDR) (err error) {
go self.stats.Call(utils.StatSv1ProcessEvent, &StatsArgsProcessEvent{CGREvent: *cdr.AsCGREvent()}, &reply)
}
if len(self.cgrCfg.CDRSOnlineCDRExports) != 0 { // Replicate raw CDR
if len(self.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0 { // Replicate raw CDR
self.replicateCDRs([]*CDR{cdr})
}
if self.rals != nil && !cdr.PreRated { // CDRs not rated will be processed by Rating
go self.deriveRateStoreStatsReplicate(cdr, self.cgrCfg.CDRSStoreCdrs,
true, len(self.cgrCfg.CDRSOnlineCDRExports) != 0)
go self.deriveRateStoreStatsReplicate(cdr, self.cgrCfg.CdrsCfg().CDRSStoreCdrs,
true, len(self.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0)
}
return nil
}
@@ -414,7 +414,7 @@ func (self *CdrServer) rateCDR(cdr *CDR) ([]*CDR, error) {
if _, hasIT := cdr.ExtraFields[utils.OriginIDPrefix]; hasIT {
cgrID = "" // for queries involving originIDPrefix we ignore CGRID
}
for i := 0; i < self.cgrCfg.CDRSSMCostRetries; i++ {
for i := 0; i < self.cgrCfg.CdrsCfg().CDRSSMCostRetries; i++ {
smCosts, err = self.cdrDb.GetSMCosts(cgrID, cdr.RunID, cdr.OriginHost,
cdr.ExtraFields[utils.OriginIDPrefix])
if err == nil && len(smCosts) != 0 {
@@ -490,7 +490,7 @@ func (self *CdrServer) getCostFromRater(cdr *CDR) (*CallCost, error) {
}
func (self *CdrServer) replicateCDRs(cdrs []*CDR) (err error) {
for _, exportID := range self.cgrCfg.CDRSOnlineCDRExports {
for _, exportID := range self.cgrCfg.CdrsCfg().CDRSOnlineCDRExports {
expTpl := self.cgrCfg.CdreProfiles[exportID] // not checking for existence of profile since this should be done in a higher layer
var cdre *CDRExporter
if cdre, err = NewCDRExporter(cdrs, expTpl, expTpl.ExportFormat,
@@ -518,7 +518,8 @@ func (self *CdrServer) RateCDRs(cdrFltr *utils.CDRsFilter, sendToStats bool) err
return err
}
for _, cdr := range cdrs {
if err := self.deriveRateStoreStatsReplicate(cdr, self.cgrCfg.CDRSStoreCdrs, sendToStats, len(self.cgrCfg.CDRSOnlineCDRExports) != 0); err != nil {
if err := self.deriveRateStoreStatsReplicate(cdr, self.cgrCfg.CdrsCfg().CDRSStoreCdrs,
sendToStats, len(self.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0); err != nil {
utils.Logger.Err(fmt.Sprintf("<CDRS> Processing CDR %+v, got error: %s", cdr, err.Error()))
}
}
@@ -624,7 +625,7 @@ func (self *CdrServer) V1RateCDRs(attrs utils.AttrRateCDRs, reply *string) error
if err != nil {
return err
}
storeCDRs := self.cgrCfg.CDRSStoreCdrs
storeCDRs := self.cgrCfg.CdrsCfg().CDRSStoreCdrs
if attrs.StoreCDRs != nil {
storeCDRs = *attrs.StoreCDRs
}
@@ -632,7 +633,7 @@ func (self *CdrServer) V1RateCDRs(attrs utils.AttrRateCDRs, reply *string) error
if attrs.SendToStatS != nil {
sendToStats = *attrs.SendToStatS
}
replicate := len(self.cgrCfg.CDRSOnlineCDRExports) != 0
replicate := len(self.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0
if attrs.ReplicateCDRs != nil {
replicate = *attrs.ReplicateCDRs
}
@@ -706,7 +707,7 @@ func (cdrS *CdrServer) raStoReThStaCDR(cdr *CDR) {
return
}
for _, rtCDR := range ratedCDRs {
if cdrS.cgrCfg.CDRSStoreCdrs { // Store CDR
if cdrS.cgrCfg.CdrsCfg().CDRSStoreCdrs { // Store CDR
go func(rtCDR *CDR) {
if err := cdrS.cdrDb.SetCDR(rtCDR, true); err != nil {
utils.Logger.Warning(
@@ -715,7 +716,7 @@ func (cdrS *CdrServer) raStoReThStaCDR(cdr *CDR) {
}
}(rtCDR)
}
if len(cdrS.cgrCfg.CDRSOnlineCDRExports) != 0 {
if len(cdrS.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0 {
go cdrS.replicateCDRs([]*CDR{rtCDR})
}
cgrEv := rtCDR.AsCGREvent()
@@ -781,12 +782,12 @@ func (cdrS *CdrServer) V2ProcessCDR(cgrEv *utils.CGREvent, reply *string) (err e
if cdrS.chargerS == nil { // backwards compatibility for DerivedChargers
return cdrS.V1ProcessCDR(rawCDR, reply)
}
if cdrS.cgrCfg.CDRSStoreCdrs { // Store *raw CDR
if cdrS.cgrCfg.CdrsCfg().CDRSStoreCdrs { // Store *raw CDR
if err = cdrS.cdrDb.SetCDR(rawCDR, false); err != nil {
return utils.NewErrServerError(err) // Cannot store CDR
}
}
if len(cdrS.cgrCfg.CDRSOnlineCDRExports) != 0 {
if len(cdrS.cgrCfg.CdrsCfg().CDRSOnlineCDRExports) != 0 {
cdrS.replicateCDRs([]*CDR{rawCDR}) // Replicate raw CDR
}
if cdrS.thdS != nil {

View File

@@ -77,8 +77,8 @@ func (fsCdr FSCdr) getCGRID() string {
}
func (fsCdr FSCdr) getExtraFields() map[string]string {
extraFields := make(map[string]string, len(fsCdr.cgrCfg.CDRSExtraFields))
for _, field := range fsCdr.cgrCfg.CDRSExtraFields {
extraFields := make(map[string]string, len(fsCdr.cgrCfg.CdrsCfg().CDRSExtraFields))
for _, field := range fsCdr.cgrCfg.CdrsCfg().CDRSExtraFields {
origFieldVal, foundInVars := fsCdr.vars[field.Id]
if strings.HasPrefix(field.Id, utils.STATIC_VALUE_PREFIX) { // Support for static values injected in the CDRS. it will show up as {^value:value}
foundInVars = true

View File

@@ -411,7 +411,7 @@ func TestFsCdrFirstNonEmpty(t *testing.T) {
}
func TestFsCdrCDRFields(t *testing.T) {
fsCdrCfg.CDRSExtraFields = []*utils.RSRField{{Id: "sip_user_agent"}}
fsCdrCfg.CdrsCfg().CDRSExtraFields = []*utils.RSRField{{Id: "sip_user_agent"}}
fsCdr, err := NewFSCdr(body, fsCdrCfg)
if err != nil {
t.Errorf("Error loading cdr: %v", err)
@@ -445,7 +445,7 @@ func TestFsCdrSearchExtraField(t *testing.T) {
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
rsrSt1, _ := utils.NewRSRField("^injected_value")
rsrSt2, _ := utils.NewRSRField("^injected_hdr::injected_value/")
fsCdrCfg.CDRSExtraFields = []*utils.RSRField{{Id: "caller_id_name"}, rsrSt1, rsrSt2}
fsCdrCfg.CdrsCfg().CDRSExtraFields = []*utils.RSRField{{Id: "caller_id_name"}, rsrSt1, rsrSt2}
extraFields := fsCdr.getExtraFields()
if len(extraFields) != 3 || extraFields["caller_id_name"] != "1001" ||
extraFields["injected_value"] != "injected_value" ||
@@ -463,7 +463,7 @@ func TestFsCdrSearchExtraFieldInSlice(t *testing.T) {
}
func TestFsCdrSearchReplaceInExtraFields(t *testing.T) {
fsCdrCfg.CDRSExtraFields = utils.ParseRSRFieldsMustCompile(`read_codec;~sip_user_agent:s/([A-Za-z]*).+/$1/;write_codec`, utils.INFIELD_SEP)
fsCdrCfg.CdrsCfg().CDRSExtraFields = utils.ParseRSRFieldsMustCompile(`read_codec;~sip_user_agent:s/([A-Za-z]*).+/$1/;write_codec`, utils.INFIELD_SEP)
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
extraFields := fsCdr.getExtraFields()
if len(extraFields) != 3 {
@@ -514,8 +514,8 @@ func TestFsCdrDDazRSRExtraFields(t *testing.T) {
expCdrExtra := utils.ParseRSRFieldsMustCompile(`~effective_caller_id_number:s/(\d+)/+$1/`, utils.INFIELD_SEP)
if err != nil {
t.Error("Could not parse the config", err.Error())
} else if !reflect.DeepEqual(expCdrExtra[0], fsCdrCfg.CDRSExtraFields[0]) { // Kinda deepEqual bug since without index does not match
t.Errorf("Expecting: %+v, received: %+v", expCdrExtra, fsCdrCfg.CDRSExtraFields)
} else if !reflect.DeepEqual(expCdrExtra[0], fsCdrCfg.CdrsCfg().CDRSExtraFields[0]) { // Kinda deepEqual bug since without index does not match
t.Errorf("Expecting: %+v, received: %+v", expCdrExtra, fsCdrCfg.CdrsCfg().CDRSExtraFields)
}
fsCdr, err := NewFSCdr(simpleJsonCdr, fsCdrCfg)
if err != nil {