mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
880 lines
30 KiB
Go
880 lines
30 KiB
Go
/*
|
|
Real-time Charging System 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 (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
const (
|
|
DISABLED = "disabled"
|
|
JSON = "json"
|
|
GOB = "gob"
|
|
POSTGRES = "postgres"
|
|
MONGO = "mongo"
|
|
REDIS = "redis"
|
|
SAME = "same"
|
|
FS = "freeswitch"
|
|
)
|
|
|
|
var (
|
|
cgrCfg *CGRConfig // will be shared
|
|
dfltFsConnConfig *FsConnConfig // Default FreeSWITCH Connection configuration, built out of json default configuration
|
|
dfltKamConnConfig *KamConnConfig // Default Kamailio Connection configuration
|
|
dfltHaPoolConfig *HaPoolConfig
|
|
)
|
|
|
|
// Used to retrieve system configuration from other packages
|
|
func CgrConfig() *CGRConfig {
|
|
return cgrCfg
|
|
}
|
|
|
|
// Used to set system configuration from other places
|
|
func SetCgrConfig(cfg *CGRConfig) {
|
|
cgrCfg = cfg
|
|
}
|
|
|
|
func NewDefaultCGRConfig() (*CGRConfig, error) {
|
|
cfg := new(CGRConfig)
|
|
cfg.DataFolderPath = "/usr/share/cgrates/"
|
|
cfg.SmGenericConfig = new(SmGenericConfig)
|
|
cfg.SmFsConfig = new(SmFsConfig)
|
|
cfg.SmKamConfig = new(SmKamConfig)
|
|
cfg.SmOsipsConfig = new(SmOsipsConfig)
|
|
cfg.diameterAgentCfg = new(DiameterAgentCfg)
|
|
cfg.ConfigReloads = make(map[string]chan struct{})
|
|
cfg.ConfigReloads[utils.CDRC] = make(chan struct{}, 1)
|
|
cfg.ConfigReloads[utils.CDRC] <- struct{}{} // Unlock the channel
|
|
cfg.ConfigReloads[utils.CDRE] = make(chan struct{}, 1)
|
|
cfg.ConfigReloads[utils.CDRE] <- struct{}{} // Unlock the channel
|
|
cfg.ConfigReloads[utils.SURETAX] = make(chan struct{}, 1)
|
|
cfg.ConfigReloads[utils.SURETAX] <- struct{}{} // Unlock the channel
|
|
cfg.ConfigReloads[utils.DIAMETER_AGENT] = make(chan struct{}, 1)
|
|
cfg.ConfigReloads[utils.DIAMETER_AGENT] <- struct{}{} // Unlock the channel
|
|
cgrJsonCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(CGRATES_CFG_JSON))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cfg.MaxCallDuration = time.Duration(3) * time.Hour // Hardcoded for now
|
|
if err := cfg.loadFromJsonCfg(cgrJsonCfg); err != nil {
|
|
return nil, err
|
|
}
|
|
cfg.dfltCdreProfile = cfg.CdreProfiles[utils.META_DEFAULT].Clone() // So default will stay unique, will have nil pointer in case of no defaults loaded which is an extra check
|
|
cfg.dfltCdrcProfile = cfg.CdrcProfiles["/var/log/cgrates/cdrc/in"][utils.META_DEFAULT].Clone()
|
|
dfltFsConnConfig = cfg.SmFsConfig.Connections[0] // We leave it crashing here on purpose if no Connection defaults defined
|
|
dfltKamConnConfig = cfg.SmKamConfig.Connections[0]
|
|
if err := cfg.checkConfigSanity(); err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func NewCGRConfigFromJsonString(cfgJsonStr string) (*CGRConfig, error) {
|
|
cfg := new(CGRConfig)
|
|
if jsnCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(cfgJsonStr)); err != nil {
|
|
return nil, err
|
|
} else if err := cfg.loadFromJsonCfg(jsnCfg); err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func NewCGRConfigFromJsonStringWithDefaults(cfgJsonStr string) (*CGRConfig, error) {
|
|
cfg, _ := NewDefaultCGRConfig()
|
|
if jsnCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(cfgJsonStr)); err != nil {
|
|
return nil, err
|
|
} else if err := cfg.loadFromJsonCfg(jsnCfg); err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
// Reads all .json files out of a folder/subfolders and loads them up in lexical order
|
|
func NewCGRConfigFromFolder(cfgDir string) (*CGRConfig, error) {
|
|
cfg, err := NewDefaultCGRConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fi, err := os.Stat(cfgDir)
|
|
if err != nil {
|
|
if strings.HasSuffix(err.Error(), "no such file or directory") {
|
|
return cfg, nil
|
|
}
|
|
return nil, err
|
|
} else if !fi.IsDir() && cfgDir != utils.CONFIG_DIR { // If config dir defined, needs to exist, not checking for default
|
|
return nil, fmt.Errorf("Path: %s not a directory.", cfgDir)
|
|
}
|
|
if fi.IsDir() {
|
|
jsonFilesFound := false
|
|
err = filepath.Walk(cfgDir, func(path string, info os.FileInfo, err error) error {
|
|
if !info.IsDir() {
|
|
return nil
|
|
}
|
|
cfgFiles, err := filepath.Glob(filepath.Join(path, "*.json"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cfgFiles == nil { // No need of processing further since there are no config files in the folder
|
|
return nil
|
|
}
|
|
if !jsonFilesFound {
|
|
jsonFilesFound = true
|
|
}
|
|
for _, jsonFilePath := range cfgFiles {
|
|
if cgrJsonCfg, err := NewCgrJsonCfgFromFile(jsonFilePath); err != nil {
|
|
return err
|
|
} else if err := cfg.loadFromJsonCfg(cgrJsonCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
} else if !jsonFilesFound {
|
|
return nil, fmt.Errorf("No config file found on path %s", cfgDir)
|
|
}
|
|
}
|
|
if err := cfg.checkConfigSanity(); err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
// Holds system configuration, defaults are overwritten with values from config file if found
|
|
type CGRConfig struct {
|
|
TpDbType string
|
|
TpDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets.
|
|
TpDbPort string // The port to bind to.
|
|
TpDbName string // The name of the database to connect to.
|
|
TpDbUser string // The user to sign in as.
|
|
TpDbPass string // The user's password.
|
|
DataDbType string
|
|
DataDbHost string // The host to connect to. Values that start with / are for UNIX domain sockets.
|
|
DataDbPort string // The port to bind to.
|
|
DataDbName string // The name of the database to connect to.
|
|
DataDbUser string // The user to sign in as.
|
|
DataDbPass string // The user's password.
|
|
LoadHistorySize int // Maximum number of records to archive in load history
|
|
StorDBType string // Should reflect the database type used to store logs
|
|
StorDBHost string // The host to connect to. Values that start with / are for UNIX domain sockets.
|
|
StorDBPort string // Th e port to bind to.
|
|
StorDBName string // The name of the database to connect to.
|
|
StorDBUser string // The user to sign in as.
|
|
StorDBPass string // The user's password.
|
|
StorDBMaxOpenConns int // Maximum database connections opened
|
|
StorDBMaxIdleConns int // Maximum idle connections to keep opened
|
|
DBDataEncoding string // The encoding used to store object data in strings: <msgpack|json>
|
|
RPCJSONListen string // RPC JSON listening address
|
|
RPCGOBListen string // RPC GOB listening address
|
|
HTTPListen string // HTTP listening address
|
|
DefaultReqType string // Use this request type if not defined on top
|
|
DefaultCategory string // set default type of record
|
|
DefaultTenant string // set default tenant
|
|
DefaultSubject string // set default rating subject, useful in case of fallback
|
|
DefaultTimezone string // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
|
|
Reconnects int // number of recconect attempts in case of connection lost <-1 for infinite | nb>
|
|
ConnectAttempts int // number of initial connection attempts before giving up
|
|
ResponseCacheTTL time.Duration // the life span of a cached response
|
|
InternalTtl time.Duration // maximum duration to wait for internal connections before giving up
|
|
RoundingDecimals int // Number of decimals to round end prices at
|
|
HttpSkipTlsVerify bool // If enabled Http Client will accept any TLS certificate
|
|
TpExportPath string // Path towards export folder for offline Tariff Plans
|
|
HttpFailedDir string // Directory path where we store failed http requests
|
|
MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file
|
|
RaterEnabled bool // start standalone server (no balancer)
|
|
RaterBalancer string // balancer address host:port
|
|
RaterCdrStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234>
|
|
RaterHistoryServer string
|
|
RaterPubSubServer string
|
|
RaterUserServer string
|
|
RaterAliasesServer string
|
|
BalancerEnabled bool
|
|
SchedulerEnabled bool
|
|
CDRSEnabled bool // Enable CDR Server service
|
|
CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs
|
|
CDRSStoreCdrs bool // store cdrs in storDb
|
|
CDRSRater string // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
|
|
CDRSPubSub string // address where to reach the pubsub service: <""|internal|x.y.z.y:1234>
|
|
CDRSUsers string // address where to reach the users service: <""|internal|x.y.z.y:1234>
|
|
CDRSAliases string // address where to reach the aliases service: <""|internal|x.y.z.y:1234>
|
|
CDRSStats string // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234>
|
|
CDRSCdrReplication []*CdrReplicationCfg // Replicate raw CDRs to a number of servers
|
|
CDRStatsEnabled bool // Enable CDR Stats service
|
|
CDRStatsSaveInterval time.Duration // Save interval duration
|
|
CdreProfiles map[string]*CdreConfig
|
|
CdrcProfiles map[string]map[string]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath]map[instanceName]{Configs}
|
|
SmGenericConfig *SmGenericConfig
|
|
SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration
|
|
SmKamConfig *SmKamConfig // SM-Kamailio Configuration
|
|
SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration
|
|
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
|
|
HistoryServer string // Address where to reach the master history server: <internal|x.y.z.y:1234>
|
|
HistoryServerEnabled bool // Starts History as server: <true|false>.
|
|
HistoryDir string // Location on disk where to store history files.
|
|
HistorySaveInterval time.Duration // The timout duration between pubsub writes
|
|
PubSubServerEnabled bool // Starts PubSub as server: <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
|
|
MailerServer string // The server to use when sending emails out
|
|
MailerAuthUser string // Authenticate to email server using this user
|
|
MailerAuthPass string // Authenticate to email server with this password
|
|
MailerFromAddr string // From address used when sending emails out
|
|
DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options
|
|
sureTaxCfg *SureTaxCfg // Load here SureTax configuration, as pointer so we can have runtime reloads in the future
|
|
ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur
|
|
// Cache defaults loaded from json and needing clones
|
|
dfltCdreProfile *CdreConfig // Default cdreConfig profile
|
|
dfltCdrcProfile *CdrcConfig // Default cdrcConfig profile
|
|
}
|
|
|
|
func (self *CGRConfig) checkConfigSanity() error {
|
|
// Rater checks
|
|
if self.RaterEnabled {
|
|
if self.RaterBalancer == utils.INTERNAL && !self.BalancerEnabled {
|
|
return errors.New("Balancer not enabled but requested by Rater component.")
|
|
}
|
|
if self.RaterCdrStats == utils.INTERNAL && !self.CDRStatsEnabled {
|
|
return errors.New("CDRStats not enabled but requested by Rater component.")
|
|
}
|
|
if self.RaterHistoryServer == utils.INTERNAL && !self.HistoryServerEnabled {
|
|
return errors.New("History server not enabled but requested by Rater component.")
|
|
}
|
|
if self.RaterPubSubServer == utils.INTERNAL && !self.PubSubServerEnabled {
|
|
return errors.New("PubSub server not enabled but requested by Rater component.")
|
|
}
|
|
if self.RaterAliasesServer == utils.INTERNAL && !self.AliasesServerEnabled {
|
|
return errors.New("Aliases server not enabled but requested by Rater component.")
|
|
}
|
|
if self.RaterUserServer == utils.INTERNAL && !self.UserServerEnabled {
|
|
return errors.New("Users service not enabled but requested by Rater component.")
|
|
}
|
|
}
|
|
// CDRServer checks
|
|
if self.CDRSEnabled {
|
|
if self.CDRSRater == utils.INTERNAL && !self.RaterEnabled {
|
|
return errors.New("Rater not enabled but requested by CDRS component.")
|
|
}
|
|
if self.CDRSPubSub == utils.INTERNAL && !self.PubSubServerEnabled {
|
|
return errors.New("PubSub service not enabled but requested by CDRS component.")
|
|
}
|
|
if self.CDRSUsers == utils.INTERNAL && !self.UserServerEnabled {
|
|
return errors.New("Users service not enabled but requested by CDRS component.")
|
|
}
|
|
if self.CDRSAliases == utils.INTERNAL && !self.AliasesServerEnabled {
|
|
return errors.New("Aliases service not enabled but requested by CDRS component.")
|
|
}
|
|
if self.CDRSStats == utils.INTERNAL && !self.CDRStatsEnabled {
|
|
return errors.New("CDRStats not enabled but requested by CDRS component.")
|
|
}
|
|
}
|
|
// CDRC sanity checks
|
|
for _, cdrcCfgs := range self.CdrcProfiles {
|
|
for _, cdrcInst := range cdrcCfgs {
|
|
if !cdrcInst.Enabled {
|
|
continue
|
|
}
|
|
if len(cdrcInst.Cdrs) == 0 {
|
|
return errors.New("CdrC enabled but no CDRS defined!")
|
|
} else if cdrcInst.Cdrs == utils.INTERNAL && !self.CDRSEnabled {
|
|
return errors.New("CDRS not enabled but referenced from CDRC")
|
|
}
|
|
if len(cdrcInst.ContentFields) == 0 {
|
|
return errors.New("CdrC enabled but no fields to be processed defined!")
|
|
}
|
|
if cdrcInst.CdrFormat == utils.CSV {
|
|
for _, cdrFld := range cdrcInst.ContentFields {
|
|
for _, rsrFld := range cdrFld.Value {
|
|
if _, errConv := strconv.Atoi(rsrFld.Id); errConv != nil && !rsrFld.IsStatic() {
|
|
return fmt.Errorf("CDR fields must be indices in case of .csv files, have instead: %s", rsrFld.Id)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// SM-Generic checks
|
|
if self.SmGenericConfig.Enabled {
|
|
if len(self.SmGenericConfig.HaRater) == 0 {
|
|
return errors.New("Rater definition is mandatory!")
|
|
}
|
|
if len(self.SmGenericConfig.HaCdrs) == 0 {
|
|
return errors.New("Cdrs definition is mandatory!")
|
|
}
|
|
if self.SmGenericConfig.HaRater[0].Server == utils.INTERNAL && !self.RaterEnabled {
|
|
return errors.New("Rater not enabled but requested by SM-Generic component.")
|
|
}
|
|
if self.SmGenericConfig.HaCdrs[0].Server == utils.INTERNAL && !self.CDRSEnabled {
|
|
return errors.New("CDRS not enabled but referenced by SM-Generic component")
|
|
}
|
|
}
|
|
// SM-FreeSWITCH checks
|
|
if self.SmFsConfig.Enabled {
|
|
if len(self.SmFsConfig.HaRater) == 0 {
|
|
return errors.New("Rater definition is mandatory!")
|
|
}
|
|
if len(self.SmFsConfig.HaCdrs) == 0 {
|
|
return errors.New("Cdrs definition is mandatory!")
|
|
}
|
|
if self.SmFsConfig.HaRater[0].Server == utils.INTERNAL && !self.RaterEnabled {
|
|
return errors.New("Rater not enabled but requested by SM-FreeSWITCH component.")
|
|
}
|
|
if self.SmFsConfig.HaCdrs[0].Server == utils.INTERNAL && !self.CDRSEnabled {
|
|
return errors.New("CDRS not enabled but referenced by SM-FreeSWITCH component")
|
|
}
|
|
}
|
|
// SM-Kamailio checks
|
|
if self.SmKamConfig.Enabled {
|
|
if len(self.SmKamConfig.HaRater) == 0 {
|
|
return errors.New("Rater definition is mandatory!")
|
|
}
|
|
if len(self.SmKamConfig.HaCdrs) == 0 {
|
|
return errors.New("Cdrs definition is mandatory!")
|
|
}
|
|
if self.SmKamConfig.HaRater[0].Server == utils.INTERNAL && !self.RaterEnabled {
|
|
return errors.New("Rater not enabled but requested by SM-Kamailio component.")
|
|
}
|
|
if self.SmKamConfig.HaCdrs[0].Server == utils.INTERNAL && !self.CDRSEnabled {
|
|
return errors.New("CDRS not enabled but referenced by SM-Kamailio component")
|
|
}
|
|
}
|
|
// SM-OpenSIPS checks
|
|
if self.SmOsipsConfig.Enabled {
|
|
if len(self.SmOsipsConfig.HaRater) == 0 {
|
|
return errors.New("Rater definition is mandatory!")
|
|
}
|
|
if len(self.SmOsipsConfig.HaCdrs) == 0 {
|
|
return errors.New("Cdrs definition is mandatory!")
|
|
}
|
|
if self.SmOsipsConfig.HaRater[0].Server == utils.INTERNAL && !self.RaterEnabled {
|
|
return errors.New("Rater not enabled but requested by SM-OpenSIPS component.")
|
|
}
|
|
if self.SmOsipsConfig.HaCdrs[0].Server == utils.INTERNAL && !self.CDRSEnabled {
|
|
return errors.New("CDRS not enabled but referenced by SM-OpenSIPS component")
|
|
}
|
|
}
|
|
// DAgent checks
|
|
if self.diameterAgentCfg.Enabled {
|
|
if self.diameterAgentCfg.SMGeneric == utils.INTERNAL && !self.SmGenericConfig.Enabled {
|
|
return errors.New("SMGeneric not enabled but referenced by DiameterAgent component")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Loads from json configuration object, will be used for defaults, config from file and reload, might need lock
|
|
func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
|
|
|
|
// Load sections out of JSON config, stop on error
|
|
jsnGeneralCfg, err := jsnCfg.GeneralJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnListenCfg, err := jsnCfg.ListenJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnTpDbCfg, err := jsnCfg.DbJsonCfg(TPDB_JSN)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnStorDbCfg, err := jsnCfg.DbJsonCfg(STORDB_JSN)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnBalancerCfg, err := jsnCfg.BalancerJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnRaterCfg, err := jsnCfg.RaterJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSchedCfg, err := jsnCfg.SchedulerJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnCdrsCfg, err := jsnCfg.CdrsJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnCdrstatsCfg, err := jsnCfg.CdrStatsJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnCdreCfg, err := jsnCfg.CdreJsonCfgs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnCdrcCfg, err := jsnCfg.CdrcJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSmGenericCfg, err := jsnCfg.SmGenericJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSmFsCfg, err := jsnCfg.SmFsJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSmKamCfg, err := jsnCfg.SmKamJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSmOsipsCfg, err := jsnCfg.SmOsipsJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnDACfg, err := jsnCfg.DiameterAgentJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnHistServCfg, err := jsnCfg.HistServJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnPubSubServCfg, err := jsnCfg.PubSubServJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnAliasesServCfg, err := jsnCfg.AliasesServJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnUserServCfg, err := jsnCfg.UserServJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnMailerCfg, err := jsnCfg.MailerJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsnSureTaxCfg, err := jsnCfg.SureTaxJsonCfg()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// All good, start populating config variables
|
|
if jsnTpDbCfg != nil {
|
|
if jsnTpDbCfg.Db_type != nil {
|
|
self.TpDbType = *jsnTpDbCfg.Db_type
|
|
}
|
|
if jsnTpDbCfg.Db_host != nil {
|
|
self.TpDbHost = *jsnTpDbCfg.Db_host
|
|
}
|
|
if jsnTpDbCfg.Db_port != nil {
|
|
self.TpDbPort = strconv.Itoa(*jsnTpDbCfg.Db_port)
|
|
}
|
|
if jsnTpDbCfg.Db_name != nil {
|
|
self.TpDbName = *jsnTpDbCfg.Db_name
|
|
}
|
|
if jsnTpDbCfg.Db_user != nil {
|
|
self.TpDbUser = *jsnTpDbCfg.Db_user
|
|
}
|
|
if jsnTpDbCfg.Db_passwd != nil {
|
|
self.TpDbPass = *jsnTpDbCfg.Db_passwd
|
|
}
|
|
}
|
|
|
|
if jsnDataDbCfg != nil {
|
|
if jsnDataDbCfg.Db_type != nil {
|
|
self.DataDbType = *jsnDataDbCfg.Db_type
|
|
}
|
|
if jsnDataDbCfg.Db_host != nil {
|
|
self.DataDbHost = *jsnDataDbCfg.Db_host
|
|
}
|
|
if jsnDataDbCfg.Db_port != nil {
|
|
self.DataDbPort = strconv.Itoa(*jsnDataDbCfg.Db_port)
|
|
}
|
|
if jsnDataDbCfg.Db_name != nil {
|
|
self.DataDbName = *jsnDataDbCfg.Db_name
|
|
}
|
|
if jsnDataDbCfg.Db_user != nil {
|
|
self.DataDbUser = *jsnDataDbCfg.Db_user
|
|
}
|
|
if jsnDataDbCfg.Db_passwd != nil {
|
|
self.DataDbPass = *jsnDataDbCfg.Db_passwd
|
|
}
|
|
if jsnDataDbCfg.Load_history_size != nil {
|
|
self.LoadHistorySize = *jsnDataDbCfg.Load_history_size
|
|
}
|
|
}
|
|
|
|
if jsnStorDbCfg != nil {
|
|
if jsnStorDbCfg.Db_type != nil {
|
|
self.StorDBType = *jsnStorDbCfg.Db_type
|
|
}
|
|
if jsnStorDbCfg.Db_host != nil {
|
|
self.StorDBHost = *jsnStorDbCfg.Db_host
|
|
}
|
|
if jsnStorDbCfg.Db_port != nil {
|
|
self.StorDBPort = strconv.Itoa(*jsnStorDbCfg.Db_port)
|
|
}
|
|
if jsnStorDbCfg.Db_name != nil {
|
|
self.StorDBName = *jsnStorDbCfg.Db_name
|
|
}
|
|
if jsnStorDbCfg.Db_user != nil {
|
|
self.StorDBUser = *jsnStorDbCfg.Db_user
|
|
}
|
|
if jsnStorDbCfg.Db_passwd != nil {
|
|
self.StorDBPass = *jsnStorDbCfg.Db_passwd
|
|
}
|
|
if jsnStorDbCfg.Max_open_conns != nil {
|
|
self.StorDBMaxOpenConns = *jsnStorDbCfg.Max_open_conns
|
|
}
|
|
if jsnStorDbCfg.Max_idle_conns != nil {
|
|
self.StorDBMaxIdleConns = *jsnStorDbCfg.Max_idle_conns
|
|
}
|
|
}
|
|
|
|
if jsnGeneralCfg != nil {
|
|
if jsnGeneralCfg.Dbdata_encoding != nil {
|
|
self.DBDataEncoding = *jsnGeneralCfg.Dbdata_encoding
|
|
}
|
|
if jsnGeneralCfg.Default_reqtype != nil {
|
|
self.DefaultReqType = *jsnGeneralCfg.Default_reqtype
|
|
}
|
|
if jsnGeneralCfg.Default_category != nil {
|
|
self.DefaultCategory = *jsnGeneralCfg.Default_category
|
|
}
|
|
if jsnGeneralCfg.Default_tenant != nil {
|
|
self.DefaultTenant = *jsnGeneralCfg.Default_tenant
|
|
}
|
|
if jsnGeneralCfg.Default_subject != nil {
|
|
self.DefaultSubject = *jsnGeneralCfg.Default_subject
|
|
}
|
|
if jsnGeneralCfg.Connect_attempts != nil {
|
|
self.ConnectAttempts = *jsnGeneralCfg.Connect_attempts
|
|
}
|
|
if jsnGeneralCfg.Response_cache_ttl != nil {
|
|
if self.ResponseCacheTTL, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Response_cache_ttl); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if jsnGeneralCfg.Reconnects != nil {
|
|
self.Reconnects = *jsnGeneralCfg.Reconnects
|
|
}
|
|
if jsnGeneralCfg.Rounding_decimals != nil {
|
|
self.RoundingDecimals = *jsnGeneralCfg.Rounding_decimals
|
|
}
|
|
if jsnGeneralCfg.Http_skip_tls_verify != nil {
|
|
self.HttpSkipTlsVerify = *jsnGeneralCfg.Http_skip_tls_verify
|
|
}
|
|
if jsnGeneralCfg.Tpexport_dir != nil {
|
|
self.TpExportPath = *jsnGeneralCfg.Tpexport_dir
|
|
}
|
|
if jsnGeneralCfg.Http_failed_dir != nil {
|
|
self.HttpFailedDir = *jsnGeneralCfg.Http_failed_dir
|
|
}
|
|
if jsnGeneralCfg.Default_timezone != nil {
|
|
self.DefaultTimezone = *jsnGeneralCfg.Default_timezone
|
|
}
|
|
if jsnGeneralCfg.Internal_ttl != nil {
|
|
if self.InternalTtl, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Internal_ttl); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnListenCfg != nil {
|
|
if jsnListenCfg.Rpc_json != nil {
|
|
self.RPCJSONListen = *jsnListenCfg.Rpc_json
|
|
}
|
|
if jsnListenCfg.Rpc_gob != nil {
|
|
self.RPCGOBListen = *jsnListenCfg.Rpc_gob
|
|
}
|
|
if jsnListenCfg.Http != nil {
|
|
self.HTTPListen = *jsnListenCfg.Http
|
|
}
|
|
}
|
|
|
|
if jsnRaterCfg != nil {
|
|
if jsnRaterCfg.Enabled != nil {
|
|
self.RaterEnabled = *jsnRaterCfg.Enabled
|
|
}
|
|
if jsnRaterCfg.Balancer != nil {
|
|
self.RaterBalancer = *jsnRaterCfg.Balancer
|
|
}
|
|
if jsnRaterCfg.Cdrstats != nil {
|
|
self.RaterCdrStats = *jsnRaterCfg.Cdrstats
|
|
}
|
|
if jsnRaterCfg.Historys != nil {
|
|
self.RaterHistoryServer = *jsnRaterCfg.Historys
|
|
}
|
|
if jsnRaterCfg.Pubsubs != nil {
|
|
self.RaterPubSubServer = *jsnRaterCfg.Pubsubs
|
|
}
|
|
if jsnRaterCfg.Aliases != nil {
|
|
self.RaterAliasesServer = *jsnRaterCfg.Aliases
|
|
}
|
|
if jsnRaterCfg.Users != nil {
|
|
self.RaterUserServer = *jsnRaterCfg.Users
|
|
}
|
|
}
|
|
|
|
if jsnBalancerCfg != nil && jsnBalancerCfg.Enabled != nil {
|
|
self.BalancerEnabled = *jsnBalancerCfg.Enabled
|
|
}
|
|
|
|
if jsnSchedCfg != nil && jsnSchedCfg.Enabled != nil {
|
|
self.SchedulerEnabled = *jsnSchedCfg.Enabled
|
|
}
|
|
|
|
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.Rater != nil {
|
|
self.CDRSRater = *jsnCdrsCfg.Rater
|
|
}
|
|
if jsnCdrsCfg.Pubsubs != nil {
|
|
self.CDRSPubSub = *jsnCdrsCfg.Pubsubs
|
|
}
|
|
if jsnCdrsCfg.Users != nil {
|
|
self.CDRSUsers = *jsnCdrsCfg.Users
|
|
}
|
|
if jsnCdrsCfg.Aliases != nil {
|
|
self.CDRSAliases = *jsnCdrsCfg.Aliases
|
|
}
|
|
if jsnCdrsCfg.Cdrstats != nil {
|
|
self.CDRSStats = *jsnCdrsCfg.Cdrstats
|
|
}
|
|
if jsnCdrsCfg.Cdr_replication != nil {
|
|
self.CDRSCdrReplication = make([]*CdrReplicationCfg, len(*jsnCdrsCfg.Cdr_replication))
|
|
for idx, rplJsonCfg := range *jsnCdrsCfg.Cdr_replication {
|
|
self.CDRSCdrReplication[idx] = new(CdrReplicationCfg)
|
|
if rplJsonCfg.Transport != nil {
|
|
self.CDRSCdrReplication[idx].Transport = *rplJsonCfg.Transport
|
|
}
|
|
if rplJsonCfg.Server != nil {
|
|
self.CDRSCdrReplication[idx].Server = *rplJsonCfg.Server
|
|
}
|
|
if rplJsonCfg.Synchronous != nil {
|
|
self.CDRSCdrReplication[idx].Synchronous = *rplJsonCfg.Synchronous
|
|
}
|
|
self.CDRSCdrReplication[idx].Attempts = 1
|
|
if rplJsonCfg.Attempts != nil {
|
|
self.CDRSCdrReplication[idx].Attempts = *rplJsonCfg.Attempts
|
|
}
|
|
if rplJsonCfg.Cdr_filter != nil {
|
|
if self.CDRSCdrReplication[idx].CdrFilter, err = utils.ParseRSRFields(*rplJsonCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnCdrstatsCfg != nil {
|
|
if jsnCdrstatsCfg.Enabled != nil {
|
|
self.CDRStatsEnabled = *jsnCdrstatsCfg.Enabled
|
|
if jsnCdrstatsCfg.Save_Interval != nil {
|
|
if self.CDRStatsSaveInterval, err = utils.ParseDurationWithSecs(*jsnCdrstatsCfg.Save_Interval); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnCdreCfg != nil {
|
|
if self.CdreProfiles == nil {
|
|
self.CdreProfiles = make(map[string]*CdreConfig)
|
|
}
|
|
for profileName, jsnCdre1Cfg := range jsnCdreCfg {
|
|
if _, hasProfile := self.CdreProfiles[profileName]; !hasProfile { // New profile, create before loading from json
|
|
self.CdreProfiles[profileName] = new(CdreConfig)
|
|
if profileName != utils.META_DEFAULT {
|
|
self.CdreProfiles[profileName] = self.dfltCdreProfile.Clone() // Clone default so we do not inherit pointers
|
|
}
|
|
}
|
|
if err = self.CdreProfiles[profileName].loadFromJsonCfg(jsnCdre1Cfg); err != nil { // Update the existing profile with content from json config
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnCdrcCfg != nil {
|
|
if self.CdrcProfiles == nil {
|
|
self.CdrcProfiles = make(map[string]map[string]*CdrcConfig)
|
|
}
|
|
for profileName, jsnCrc1Cfg := range jsnCdrcCfg {
|
|
if _, hasDir := self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir]; !hasDir {
|
|
self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir] = make(map[string]*CdrcConfig)
|
|
}
|
|
if _, hasProfile := self.CdrcProfiles[profileName]; !hasProfile {
|
|
if profileName == utils.META_DEFAULT {
|
|
self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName] = new(CdrcConfig)
|
|
} else {
|
|
self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName] = self.dfltCdrcProfile.Clone() // Clone default so we do not inherit pointers
|
|
}
|
|
}
|
|
if err = self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName].loadFromJsonCfg(jsnCrc1Cfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnSmGenericCfg != nil {
|
|
if err := self.SmGenericConfig.loadFromJsonCfg(jsnSmGenericCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if jsnSmFsCfg != nil {
|
|
if err := self.SmFsConfig.loadFromJsonCfg(jsnSmFsCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if jsnSmKamCfg != nil {
|
|
if err := self.SmKamConfig.loadFromJsonCfg(jsnSmKamCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if jsnSmOsipsCfg != nil {
|
|
if err := self.SmOsipsConfig.loadFromJsonCfg(jsnSmOsipsCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if jsnDACfg != nil {
|
|
if err := self.diameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if jsnHistServCfg != nil {
|
|
if jsnHistServCfg.Enabled != nil {
|
|
self.HistoryServerEnabled = *jsnHistServCfg.Enabled
|
|
}
|
|
if jsnHistServCfg.History_dir != nil {
|
|
self.HistoryDir = *jsnHistServCfg.History_dir
|
|
}
|
|
if jsnHistServCfg.Save_interval != nil {
|
|
if self.HistorySaveInterval, err = utils.ParseDurationWithSecs(*jsnHistServCfg.Save_interval); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if jsnPubSubServCfg != nil {
|
|
if jsnPubSubServCfg.Enabled != nil {
|
|
self.PubSubServerEnabled = *jsnPubSubServCfg.Enabled
|
|
}
|
|
}
|
|
|
|
if jsnAliasesServCfg != nil {
|
|
if jsnAliasesServCfg.Enabled != nil {
|
|
self.AliasesServerEnabled = *jsnAliasesServCfg.Enabled
|
|
}
|
|
}
|
|
|
|
if jsnUserServCfg != nil {
|
|
if jsnUserServCfg.Enabled != nil {
|
|
self.UserServerEnabled = *jsnUserServCfg.Enabled
|
|
}
|
|
if jsnUserServCfg.Indexes != nil {
|
|
self.UserServerIndexes = *jsnUserServCfg.Indexes
|
|
}
|
|
}
|
|
|
|
if jsnMailerCfg != nil {
|
|
if jsnMailerCfg.Server != nil {
|
|
self.MailerServer = *jsnMailerCfg.Server
|
|
}
|
|
if jsnMailerCfg.Auth_user != nil {
|
|
self.MailerAuthUser = *jsnMailerCfg.Auth_user
|
|
}
|
|
if jsnMailerCfg.Auth_passwd != nil {
|
|
self.MailerAuthPass = *jsnMailerCfg.Auth_passwd
|
|
}
|
|
if jsnMailerCfg.From_address != nil {
|
|
self.MailerFromAddr = *jsnMailerCfg.From_address
|
|
}
|
|
}
|
|
|
|
if jsnSureTaxCfg != nil { // New config for SureTax
|
|
if self.sureTaxCfg, err = NewSureTaxCfgWithDefaults(); err != nil {
|
|
return err
|
|
}
|
|
if err := self.sureTaxCfg.loadFromJsonCfg(jsnSureTaxCfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Use locking to retrieve the configuration, possibility later for runtime reload
|
|
func (self *CGRConfig) SureTaxCfg() *SureTaxCfg {
|
|
cfgChan := <-self.ConfigReloads[utils.SURETAX] // Lock config for read or reloads
|
|
defer func() { self.ConfigReloads[utils.SURETAX] <- cfgChan }()
|
|
return self.sureTaxCfg
|
|
}
|
|
|
|
func (self *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg {
|
|
cfgChan := <-self.ConfigReloads[utils.DIAMETER_AGENT] // Lock config for read or reloads
|
|
defer func() { self.ConfigReloads[utils.DIAMETER_AGENT] <- cfgChan }()
|
|
return self.diameterAgentCfg
|
|
}
|