mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Add RPCConns section in config
This commit is contained in:
@@ -31,6 +31,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/rpcclient"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -134,7 +136,7 @@ func NewDefaultCGRConfig() (cfg *CGRConfig, err error) {
|
||||
cfg.DataFolderPath = "/usr/share/cgrates/"
|
||||
cfg.MaxCallDuration = time.Duration(3) * time.Hour // Hardcoded for now
|
||||
|
||||
cfg.rpcConns = make(map[string]*RpcConn)
|
||||
cfg.rpcConns = make(map[string]*RPCConn)
|
||||
cfg.generalCfg = new(GeneralCfg)
|
||||
cfg.generalCfg.NodeID = utils.UUIDSha1Prefix()
|
||||
cfg.dataDbCfg = new(DataDbCfg)
|
||||
@@ -257,7 +259,7 @@ type CGRConfig struct {
|
||||
ConfigReloads map[string]chan struct{} // Signals to specific entities that a config reload should occur
|
||||
rldChans map[string]chan struct{} // index here the channels used for reloads
|
||||
|
||||
rpcConns map[string]*RpcConn
|
||||
rpcConns map[string]*RPCConn
|
||||
|
||||
generalCfg *GeneralCfg // General config
|
||||
dataDbCfg *DataDbCfg // Database config
|
||||
@@ -321,7 +323,7 @@ func (cfg *CGRConfig) LazySanityCheck() {
|
||||
func (cfg *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
// Load sections out of JSON config, stop on error
|
||||
for _, loadFunc := range []func(*CgrJsonCfg) error{
|
||||
cfg.loadRpcConns,
|
||||
cfg.loadRPCConns,
|
||||
cfg.loadGeneralCfg, cfg.loadCacheCfg, cfg.loadListenCfg,
|
||||
cfg.loadHttpCfg, cfg.loadDataDBCfg, cfg.loadStorDBCfg,
|
||||
cfg.loadFilterSCfg, cfg.loadRalSCfg, cfg.loadSchedulerCfg,
|
||||
@@ -341,12 +343,37 @@ func (cfg *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// loadRpcConns loads the RPCConns section of the configuration
|
||||
func (cfg *CGRConfig) loadRpcConns(jsnCfg *CgrJsonCfg) (err error) {
|
||||
//var jsnRpcConns map[string]*RpcConnsJson
|
||||
//if jsnRpcConns, err = jsnCfg.RpcConnJsonCfg(); err != nil {
|
||||
// return
|
||||
//}
|
||||
// loadRPCConns loads the RPCConns section of the configuration
|
||||
func (cfg *CGRConfig) loadRPCConns(jsnCfg *CgrJsonCfg) (err error) {
|
||||
var jsnRpcConns map[string]*RPCConnsJson
|
||||
if jsnRpcConns, err = jsnCfg.RPCConnJsonCfg(); err != nil {
|
||||
return
|
||||
}
|
||||
// hardoded the *internal and *localhost connections
|
||||
cfg.rpcConns[utils.MetaInternal] = &RPCConn{
|
||||
Strategy: rpcclient.POOL_FIRST,
|
||||
PoolSize: 0,
|
||||
Conns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
},
|
||||
}
|
||||
cfg.rpcConns[utils.MetaLocalHost] = &RPCConn{
|
||||
Strategy: rpcclient.POOL_FIRST,
|
||||
PoolSize: 0,
|
||||
Conns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: "127.0.0.1:2012",
|
||||
Transport: utils.MetaJSONrpc,
|
||||
},
|
||||
},
|
||||
}
|
||||
for key, val := range jsnRpcConns {
|
||||
if err = cfg.rpcConns[key].loadFromJsonCfg(val); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
|
||||
|
||||
"rpc_conns": {}, // rpc connections definitions
|
||||
|
||||
|
||||
"data_db": { // database used to store runtime data (eg: accounts)
|
||||
"db_type": "*redis", // data_db type: <*redis|*mongo>
|
||||
"db_host": "127.0.0.1", // data_db host address
|
||||
|
||||
@@ -39,7 +39,6 @@ const (
|
||||
FreeSWITCHAgentJSN = "freeswitch_agent"
|
||||
KamailioAgentJSN = "kamailio_agent"
|
||||
AsteriskAgentJSN = "asterisk_agent"
|
||||
OSIPS_JSN = "opensips"
|
||||
DA_JSN = "diameter_agent"
|
||||
RA_JSN = "radius_agent"
|
||||
HttpAgentJson = "http_agent"
|
||||
@@ -60,7 +59,7 @@ const (
|
||||
Apier = "apier"
|
||||
DNSAgentJson = "dns_agent"
|
||||
ERsJson = "ers"
|
||||
RpcConnsJsonName = "rpc_conns"
|
||||
RPCConnsJsonName = "rpc_conns"
|
||||
)
|
||||
|
||||
// Loads the json config out of io.Reader, eg other sources than file, maybe over http
|
||||
@@ -85,13 +84,13 @@ func (self CgrJsonCfg) GeneralJsonCfg() (*GeneralJsonCfg, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) RpcConnJsonCfg() (map[string]*RpcConnsJson, error) {
|
||||
rawCfg, hasKey := self[RpcConnsJsonName]
|
||||
func (self CgrJsonCfg) RPCConnJsonCfg() (map[string]*RPCConnsJson, error) {
|
||||
rawCfg, hasKey := self[RPCConnsJsonName]
|
||||
if !hasKey {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := make(map[string]*RpcConnsJson)
|
||||
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
|
||||
cfg := make(map[string]*RPCConnsJson)
|
||||
if err := json.Unmarshal(*rawCfg, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
|
||||
@@ -23,6 +23,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/rpcclient"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -1910,3 +1912,173 @@ func TestCgrCfgEventReaderDefault(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRpcConnsDefaults(t *testing.T) {
|
||||
eCfg := make(map[string]*RPCConn)
|
||||
// hardoded the *internal and *localhost connections
|
||||
eCfg[utils.MetaInternal] = &RPCConn{
|
||||
Strategy: rpcclient.POOL_FIRST,
|
||||
PoolSize: 0,
|
||||
Conns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
},
|
||||
}
|
||||
eCfg[utils.MetaLocalHost] = &RPCConn{
|
||||
Strategy: rpcclient.POOL_FIRST,
|
||||
PoolSize: 0,
|
||||
Conns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: "127.0.0.1:2012",
|
||||
Transport: utils.MetaJSONrpc,
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(cgrCfg.rpcConns, eCfg) {
|
||||
t.Errorf("received: %+v,\n expecting: %+v", utils.ToJSON(cgrCfg.rpcConns), utils.ToJSON(eCfg))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckConfigSanity(t *testing.T) {
|
||||
// Rater checks
|
||||
cfg, _ := NewDefaultCGRConfig()
|
||||
cfg.ralsCfg = &RalsCfg{
|
||||
Enabled: true,
|
||||
StatSConns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
},
|
||||
}
|
||||
expected := "<Stats> not enabled but requested by <RALs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.statsCfg.Enabled = true
|
||||
cfg.ralsCfg.ThresholdSConns = []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
}
|
||||
expected = "<ThresholdS> not enabled but requested by <RALs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.ralsCfg = &RalsCfg{
|
||||
Enabled: false,
|
||||
StatSConns: []*RemoteHost{},
|
||||
ThresholdSConns: []*RemoteHost{},
|
||||
}
|
||||
// CDRServer checks
|
||||
cfg.thresholdSCfg.Enabled = true
|
||||
cfg.cdrsCfg = &CdrsCfg{
|
||||
Enabled: true,
|
||||
ChargerSConns: []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
},
|
||||
}
|
||||
expected = "<Chargers> not enabled but requested by <CDRs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.chargerSCfg.Enabled = true
|
||||
cfg.cdrsCfg.RaterConns = []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
}
|
||||
expected = "<RALs> not enabled but requested by <CDRs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.ralsCfg.Enabled = true
|
||||
cfg.cdrsCfg.AttributeSConns = []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
}
|
||||
expected = "<AttributeS> not enabled but requested by <CDRs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.statsCfg.Enabled = false
|
||||
cfg.attributeSCfg.Enabled = true
|
||||
cfg.cdrsCfg.StatSConns = []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
}
|
||||
expected = "<StatS> not enabled but requested by <CDRs> component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.statsCfg.Enabled = true
|
||||
cfg.cdrsCfg.OnlineCDRExports = []string{"stringy"}
|
||||
cfg.CdreProfiles = map[string]*CdreCfg{"stringx": &CdreCfg{}}
|
||||
expected = "<CDRs> Cannot find CDR export template with ID: <stringy>"
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.thresholdSCfg.Enabled = false
|
||||
cfg.cdrsCfg.OnlineCDRExports = []string{"stringx"}
|
||||
cfg.cdrsCfg.ThresholdSConns = []*RemoteHost{
|
||||
&RemoteHost{
|
||||
Address: utils.MetaInternal,
|
||||
},
|
||||
}
|
||||
expected = "ThresholdS not enabled but requested by CDRs component."
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
// CDRC sanity checks
|
||||
cfg, _ = NewDefaultCGRConfig()
|
||||
cfg.CdrcProfiles = map[string][]*CdrcCfg{
|
||||
"test": []*CdrcCfg{
|
||||
&CdrcCfg{
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
expected = "<cdrc> Instance: , cdrc enabled but no CDRs defined!"
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
cfg.dispatcherSCfg.Enabled = false
|
||||
cfg.CdrcProfiles = map[string][]*CdrcCfg{
|
||||
"test": []*CdrcCfg{
|
||||
&CdrcCfg{
|
||||
Enabled: true,
|
||||
CdrsConns: []*RemoteHost{
|
||||
&RemoteHost{Address: utils.MetaInternal},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expected = "<CDRs> not enabled but referenced from <cdrc>"
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
|
||||
cfg.CdrcProfiles = map[string][]*CdrcCfg{
|
||||
"test": []*CdrcCfg{
|
||||
&CdrcCfg{
|
||||
Enabled: true,
|
||||
CdrsConns: []*RemoteHost{
|
||||
&RemoteHost{Address: utils.MetaInternal},
|
||||
},
|
||||
ContentFields: []*FCTemplate{},
|
||||
},
|
||||
},
|
||||
}
|
||||
cfg.cdrsCfg = &CdrsCfg{
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
expected = "<cdrc> enabled but no fields to be processed defined!"
|
||||
if err := cfg.checkConfigSanity(); err == nil || err.Error() != expected {
|
||||
t.Errorf("Expecting: %+q received: %+q", expected, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ type FsConnJsonCfg struct {
|
||||
Alias *string
|
||||
}
|
||||
|
||||
type RpcConnsJson struct {
|
||||
type RPCConnsJson struct {
|
||||
Strategy *string
|
||||
PoolSize *int
|
||||
Conns *[]*RemoteHostJson
|
||||
|
||||
81
config/rpcconn.go
Normal file
81
config/rpcconn.go
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
// Returns the first cached default value for a RemoteHost connection
|
||||
func NewDfltRemoteHost() *RemoteHost {
|
||||
if dfltRemoteHost == nil {
|
||||
return new(RemoteHost) // No defaults, most probably we are building the defaults now
|
||||
}
|
||||
dfltVal := *dfltRemoteHost // Copy the value instead of it's pointer
|
||||
return &dfltVal
|
||||
}
|
||||
|
||||
type RPCConn struct {
|
||||
Strategy string
|
||||
PoolSize int
|
||||
Conns []*RemoteHost
|
||||
}
|
||||
|
||||
func (rC *RPCConn) loadFromJsonCfg(jsnCfg *RPCConnsJson) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Strategy != nil {
|
||||
rC.Strategy = *jsnCfg.Strategy
|
||||
}
|
||||
if jsnCfg.PoolSize != nil {
|
||||
rC.PoolSize = *jsnCfg.PoolSize
|
||||
}
|
||||
if jsnCfg.Conns != nil {
|
||||
rC.Conns = make([]*RemoteHost, len(*jsnCfg.Conns))
|
||||
for idx, jsnHaCfg := range *jsnCfg.Conns {
|
||||
rC.Conns[idx] = NewDfltRemoteHost()
|
||||
rC.Conns[idx].loadFromJsonCfg(jsnHaCfg)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// One connection to Rater
|
||||
type RemoteHost struct {
|
||||
Address string
|
||||
Transport string
|
||||
Synchronous bool
|
||||
TLS bool
|
||||
}
|
||||
|
||||
func (self *RemoteHost) loadFromJsonCfg(jsnCfg *RemoteHostJson) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Address != nil {
|
||||
self.Address = *jsnCfg.Address
|
||||
}
|
||||
if jsnCfg.Transport != nil {
|
||||
self.Transport = *jsnCfg.Transport
|
||||
}
|
||||
if jsnCfg.Synchronous != nil {
|
||||
self.Synchronous = *jsnCfg.Synchronous
|
||||
}
|
||||
if jsnCfg.Tls != nil {
|
||||
self.TLS = *jsnCfg.Tls
|
||||
}
|
||||
return nil
|
||||
}
|
||||
19
config/rpcconn_test.go
Normal file
19
config/rpcconn_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
@@ -24,68 +24,6 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// Returns the first cached default value for a FreeSWITCHAgent connection
|
||||
func NewDfltRemoteHost() *RemoteHost {
|
||||
if dfltRemoteHost == nil {
|
||||
return new(RemoteHost) // No defaults, most probably we are building the defaults now
|
||||
}
|
||||
dfltVal := *dfltRemoteHost // Copy the value instead of it's pointer
|
||||
return &dfltVal
|
||||
}
|
||||
|
||||
type RpcConn struct {
|
||||
Strategy string
|
||||
PoolSize int
|
||||
Conns []*RemoteHost
|
||||
}
|
||||
|
||||
func (rC *RpcConn) loadFromJsonCfg(jsnCfg *RpcConnsJson) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return
|
||||
}
|
||||
if jsnCfg.Strategy != nil {
|
||||
rC.Strategy = *jsnCfg.Strategy
|
||||
}
|
||||
if jsnCfg.PoolSize != nil {
|
||||
rC.PoolSize = *jsnCfg.PoolSize
|
||||
}
|
||||
if jsnCfg.Conns != nil {
|
||||
rC.Conns = make([]*RemoteHost, len(*jsnCfg.Conns))
|
||||
for idx, jsnHaCfg := range *jsnCfg.Conns {
|
||||
rC.Conns[idx] = NewDfltRemoteHost()
|
||||
rC.Conns[idx].loadFromJsonCfg(jsnHaCfg)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// One connection to Rater
|
||||
type RemoteHost struct {
|
||||
Address string
|
||||
Transport string
|
||||
Synchronous bool
|
||||
TLS bool
|
||||
}
|
||||
|
||||
func (self *RemoteHost) loadFromJsonCfg(jsnCfg *RemoteHostJson) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Address != nil {
|
||||
self.Address = *jsnCfg.Address
|
||||
}
|
||||
if jsnCfg.Transport != nil {
|
||||
self.Transport = *jsnCfg.Transport
|
||||
}
|
||||
if jsnCfg.Synchronous != nil {
|
||||
self.Synchronous = *jsnCfg.Synchronous
|
||||
}
|
||||
if jsnCfg.Tls != nil {
|
||||
self.TLS = *jsnCfg.Tls
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns the first cached default value for a FreeSWITCHAgent connection
|
||||
func NewDfltFsConnConfig() *FsConnCfg {
|
||||
if dfltFsConnConfig == nil {
|
||||
|
||||
@@ -193,6 +193,7 @@ const (
|
||||
DRYRUN = "dry_run"
|
||||
META_COMBIMED = "*combimed"
|
||||
MetaInternal = "*internal"
|
||||
MetaLocalHost = "*localhost"
|
||||
ZERO_RATING_SUBJECT_PREFIX = "*zero"
|
||||
OK = "OK"
|
||||
MetaFileXML = "*file_xml"
|
||||
|
||||
Reference in New Issue
Block a user