From 26cbbdd61864887a22bb0283924be8412e47e0b7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 24 Oct 2018 16:29:48 +0300 Subject: [PATCH] Added separate config structures for: Cdrs config, CdrStatscfg config --- cmd/cgr-engine/cgr-engine.go | 46 +-- config/cdrscfg.go | 131 ++++++++ config/cdrscfg_test.go | 82 +++++ config/cdrstatscfg.go | 48 +++ config/config.go | 566 ++++++++++++++++------------------- config/config_test.go | 82 +++-- config/schedulercfg.go | 10 +- config/schedulercfg_test.go | 57 ++++ engine/cdrs.go | 27 +- engine/fscdr.go | 4 +- engine/fscdr_test.go | 10 +- 11 files changed, 664 insertions(+), 399 deletions(-) create mode 100644 config/cdrscfg.go create mode 100644 config/cdrscfg_test.go create mode 100644 config/cdrstatscfg.go create mode 100644 config/schedulercfg_test.go diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index c5788629c..695bdb089 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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) } diff --git a/config/cdrscfg.go b/config/cdrscfg.go new file mode 100644 index 000000000..221675b3c --- /dev/null +++ b/config/cdrscfg.go @@ -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 +*/ + +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 +} diff --git a/config/cdrscfg_test.go b/config/cdrscfg_test.go new file mode 100644 index 000000000..4cc89eb85 --- /dev/null +++ b/config/cdrscfg_test.go @@ -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 +*/ +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: + "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)) + } +} diff --git a/config/cdrstatscfg.go b/config/cdrstatscfg.go new file mode 100644 index 000000000..2bc572563 --- /dev/null +++ b/config/cdrstatscfg.go @@ -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 +*/ + +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 +} diff --git a/config/config.go b/config/config.go index 50006acca..a9ee47d45 100755 --- a/config/config.go +++ b/config/config.go @@ -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: . - AliasesServerEnabled bool // Starts PubSub as server: . - UserServerEnabled bool // Starts User as server: - 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: . + AliasesServerEnabled bool // Starts PubSub as server: . + UserServerEnabled bool // Starts User as server: + 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(" 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(" 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(" RALs definition is mandatory!") } - for _, conn := range self.sessionSCfg.ChargerSConns { - if conn.Address == utils.MetaInternal && !self.chargerSCfg.Enabled { - return errors.New(" ChargerS not enabled but requested") + if !self.chargerSCfg.Enabled { + for _, conn := range self.sessionSCfg.ChargerSConns { + if conn.Address == utils.MetaInternal { + return errors.New(" ChargerS not enabled but requested") + } } } - for _, smgRALsConn := range self.sessionSCfg.RALsConns { - if smgRALsConn.Address == utils.MetaInternal && !self.ralsCfg.RALsEnabled { - return errors.New(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" 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(" AttributeS not enabled but requested by SMGeneric component.") + } } } if len(self.sessionSCfg.CDRsConns) == 0 { return errors.New(" CDRs definition is mandatory!") } - for _, smgCDRSConn := range self.sessionSCfg.CDRsConns { - if smgCDRSConn.Address == utils.MetaInternal && !self.CDRSEnabled { - return errors.New(" 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(" 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(" Rater definition is mandatory!") } - for _, smOsipsRaterConn := range self.SmOsipsConfig.RALsConns { - if smOsipsRaterConn.Address == utils.MetaInternal && !self.ralsCfg.RALsEnabled { - return errors.New(" RALs not enabled.") + if !self.ralsCfg.RALsEnabled { + for _, smOsipsRaterConn := range self.SmOsipsConfig.RALsConns { + if smOsipsRaterConn.Address == utils.MetaInternal { + return errors.New(" RALs not enabled.") + } } } if len(self.SmOsipsConfig.CDRsConns) == 0 { return errors.New(" CDRs definition is mandatory!") } - - for _, smOsipsCDRSConn := range self.SmOsipsConfig.CDRsConns { - if smOsipsCDRSConn.Address == utils.MetaInternal && !self.CDRSEnabled { - return errors.New(" CDRS not enabled.") + if !self.cdrsCfg.CDRSEnabled { + for _, smOsipsCDRSConn := range self.SmOsipsConfig.CDRsConns { + if smOsipsCDRSConn.Address == utils.MetaInternal { + return errors.New(" 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 } diff --git a/config/config_test.go b/config/config_test.go index 515fb6515..8dcb0e7d3 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -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) } } diff --git a/config/schedulercfg.go b/config/schedulercfg.go index e126afe25..c94065cdd 100755 --- a/config/schedulercfg.go +++ b/config/schedulercfg.go @@ -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 diff --git a/config/schedulercfg_test.go b/config/schedulercfg_test.go new file mode 100644 index 000000000..c8ee107c6 --- /dev/null +++ b/config/schedulercfg_test.go @@ -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 +*/ +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: + "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) + } +} diff --git a/engine/cdrs.go b/engine/cdrs.go index 359c5f571..a8a56dfe4 100644 --- a/engine/cdrs.go +++ b/engine/cdrs.go @@ -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(" 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(" 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 { diff --git a/engine/fscdr.go b/engine/fscdr.go index 93fff3e09..f322d692f 100644 --- a/engine/fscdr.go +++ b/engine/fscdr.go @@ -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 diff --git a/engine/fscdr_test.go b/engine/fscdr_test.go index 5fce802d9..ad2c792ce 100644 --- a/engine/fscdr_test.go +++ b/engine/fscdr_test.go @@ -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 {