mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
`ClientConnector` is no longer defined within `rpcclient` in its latest
version. It has been changed to be obtained from the `cgrates/birpc`
library instead.
Replaced `net/rpc` with `cgrates/birpc` and `net/rpc/jsonrpc` with
`cgrates/birpc/jsonrpc` libraries.
The implementations of `CallBiRPC()` and `Handlers()` were removed,
along with the methods associated with them.
The `rpcclient.BIRPCConector` and the methods prefixed with `BiRPC` were
removed from the `BiRPClient` interface.
The `BiRPClient` interface was renamed to `BIRPCClient`, although not
sure if needed (seems useful just to test if the structure is correct).
`rpcclient.BiRPCConector` has been replaced with `context.ClientConnector`,
which is now passed alongside `context.Context` within the same struct
(`cgrates/birpc/context.Context`). Consequently, functions that were
previously relying on it are now receiving the context instead. The
changes were made in the following functions:
- `engine/connmanager.go` - `*ConnManager.Call`
- `engine/connmanager.go` - `*ConnManager.getConn`
- `engine/connmanager.go` - `*ConnManager.getConnWithConfig`
- `engine/libengine.go` - `NewRPCPool`
- `engine/libengine.go` - `NewRPCConnection`
- `agents/libagents.go` - `processRequest`
Compilation errors related to the `rpcclient.NewRPCClient` function were
resolved by adding the missing `context`, `max_reconnect_interval`, and
`delayFunc` parameters. Additionally, context was added to all calls made
by the client. An effort was made to avoid passing hardcoded values as
much as possible, and extra flags were added where necessary for cgr
binaries.
The `max_reconnect_interval` parameter is now passed from parent
functions, which required adjustments to the function signature.
A new context field was added to all agent objects to ensure access to
it before sending it to the `connmanager's Call`, effectively replacing
`birpcclient`. Although an alternative would have been to create the
new service and add it to the context right before passing it to the
handlers, the chosen approach is definitely more comfortable.
With the addition of a context field for the SIP servers agents, an
additional error needed to be handled, coming from the creation of the
service. Agent constructors within the services package log errors as
they occur and return. Alternate solutions considered were either
shutting down the engine instead of returning, or just logging the
occurrence as a warning, particularly when the `ctx.Client` isn't
required, especially in cases where bidirectional connections are not
needed. For the latter option, it's crucial to return the object with
the error rather than nil or to make the error nil immediately after
logging.
Context has been integrated into all internal Call implementations to
ensure the objects conform to the `birpc.ClientConnector` interface.
These implementations will be removed in the near future as all service
objects are being wrapped in a `birpc.Service` type that satisfies the
`birpc.ClientConnector` interface. Currently, they are being retained
as a reference in case of any unexpected issues that arise.
Ensured that the `birpc.Service` wrapped service objects are passed to
the internal channel getters rather than the objects themselves.
Add context.TODO() to all \*ConnManager.Call function calls. To be
replaced with the context passed to the Method, when available.
For all `*ConnManager.Call` function calls, `context.TODO()` has been
added. This will be replaced with the context passed to the method when
it becomes available.
The value returned by StringGetOpts is now passed directly to the
FirstNonEmpty function, instead of being assigned to a variable
first.
The implementation of the `*AnalyzerService.GetInternalBiRPCCodec`
function has been removed from the services package. Additionally,
the AnalyzerBiRPCConnector type definition and its associated methods
have been removed.
The codec implementation has been revised to include the following
changes:
- `rpc.ServerCodec` -> `birpc.ServerCodec`;
- `rpc2.ServerCodec` -> `birpc.BirpcCodec`;
- `rpc2.Request` -> `birpc.Request`;
- `rpc2.Response` -> `birpc.Response`;
- The constructors for json and gob birpc codecs in `cenkalti/rpc`
have been replaced with ones from the `birpc/jsonrpc` library;
- The gob codec implementation has been removed in favor of the
version already implemented in the birpc external library.
The server implementation has been updated with the following changes:
- A field that represents a simple RPC server has been added to the
Server struct;
- Both the simple and bidirectional RPC servers are now initialized
inside the Server constructor, eliminating the need for nil checks;
- Usage of `net/rpc` and `cenkalti/rpc2` has been replaced with
`cgrates/birpc`;
- Additional `(Bi)RPCUnregisterName` methods have been added;
- The implementations for (bi)json/gob servers have been somewhat
simplified.
Before deleting the Call functions and using the `birpc.NewService`
method to register the methods for all cgrates components, update the
Call functions to satisfy the `birpc.ClientConnector` interface. This
way it will be a bit safer. Had to be done for SessionS though.
The `BiRPCCall` method has been removed from coreutils.go. The
`RPCCall` and `APIerRPCCall` methods are also to be removed in the
future.
Ensured that all methods for `SessionSv1` and `SessionS` have the
correct function signature with context. The same adjustments were made
for the session dispatcher methods and for the `SessionSv1Interface`.
Also removed sessionsbirpc.go and smgbirpc.go files.
Implemented the following methods to help with the registration of
methods across all subsystems:
- `NewServiceWithName`;
- `NewDispatcherService` for all dispatcher methods;
- `NewService` for the remaining methods that are already named
correctly.
Compared to the constructor from the external library, these also make
sure that the naming of the methods is consistent with our constants.
Added context to the Call methods for the mock client connectors (used
in tests).
Removed unused rpc fields from inside the following services:
- EeS
- LoaderS
- ResourceS
- RouteS
- StatS
- ThresholdS
- SessionS
- CoreS
Updated the methods implementing the logic for API methods to align
with the latest changes, ensuring consistency and correctness. The
modifications include:
- Adjusting the function signature to the new format
(ctx, args, reply).
- Prefixing names with 'V*' to indicate that they are utilized by
or registered as APIs.
- Containing the complete logic within the methods, enabling APIs
to call them and return their reply directly.
The subsystems affected by these changes are detailed as follows:
- CoreS: Additional methods were implementing utilizing the
existing ones. Though modifying them directly was possible, certain
methods (e.g., StopCPUProfiling()) were used elsewhere and not as
RPC requests.
- CDRs: Renamed V1CountCDRs to V1GetCDRsCount.
- StatS: V1GetQueueFloatMetrics, V1GetQueueStringMetrics,
V1GetStatQueue accept different arguments compared to API functions
(opted to register StatSv1 instead).
- ResourceS: Renamed V1ResourcesForEvent to V1GetResourcesForEvent
to align with API naming.
- DispatcherS: Renamed V1GetProfilesForEvent to
DispatcherSv1GetProfilesForEvent.
- For the rest, adding context to the function signature was enough.
In the unit tests, wrapping the object within a biprc.Service is now
ensured before passing it to the internal connections map under the
corresponding key.
Some tests that are covering error cases, are also checking the other
return value besides the error. That check has been removed since it
is redundant.
Revised the RPC/BiRPC clients' constructors (for use in tests)
A different approach has been chosen for the handling of ping methods
within subsystems. Instead of defining the same structure in every file,
the ping methods were added inside the Service constructor function.
Though the existing Ping methods were left as they were, they will be
removed in the future.
An additional method has been implemented to register the Ping method
from outside of the engine package.
Implemented Sleep and CapsError methods for SessionS (before they were
exclusively for bidirectional use, I believe).
A specific issue has been fixed within the CapsError SessionSv1 API
implementation, which is designed to overwrite methods that cannot be
allocated due to the threshold limit being reached. Previously, it was
deallocating when writing the response, even when a spot hadn't been
allocated in the first place (due to the cap being hit). The reason
behind this, especially why the test was passing before, still needs
to be looked into, as the problem should have occurred from before.
Implement `*SessionSv1.RegisterInternalBiJSONConn` method in apier.
All agent methods have been registered under the SessionSv1 name. For
the correct method names, the leading "V1" prefix has been trimmed
using the `birpc.NewServiceWithMethodsRename` function.
Revise the RegisterRpcParams function to populate the parameters
while relying on the `*birpc.Service` type instead. This will
automatically also deal with the validation. At the moment,
any error encountered is logged without being returned. Might
be changed in the future.
Inside the cgrRPCAction function, `mapstructure.Decode`'s output parameter
is now guaranteed to always be a pointer.
Updated go.mod and go.sum.
Fixed some typos.
2027 lines
64 KiB
Go
2027 lines
64 KiB
Go
/*
|
|
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
|
Copyright (C) ITsysCOM GmbH
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/rpcclient"
|
|
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
var (
|
|
dbDefaultsCfg dbDefaults
|
|
cgrCfg *CGRConfig // will be shared
|
|
dfltFsConnConfig *FsConnCfg // Default FreeSWITCH Connection configuration, built out of json default configuration
|
|
dfltKamConnConfig *KamConnCfg // Default Kamailio Connection configuration
|
|
dfltRemoteHost *RemoteHost
|
|
dfltAstConnCfg *AsteriskConnCfg
|
|
dfltLoaderConfig *LoaderSCfg
|
|
)
|
|
|
|
func newDbDefaults() dbDefaults {
|
|
deflt := dbDefaults{
|
|
utils.MetaMySQL: map[string]string{
|
|
"DbName": "cgrates",
|
|
"DbPort": "3306",
|
|
},
|
|
utils.MetaPostgres: map[string]string{
|
|
"DbName": "cgrates",
|
|
"DbPort": "5432",
|
|
},
|
|
utils.MetaMongo: map[string]string{
|
|
"DbName": "cgrates",
|
|
"DbPort": "27017",
|
|
},
|
|
utils.MetaRedis: map[string]string{
|
|
"DbName": "10",
|
|
"DbPort": "6379",
|
|
},
|
|
utils.MetaInternal: map[string]string{
|
|
"DbName": "internal",
|
|
"DbPort": "internal",
|
|
},
|
|
}
|
|
return deflt
|
|
}
|
|
|
|
type dbDefaults map[string]map[string]string
|
|
|
|
func (dbDflt dbDefaults) dbName(dbType string, flagInput string) string {
|
|
if flagInput != utils.MetaDynamic {
|
|
return flagInput
|
|
}
|
|
return dbDflt[dbType]["DbName"]
|
|
}
|
|
|
|
func (dbDflt dbDefaults) dbPort(dbType string, flagInput string) string {
|
|
if flagInput != utils.MetaDynamic {
|
|
return flagInput
|
|
}
|
|
return dbDflt[dbType]["DbPort"]
|
|
}
|
|
|
|
func init() {
|
|
cgrCfg = NewDefaultCGRConfig()
|
|
dbDefaultsCfg = newDbDefaults()
|
|
}
|
|
|
|
// CgrConfig is used to retrieve system configuration from other packages
|
|
func CgrConfig() *CGRConfig {
|
|
return cgrCfg
|
|
}
|
|
|
|
// SetCgrConfig is used to set system configuration from other places
|
|
func SetCgrConfig(cfg *CGRConfig) {
|
|
cgrCfg = cfg
|
|
}
|
|
|
|
// NewDefaultCGRConfig returns the default configuration
|
|
func NewDefaultCGRConfig() (cfg *CGRConfig) {
|
|
cfg, _ = newCGRConfig([]byte(CGRATES_CFG_JSON))
|
|
return
|
|
}
|
|
|
|
func newCGRConfig(config []byte) (cfg *CGRConfig, err error) {
|
|
cfg = new(CGRConfig)
|
|
cfg.initChanels()
|
|
cfg.DataFolderPath = "/usr/share/cgrates/"
|
|
|
|
cfg.rpcConns = make(map[string]*RPCConn)
|
|
cfg.templates = make(map[string][]*FCTemplate)
|
|
cfg.generalCfg = new(GeneralCfg)
|
|
cfg.generalCfg.NodeID = utils.UUIDSha1Prefix()
|
|
cfg.dataDbCfg = new(DataDbCfg)
|
|
cfg.dataDbCfg.Items = make(map[string]*ItemOpt)
|
|
cfg.dataDbCfg.Opts = &DataDBOpts{}
|
|
cfg.storDbCfg = new(StorDbCfg)
|
|
cfg.storDbCfg.Items = make(map[string]*ItemOpt)
|
|
cfg.storDbCfg.Opts = &StorDBOpts{}
|
|
cfg.tlsCfg = new(TLSCfg)
|
|
cfg.cacheCfg = new(CacheCfg)
|
|
cfg.cacheCfg.Partitions = make(map[string]*CacheParamCfg)
|
|
cfg.listenCfg = new(ListenCfg)
|
|
cfg.httpCfg = new(HTTPCfg)
|
|
cfg.httpCfg.dialer = &net.Dialer{}
|
|
cfg.httpCfg.ClientOpts = &http.Transport{}
|
|
cfg.filterSCfg = new(FilterSCfg)
|
|
cfg.ralsCfg = new(RalsCfg)
|
|
cfg.ralsCfg.MaxComputedUsage = make(map[string]time.Duration)
|
|
cfg.ralsCfg.BalanceRatingSubject = make(map[string]string)
|
|
cfg.schedulerCfg = new(SchedulerCfg)
|
|
cfg.cdrsCfg = new(CdrsCfg)
|
|
cfg.analyzerSCfg = new(AnalyzerSCfg)
|
|
cfg.sessionSCfg = new(SessionSCfg)
|
|
cfg.sessionSCfg.STIRCfg = new(STIRcfg)
|
|
cfg.sessionSCfg.DefaultUsage = make(map[string]time.Duration)
|
|
cfg.fsAgentCfg = new(FsAgentCfg)
|
|
cfg.kamAgentCfg = new(KamAgentCfg)
|
|
cfg.asteriskAgentCfg = new(AsteriskAgentCfg)
|
|
cfg.diameterAgentCfg = new(DiameterAgentCfg)
|
|
cfg.radiusAgentCfg = new(RadiusAgentCfg)
|
|
cfg.dnsAgentCfg = new(DNSAgentCfg)
|
|
cfg.attributeSCfg = &AttributeSCfg{Opts: &AttributesOpts{}}
|
|
cfg.chargerSCfg = new(ChargerSCfg)
|
|
cfg.resourceSCfg = &ResourceSConfig{Opts: &ResourcesOpts{}}
|
|
cfg.statsCfg = &StatSCfg{Opts: &StatsOpts{}}
|
|
cfg.thresholdSCfg = &ThresholdSCfg{Opts: &ThresholdsOpts{}}
|
|
cfg.routeSCfg = &RouteSCfg{Opts: &RoutesOpts{}}
|
|
cfg.sureTaxCfg = new(SureTaxCfg)
|
|
cfg.dispatcherSCfg = new(DispatcherSCfg)
|
|
cfg.registrarCCfg = new(RegistrarCCfgs)
|
|
cfg.registrarCCfg.RPC = new(RegistrarCCfg)
|
|
cfg.registrarCCfg.Dispatchers = new(RegistrarCCfg)
|
|
cfg.registrarCCfg.RPC.Hosts = make(map[string][]*RemoteHost)
|
|
cfg.registrarCCfg.Dispatchers.Hosts = make(map[string][]*RemoteHost)
|
|
cfg.loaderCgrCfg = new(LoaderCgrCfg)
|
|
cfg.migratorCgrCfg = new(MigratorCgrCfg)
|
|
cfg.migratorCgrCfg.OutDataDBOpts = &DataDBOpts{}
|
|
cfg.migratorCgrCfg.OutStorDBOpts = &StorDBOpts{}
|
|
cfg.mailerCfg = new(MailerCfg)
|
|
cfg.loaderCfg = make(LoaderSCfgs, 0)
|
|
cfg.apier = new(ApierCfg)
|
|
cfg.ersCfg = new(ERsCfg)
|
|
cfg.eesCfg = new(EEsCfg)
|
|
cfg.eesCfg.Cache = make(map[string]*CacheParamCfg)
|
|
cfg.sipAgentCfg = new(SIPAgentCfg)
|
|
cfg.configSCfg = new(ConfigSCfg)
|
|
cfg.apiBanCfg = new(APIBanCfg)
|
|
cfg.sentryPeerCfg = new(SentryPeerCfg)
|
|
cfg.coreSCfg = new(CoreSCfg)
|
|
cfg.dfltEvExp = &EventExporterCfg{Opts: &EventExporterOpts{
|
|
Els: new(ElsOpts),
|
|
SQL: new(SQLOpts),
|
|
AMQP: new(AMQPOpts),
|
|
AWS: new(AWSOpts),
|
|
NATS: new(NATSOpts),
|
|
RPC: new(RPCOpts),
|
|
Kafka: new(KafkaOpts),
|
|
}}
|
|
cfg.dfltEvRdr = &EventReaderCfg{Opts: &EventReaderOpts{
|
|
SQLOpts: new(SQLROpts),
|
|
CSVOpts: new(CSVROpts),
|
|
AWSOpts: new(AWSROpts),
|
|
AMQPOpts: new(AMQPROpts),
|
|
KafkaOpts: new(KafkaROpts),
|
|
NATSOpts: new(NATSROpts),
|
|
}}
|
|
|
|
cfg.cacheDP = make(map[string]utils.MapStorage)
|
|
|
|
var cgrJSONCfg *CgrJsonCfg
|
|
if cgrJSONCfg, err = NewCgrJsonCfgFromBytes(config); err != nil {
|
|
return
|
|
}
|
|
if err = cfg.loadFromJSONCfg(cgrJSONCfg); err != nil {
|
|
return
|
|
}
|
|
|
|
// populate default ERs reader
|
|
for _, ersRdr := range cfg.ersCfg.Readers {
|
|
if ersRdr.ID == utils.MetaDefault {
|
|
cfg.dfltEvRdr = ersRdr.Clone()
|
|
break
|
|
}
|
|
}
|
|
// populate default EEs exporter
|
|
for _, ersExp := range cfg.eesCfg.Exporters {
|
|
if ersExp.ID == utils.MetaDefault {
|
|
cfg.dfltEvExp = ersExp.Clone()
|
|
break
|
|
}
|
|
}
|
|
dfltFsConnConfig = cfg.fsAgentCfg.EventSocketConns[0] // We leave it crashing here on purpose if no Connection defaults defined
|
|
dfltKamConnConfig = cfg.kamAgentCfg.EvapiConns[0]
|
|
dfltAstConnCfg = cfg.asteriskAgentCfg.AsteriskConns[0]
|
|
dfltLoaderConfig = cfg.loaderCfg[0].Clone()
|
|
dfltRemoteHost = new(RemoteHost)
|
|
*dfltRemoteHost = *cfg.rpcConns[utils.MetaLocalHost].Conns[0]
|
|
err = cfg.checkConfigSanity()
|
|
return
|
|
}
|
|
|
|
// NewCGRConfigFromJSONStringWithDefaults returns the given config with the default option loaded
|
|
func NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr string) (cfg *CGRConfig, err error) {
|
|
cfg = NewDefaultCGRConfig()
|
|
jsnCfg := new(CgrJsonCfg)
|
|
if err = NewRjReaderFromBytes([]byte(cfgJSONStr)).Decode(jsnCfg); err != nil {
|
|
return
|
|
} else if err = cfg.loadFromJSONCfg(jsnCfg); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// NewCGRConfigFromPath reads all json files out of a folder/subfolders and loads them up in lexical order
|
|
func NewCGRConfigFromPath(path string) (cfg *CGRConfig, err error) {
|
|
cfg = NewDefaultCGRConfig()
|
|
cfg.ConfigPath = path
|
|
|
|
if err = cfg.loadConfigFromPath(path, []func(*CgrJsonCfg) error{cfg.loadFromJSONCfg}, false); err != nil {
|
|
return
|
|
}
|
|
err = cfg.checkConfigSanity()
|
|
return
|
|
}
|
|
|
|
// newCGRConfigFromPathWithoutEnv reads all json files out of a folder/subfolders and loads them up in lexical order
|
|
// it will not read *env variables and will not checkConfigSanity as it is not needed for configs
|
|
func newCGRConfigFromPathWithoutEnv(path string) (cfg *CGRConfig, err error) {
|
|
cfg = NewDefaultCGRConfig()
|
|
cfg.ConfigPath = path
|
|
|
|
err = cfg.loadConfigFromPath(path, []func(*CgrJsonCfg) error{cfg.loadFromJSONCfg}, true)
|
|
return
|
|
}
|
|
|
|
func isHidden(fileName string) bool {
|
|
if fileName == "." || fileName == ".." {
|
|
return false
|
|
}
|
|
return strings.HasPrefix(fileName, ".")
|
|
}
|
|
|
|
// CGRConfig holds system configuration, defaults are overwritten with values from config file if found
|
|
type CGRConfig struct {
|
|
lks map[string]*sync.RWMutex
|
|
DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options
|
|
ConfigPath string // Path towards config
|
|
|
|
// Cache defaults loaded from json and needing clones
|
|
dfltEvRdr *EventReaderCfg // default event reader
|
|
dfltEvExp *EventExporterCfg // default event exporter
|
|
|
|
loaderCfg LoaderSCfgs // LoaderS configs
|
|
httpAgentCfg HTTPAgentCfgs // HttpAgent configs
|
|
|
|
rldChans map[string]chan struct{} // index here the channels used for reloads
|
|
|
|
rpcConns RPCConns
|
|
|
|
templates FcTemplates
|
|
|
|
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
|
|
sessionSCfg *SessionSCfg // SessionS config
|
|
fsAgentCfg *FsAgentCfg // FreeSWITCHAgent config
|
|
kamAgentCfg *KamAgentCfg // KamailioAgent config
|
|
asteriskAgentCfg *AsteriskAgentCfg // AsteriskAgent config
|
|
diameterAgentCfg *DiameterAgentCfg // DiameterAgent config
|
|
radiusAgentCfg *RadiusAgentCfg // RadiusAgent config
|
|
dnsAgentCfg *DNSAgentCfg // DNSAgent config
|
|
attributeSCfg *AttributeSCfg // AttributeS config
|
|
chargerSCfg *ChargerSCfg // ChargerS config
|
|
resourceSCfg *ResourceSConfig // ResourceS config
|
|
statsCfg *StatSCfg // StatS config
|
|
thresholdSCfg *ThresholdSCfg // ThresholdS config
|
|
routeSCfg *RouteSCfg // RouteS config
|
|
sureTaxCfg *SureTaxCfg // SureTax config
|
|
dispatcherSCfg *DispatcherSCfg // DispatcherS config
|
|
registrarCCfg *RegistrarCCfgs // RegistrarC config
|
|
loaderCgrCfg *LoaderCgrCfg // LoaderCgr config
|
|
migratorCgrCfg *MigratorCgrCfg // MigratorCgr config
|
|
mailerCfg *MailerCfg // Mailer config
|
|
analyzerSCfg *AnalyzerSCfg // AnalyzerS config
|
|
apier *ApierCfg // APIer config
|
|
ersCfg *ERsCfg // EventReader config
|
|
eesCfg *EEsCfg // EventExporter config
|
|
sipAgentCfg *SIPAgentCfg // SIPAgent config
|
|
configSCfg *ConfigSCfg // ConfigS config
|
|
apiBanCfg *APIBanCfg // APIBan config
|
|
sentryPeerCfg *SentryPeerCfg //SentryPeer config
|
|
coreSCfg *CoreSCfg // CoreS config
|
|
|
|
cacheDP map[string]utils.MapStorage
|
|
cacheDPMux sync.RWMutex
|
|
}
|
|
|
|
var posibleLoaderTypes = utils.NewStringSet([]string{utils.MetaAttributes,
|
|
utils.MetaResources, utils.MetaFilters, utils.MetaStats,
|
|
utils.MetaRoutes, utils.MetaThresholds, utils.MetaChargers,
|
|
utils.MetaDispatchers, utils.MetaDispatcherHosts})
|
|
|
|
var possibleReaderTypes = utils.NewStringSet([]string{utils.MetaFileCSV,
|
|
utils.MetaKafkajsonMap, utils.MetaFileXML, utils.MetaSQL, utils.MetaFileFWV,
|
|
utils.MetaFileJSON, utils.MetaNone, utils.MetaAMQPjsonMap, utils.MetaS3jsonMap,
|
|
utils.MetaSQSjsonMap, utils.MetaAMQPV1jsonMap, utils.MetaNatsjsonMap})
|
|
|
|
var possibleExporterTypes = utils.NewStringSet([]string{utils.MetaFileCSV, utils.MetaNone, utils.MetaFileFWV,
|
|
utils.MetaHTTPPost, utils.MetaHTTPjsonMap, utils.MetaAMQPjsonMap, utils.MetaAMQPV1jsonMap, utils.MetaSQSjsonMap,
|
|
utils.MetaKafkajsonMap, utils.MetaS3jsonMap, utils.MetaElastic, utils.MetaVirt, utils.MetaSQL, utils.MetaNatsjsonMap,
|
|
utils.MetaLog, utils.MetaRPC})
|
|
|
|
// LazySanityCheck used after check config sanity to display warnings related to the config
|
|
func (cfg *CGRConfig) LazySanityCheck() {
|
|
for _, expID := range cfg.cdrsCfg.OnlineCDRExports {
|
|
for _, ee := range cfg.eesCfg.Exporters {
|
|
if ee.ID == expID && ee.Type == utils.MetaS3jsonMap || ee.Type == utils.MetaSQSjsonMap {
|
|
poster := utils.SQSPoster
|
|
if ee.Type == utils.MetaS3jsonMap {
|
|
poster = utils.S3Poster
|
|
}
|
|
argsMap := utils.GetUrlRawArguments(ee.ExportPath)
|
|
for _, arg := range []string{utils.AWSRegion, utils.AWSKey, utils.AWSSecret} {
|
|
if _, has := argsMap[arg]; !has {
|
|
utils.Logger.Warning(fmt.Sprintf("<%s> No %s present for AWS for exporter with ID : <%s>.", poster, arg, ee.ID))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for _, exporter := range cfg.eesCfg.Exporters {
|
|
if exporter.Type == utils.MetaS3jsonMap || exporter.Type == utils.MetaSQSjsonMap {
|
|
poster := utils.SQSPoster
|
|
if exporter.Type == utils.MetaS3jsonMap {
|
|
poster = utils.S3Poster
|
|
}
|
|
argsMap := utils.GetUrlRawArguments(exporter.ExportPath)
|
|
for _, arg := range []string{utils.AWSRegion, utils.AWSKey, utils.AWSSecret} {
|
|
if _, has := argsMap[arg]; !has {
|
|
utils.Logger.Warning(fmt.Sprintf("<%s> No %s present for AWS for exporter with ID: <%s>.", poster, arg, exporter.ID))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Loads from json configuration object, will be used for defaults, config from file and reload, might need lock
|
|
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.loadGeneralCfg, cfg.loadTemplateSCfg, cfg.loadCacheCfg, cfg.loadListenCfg,
|
|
cfg.loadHTTPCfg, cfg.loadDataDBCfg, cfg.loadStorDBCfg,
|
|
cfg.loadFilterSCfg, cfg.loadRalSCfg, cfg.loadSchedulerCfg,
|
|
cfg.loadCdrsCfg, cfg.loadSessionSCfg,
|
|
cfg.loadFreeswitchAgentCfg, cfg.loadKamAgentCfg,
|
|
cfg.loadAsteriskAgentCfg, cfg.loadDiameterAgentCfg, cfg.loadRadiusAgentCfg,
|
|
cfg.loadDNSAgentCfg, cfg.loadHTTPAgentCfg, cfg.loadAttributeSCfg,
|
|
cfg.loadChargerSCfg, cfg.loadResourceSCfg, cfg.loadStatSCfg,
|
|
cfg.loadThresholdSCfg, cfg.loadRouteSCfg, cfg.loadLoaderSCfg,
|
|
cfg.loadMailerCfg, cfg.loadSureTaxCfg, cfg.loadDispatcherSCfg,
|
|
cfg.loadLoaderCgrCfg, cfg.loadMigratorCgrCfg, cfg.loadTLSCgrCfg,
|
|
cfg.loadAnalyzerCgrCfg, cfg.loadApierCfg, cfg.loadErsCfg, cfg.loadEesCfg,
|
|
cfg.loadSIPAgentCfg, cfg.loadRegistrarCCfg,
|
|
cfg.loadConfigSCfg, cfg.loadAPIBanCgrCfg, cfg.loadSentryPeerCgrCfg, cfg.loadCoreSCfg} {
|
|
if err = loadFunc(jsnCfg); err != nil {
|
|
return
|
|
}
|
|
}
|
|
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 connection
|
|
cfg.rpcConns[utils.MetaInternal] = &RPCConn{
|
|
Strategy: rpcclient.PoolFirst,
|
|
PoolSize: 0,
|
|
Conns: []*RemoteHost{{
|
|
Address: utils.MetaInternal,
|
|
}},
|
|
}
|
|
cfg.rpcConns[rpcclient.BiRPCInternal] = &RPCConn{
|
|
Strategy: rpcclient.PoolFirst,
|
|
PoolSize: 0,
|
|
Conns: []*RemoteHost{{
|
|
Address: rpcclient.BiRPCInternal,
|
|
}},
|
|
}
|
|
cfg.rpcConns[utils.MetaLocalHost] = &RPCConn{
|
|
Strategy: rpcclient.PoolFirst,
|
|
PoolSize: 0,
|
|
Conns: []*RemoteHost{{
|
|
Address: "127.0.0.1:2012",
|
|
Transport: utils.MetaJSON,
|
|
}},
|
|
}
|
|
cfg.rpcConns[utils.MetaBiJSONLocalHost] = &RPCConn{
|
|
Strategy: rpcclient.PoolFirst,
|
|
PoolSize: 0,
|
|
Conns: []*RemoteHost{{
|
|
Address: "127.0.0.1:2014",
|
|
Transport: rpcclient.BiRPCJSON,
|
|
}},
|
|
}
|
|
for key, val := range jsnRPCConns {
|
|
cfg.rpcConns[key] = NewDfltRPCConn()
|
|
cfg.rpcConns[key].loadFromJSONCfg(val)
|
|
}
|
|
return
|
|
}
|
|
|
|
// loadGeneralCfg loads the General section of the configuration
|
|
func (cfg *CGRConfig) loadGeneralCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnGeneralCfg *GeneralJsonCfg
|
|
if jsnGeneralCfg, err = jsnCfg.GeneralJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.generalCfg.loadFromJSONCfg(jsnGeneralCfg)
|
|
}
|
|
|
|
// loadCacheCfg loads the Cache section of the configuration
|
|
func (cfg *CGRConfig) loadCacheCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnCacheCfg *CacheJsonCfg
|
|
if jsnCacheCfg, err = jsnCfg.CacheJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.cacheCfg.loadFromJSONCfg(jsnCacheCfg)
|
|
}
|
|
|
|
// loadListenCfg loads the Listen section of the configuration
|
|
func (cfg *CGRConfig) loadListenCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnListenCfg *ListenJsonCfg
|
|
if jsnListenCfg, err = jsnCfg.ListenJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.listenCfg.loadFromJSONCfg(jsnListenCfg)
|
|
}
|
|
|
|
// loadHTTPCfg loads the Http section of the configuration
|
|
func (cfg *CGRConfig) loadHTTPCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnHTTPCfg *HTTPJsonCfg
|
|
if jsnHTTPCfg, err = jsnCfg.HttpJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.httpCfg.loadFromJSONCfg(jsnHTTPCfg)
|
|
}
|
|
|
|
// loadDataDBCfg loads the DataDB section of the configuration
|
|
func (cfg *CGRConfig) loadDataDBCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnDataDbCfg *DbJsonCfg
|
|
if jsnDataDbCfg, err = jsnCfg.DbJsonCfg(DATADB_JSN); err != nil {
|
|
return
|
|
}
|
|
if err = cfg.dataDbCfg.loadFromJSONCfg(jsnDataDbCfg); err != nil {
|
|
return
|
|
}
|
|
// in case of internalDB we need to disable the cache
|
|
// so we enforce it here
|
|
if cfg.dataDbCfg.Type == utils.MetaInternal {
|
|
// overwrite only DataDBPartitions and leave other unmodified ( e.g. *diameter_messages, *closed_sessions, etc... )
|
|
for key := range utils.DataDBPartitions {
|
|
if _, has := cfg.cacheCfg.Partitions[key]; has {
|
|
cfg.cacheCfg.Partitions[key] = &CacheParamCfg{}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
|
|
}
|
|
|
|
// loadStorDBCfg loads the StorDB section of the configuration
|
|
func (cfg *CGRConfig) loadStorDBCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnDataDbCfg *DbJsonCfg
|
|
if jsnDataDbCfg, err = jsnCfg.DbJsonCfg(STORDB_JSN); err != nil {
|
|
return
|
|
}
|
|
return cfg.storDbCfg.loadFromJSONCfg(jsnDataDbCfg)
|
|
}
|
|
|
|
// loadFilterSCfg loads the FilterS section of the configuration
|
|
func (cfg *CGRConfig) loadFilterSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnFilterSCfg *FilterSJsonCfg
|
|
if jsnFilterSCfg, err = jsnCfg.FilterSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.filterSCfg.loadFromJSONCfg(jsnFilterSCfg)
|
|
}
|
|
|
|
// loadRalSCfg loads the RalS section of the configuration
|
|
func (cfg *CGRConfig) loadRalSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnRALsCfg *RalsJsonCfg
|
|
if jsnRALsCfg, err = jsnCfg.RalsJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.ralsCfg.loadFromJSONCfg(jsnRALsCfg)
|
|
}
|
|
|
|
// loadSchedulerCfg loads the Scheduler section of the configuration
|
|
func (cfg *CGRConfig) loadSchedulerCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSchedCfg *SchedulerJsonCfg
|
|
if jsnSchedCfg, err = jsnCfg.SchedulerJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.schedulerCfg.loadFromJSONCfg(jsnSchedCfg)
|
|
}
|
|
|
|
// loadCdrsCfg loads the Cdrs section of the configuration
|
|
func (cfg *CGRConfig) loadCdrsCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnCdrsCfg *CdrsJsonCfg
|
|
if jsnCdrsCfg, err = jsnCfg.CdrsJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.cdrsCfg.loadFromJSONCfg(jsnCdrsCfg)
|
|
}
|
|
|
|
// loadSessionSCfg loads the SessionS section of the configuration
|
|
func (cfg *CGRConfig) loadSessionSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSessionSCfg *SessionSJsonCfg
|
|
if jsnSessionSCfg, err = jsnCfg.SessionSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.sessionSCfg.loadFromJSONCfg(jsnSessionSCfg)
|
|
}
|
|
|
|
// loadFreeswitchAgentCfg loads the FreeswitchAgent section of the configuration
|
|
func (cfg *CGRConfig) loadFreeswitchAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSmFsCfg *FreeswitchAgentJsonCfg
|
|
if jsnSmFsCfg, err = jsnCfg.FreeswitchAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.fsAgentCfg.loadFromJSONCfg(jsnSmFsCfg)
|
|
}
|
|
|
|
// loadKamAgentCfg loads the KamAgent section of the configuration
|
|
func (cfg *CGRConfig) loadKamAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnKamAgentCfg *KamAgentJsonCfg
|
|
if jsnKamAgentCfg, err = jsnCfg.KamAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.kamAgentCfg.loadFromJSONCfg(jsnKamAgentCfg)
|
|
}
|
|
|
|
// loadAsteriskAgentCfg loads the AsteriskAgent section of the configuration
|
|
func (cfg *CGRConfig) loadAsteriskAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSMAstCfg *AsteriskAgentJsonCfg
|
|
if jsnSMAstCfg, err = jsnCfg.AsteriskAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.asteriskAgentCfg.loadFromJSONCfg(jsnSMAstCfg)
|
|
}
|
|
|
|
// loadDiameterAgentCfg loads the DiameterAgent section of the configuration
|
|
func (cfg *CGRConfig) loadDiameterAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnDACfg *DiameterAgentJsonCfg
|
|
if jsnDACfg, err = jsnCfg.DiameterAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.diameterAgentCfg.loadFromJSONCfg(jsnDACfg, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadRadiusAgentCfg loads the RadiusAgent section of the configuration
|
|
func (cfg *CGRConfig) loadRadiusAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnRACfg *RadiusAgentJsonCfg
|
|
if jsnRACfg, err = jsnCfg.RadiusAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.radiusAgentCfg.loadFromJSONCfg(jsnRACfg, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadDNSAgentCfg loads the DNSAgent section of the configuration
|
|
func (cfg *CGRConfig) loadDNSAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnDNSCfg *DNSAgentJsonCfg
|
|
if jsnDNSCfg, err = jsnCfg.DNSAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.dnsAgentCfg.loadFromJSONCfg(jsnDNSCfg, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadHTTPAgentCfg loads the HttpAgent section of the configuration
|
|
func (cfg *CGRConfig) loadHTTPAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnHTTPAgntCfg *[]*HttpAgentJsonCfg
|
|
if jsnHTTPAgntCfg, err = jsnCfg.HttpAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.httpAgentCfg.loadFromJSONCfg(jsnHTTPAgntCfg, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadAttributeSCfg loads the AttributeS section of the configuration
|
|
func (cfg *CGRConfig) loadAttributeSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnAttributeSCfg *AttributeSJsonCfg
|
|
if jsnAttributeSCfg, err = jsnCfg.AttributeServJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.attributeSCfg.loadFromJSONCfg(jsnAttributeSCfg)
|
|
}
|
|
|
|
// loadChargerSCfg loads the ChargerS section of the configuration
|
|
func (cfg *CGRConfig) loadChargerSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnChargerSCfg *ChargerSJsonCfg
|
|
if jsnChargerSCfg, err = jsnCfg.ChargerServJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.chargerSCfg.loadFromJSONCfg(jsnChargerSCfg)
|
|
}
|
|
|
|
// loadResourceSCfg loads the ResourceS section of the configuration
|
|
func (cfg *CGRConfig) loadResourceSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnRLSCfg *ResourceSJsonCfg
|
|
if jsnRLSCfg, err = jsnCfg.ResourceSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.resourceSCfg.loadFromJSONCfg(jsnRLSCfg)
|
|
}
|
|
|
|
// loadStatSCfg loads the StatS section of the configuration
|
|
func (cfg *CGRConfig) loadStatSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnStatSCfg *StatServJsonCfg
|
|
if jsnStatSCfg, err = jsnCfg.StatSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.statsCfg.loadFromJSONCfg(jsnStatSCfg)
|
|
}
|
|
|
|
// loadThresholdSCfg loads the ThresholdS section of the configuration
|
|
func (cfg *CGRConfig) loadThresholdSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnThresholdSCfg *ThresholdSJsonCfg
|
|
if jsnThresholdSCfg, err = jsnCfg.ThresholdSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.thresholdSCfg.loadFromJSONCfg(jsnThresholdSCfg)
|
|
}
|
|
|
|
// loadRouteSCfg loads the RouteS section of the configuration
|
|
func (cfg *CGRConfig) loadRouteSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnRouteSCfg *RouteSJsonCfg
|
|
if jsnRouteSCfg, err = jsnCfg.RouteSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.routeSCfg.loadFromJSONCfg(jsnRouteSCfg)
|
|
}
|
|
|
|
// loadLoaderSCfg loads the LoaderS section of the configuration
|
|
func (cfg *CGRConfig) loadLoaderSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnLoaderCfg []*LoaderJsonCfg
|
|
if jsnLoaderCfg, err = jsnCfg.LoaderJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
// cfg.loaderCfg = make(LoaderSCfgs, len(jsnLoaderCfg))
|
|
for _, profile := range jsnLoaderCfg {
|
|
loadSCfgp := NewDfltLoaderSCfg()
|
|
if err = loadSCfgp.loadFromJSONCfg(profile, cfg.templates, cfg.generalCfg.RSRSep); err != nil {
|
|
return
|
|
}
|
|
cfg.loaderCfg = append(cfg.loaderCfg, loadSCfgp) // use append so the loaderS profile to be loaded from multiple files
|
|
}
|
|
return
|
|
}
|
|
|
|
// loadMailerCfg loads the Mailer section of the configuration
|
|
func (cfg *CGRConfig) loadMailerCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnMailerCfg *MailerJsonCfg
|
|
if jsnMailerCfg, err = jsnCfg.MailerJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.mailerCfg.loadFromJSONCfg(jsnMailerCfg)
|
|
}
|
|
|
|
// loadSureTaxCfg loads the SureTax section of the configuration
|
|
func (cfg *CGRConfig) loadSureTaxCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSureTaxCfg *SureTaxJsonCfg
|
|
if jsnSureTaxCfg, err = jsnCfg.SureTaxJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.sureTaxCfg.loadFromJSONCfg(jsnSureTaxCfg)
|
|
}
|
|
|
|
// loadDispatcherSCfg loads the DispatcherS section of the configuration
|
|
func (cfg *CGRConfig) loadDispatcherSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnDispatcherSCfg *DispatcherSJsonCfg
|
|
if jsnDispatcherSCfg, err = jsnCfg.DispatcherSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.dispatcherSCfg.loadFromJSONCfg(jsnDispatcherSCfg)
|
|
}
|
|
|
|
// loadRegistrarCCfg loads the RegistrarC section of the configuration
|
|
func (cfg *CGRConfig) loadRegistrarCCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnRegistrarCCfg *RegistrarCJsonCfgs
|
|
if jsnRegistrarCCfg, err = jsnCfg.RegistrarCJsonCfgs(); err != nil {
|
|
return
|
|
}
|
|
return cfg.registrarCCfg.loadFromJSONCfg(jsnRegistrarCCfg)
|
|
}
|
|
|
|
// loadLoaderCgrCfg loads the Loader section of the configuration
|
|
func (cfg *CGRConfig) loadLoaderCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnLoaderCgrCfg *LoaderCfgJson
|
|
if jsnLoaderCgrCfg, err = jsnCfg.LoaderCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.loaderCgrCfg.loadFromJSONCfg(jsnLoaderCgrCfg)
|
|
}
|
|
|
|
// loadMigratorCgrCfg loads the Migrator section of the configuration
|
|
func (cfg *CGRConfig) loadMigratorCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnMigratorCgrCfg *MigratorCfgJson
|
|
if jsnMigratorCgrCfg, err = jsnCfg.MigratorCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.migratorCgrCfg.loadFromJSONCfg(jsnMigratorCgrCfg)
|
|
}
|
|
|
|
// loadTLSCgrCfg loads the Tls section of the configuration
|
|
func (cfg *CGRConfig) loadTLSCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnTLSCgrCfg *TlsJsonCfg
|
|
if jsnTLSCgrCfg, err = jsnCfg.TlsCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.tlsCfg.loadFromJSONCfg(jsnTLSCgrCfg)
|
|
}
|
|
|
|
// loadAnalyzerCgrCfg loads the Analyzer section of the configuration
|
|
func (cfg *CGRConfig) loadAnalyzerCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnAnalyzerCgrCfg *AnalyzerSJsonCfg
|
|
if jsnAnalyzerCgrCfg, err = jsnCfg.AnalyzerCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.analyzerSCfg.loadFromJSONCfg(jsnAnalyzerCgrCfg)
|
|
}
|
|
|
|
// loadAPIBanCgrCfg loads the Analyzer section of the configuration
|
|
func (cfg *CGRConfig) loadAPIBanCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnAPIBanCfg *APIBanJsonCfg
|
|
if jsnAPIBanCfg, err = jsnCfg.ApiBanCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.apiBanCfg.loadFromJSONCfg(jsnAPIBanCfg)
|
|
}
|
|
func (cfg *CGRConfig) loadSentryPeerCgrCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSentryPeerCfg *SentryPeerJsonCfg
|
|
if jsnSentryPeerCfg, err = jsnCfg.SentryPeerJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.sentryPeerCfg.loadFromJSONCfg(jsnSentryPeerCfg)
|
|
}
|
|
|
|
// loadApierCfg loads the Apier section of the configuration
|
|
func (cfg *CGRConfig) loadApierCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnApierCfg *ApierJsonCfg
|
|
if jsnApierCfg, err = jsnCfg.ApierCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.apier.loadFromJSONCfg(jsnApierCfg)
|
|
}
|
|
|
|
// loadCoreSCfg loads the CoreS section of the configuration
|
|
func (cfg *CGRConfig) loadCoreSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnCoreCfg *CoreSJsonCfg
|
|
if jsnCoreCfg, err = jsnCfg.CoreSCfgJson(); err != nil {
|
|
return
|
|
}
|
|
return cfg.coreSCfg.loadFromJSONCfg(jsnCoreCfg)
|
|
}
|
|
|
|
// loadErsCfg loads the Ers section of the configuration
|
|
func (cfg *CGRConfig) loadErsCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnERsCfg *ERsJsonCfg
|
|
if jsnERsCfg, err = jsnCfg.ERsJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.ersCfg.loadFromJSONCfg(jsnERsCfg, cfg.templates, cfg.generalCfg.RSRSep, cfg.dfltEvRdr, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadEesCfg loads the Ees section of the configuration
|
|
func (cfg *CGRConfig) loadEesCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnEEsCfg *EEsJsonCfg
|
|
if jsnEEsCfg, err = jsnCfg.EEsJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.eesCfg.loadFromJSONCfg(jsnEEsCfg, cfg.templates, cfg.generalCfg.RSRSep, cfg.dfltEvExp)
|
|
}
|
|
|
|
// loadSIPAgentCfg loads the sip_agent section of the configuration
|
|
func (cfg *CGRConfig) loadSIPAgentCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnSIPAgentCfg *SIPAgentJsonCfg
|
|
if jsnSIPAgentCfg, err = jsnCfg.SIPAgentJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.sipAgentCfg.loadFromJSONCfg(jsnSIPAgentCfg, cfg.generalCfg.RSRSep)
|
|
}
|
|
|
|
// loadTemplateSCfg loads the Template section of the configuration
|
|
func (cfg *CGRConfig) loadTemplateSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnTemplateCfg map[string][]*FcTemplateJsonCfg
|
|
if jsnTemplateCfg, err = jsnCfg.TemplateSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
for k, val := range jsnTemplateCfg {
|
|
if cfg.templates[k], err = FCTemplatesFromFCTemplatesJSONCfg(val, cfg.generalCfg.RSRSep); err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (cfg *CGRConfig) loadConfigSCfg(jsnCfg *CgrJsonCfg) (err error) {
|
|
var jsnConfigSCfg *ConfigSCfgJson
|
|
if jsnConfigSCfg, err = jsnCfg.ConfigSJsonCfg(); err != nil {
|
|
return
|
|
}
|
|
return cfg.configSCfg.loadFromJSONCfg(jsnConfigSCfg)
|
|
}
|
|
|
|
// SureTaxCfg use locking to retrieve the configuration, possibility later for runtime reload
|
|
func (cfg *CGRConfig) SureTaxCfg() *SureTaxCfg {
|
|
cfg.lks[SURETAX_JSON].Lock()
|
|
defer cfg.lks[SURETAX_JSON].Unlock()
|
|
return cfg.sureTaxCfg
|
|
}
|
|
|
|
// DiameterAgentCfg returns the config for Diameter Agent
|
|
func (cfg *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg {
|
|
cfg.lks[DA_JSN].Lock()
|
|
defer cfg.lks[DA_JSN].Unlock()
|
|
return cfg.diameterAgentCfg
|
|
}
|
|
|
|
// RadiusAgentCfg returns the config for Radius Agent
|
|
func (cfg *CGRConfig) RadiusAgentCfg() *RadiusAgentCfg {
|
|
cfg.lks[RA_JSN].Lock()
|
|
defer cfg.lks[RA_JSN].Unlock()
|
|
return cfg.radiusAgentCfg
|
|
}
|
|
|
|
// DNSAgentCfg returns the config for DNS Agent
|
|
func (cfg *CGRConfig) DNSAgentCfg() *DNSAgentCfg {
|
|
cfg.lks[DNSAgentJson].Lock()
|
|
defer cfg.lks[DNSAgentJson].Unlock()
|
|
return cfg.dnsAgentCfg
|
|
}
|
|
|
|
// AttributeSCfg returns the config for AttributeS
|
|
func (cfg *CGRConfig) AttributeSCfg() *AttributeSCfg {
|
|
cfg.lks[ATTRIBUTE_JSN].Lock()
|
|
defer cfg.lks[ATTRIBUTE_JSN].Unlock()
|
|
return cfg.attributeSCfg
|
|
}
|
|
|
|
// ChargerSCfg returns the config for ChargerS
|
|
func (cfg *CGRConfig) ChargerSCfg() *ChargerSCfg {
|
|
cfg.lks[ChargerSCfgJson].Lock()
|
|
defer cfg.lks[ChargerSCfgJson].Unlock()
|
|
return cfg.chargerSCfg
|
|
}
|
|
|
|
// ResourceSCfg returns the config for ResourceS
|
|
func (cfg *CGRConfig) ResourceSCfg() *ResourceSConfig { // not done
|
|
cfg.lks[RESOURCES_JSON].Lock()
|
|
defer cfg.lks[RESOURCES_JSON].Unlock()
|
|
return cfg.resourceSCfg
|
|
}
|
|
|
|
// StatSCfg returns the config for StatS
|
|
func (cfg *CGRConfig) StatSCfg() *StatSCfg { // not done
|
|
cfg.lks[STATS_JSON].Lock()
|
|
defer cfg.lks[STATS_JSON].Unlock()
|
|
return cfg.statsCfg
|
|
}
|
|
|
|
// ThresholdSCfg returns the config for ThresholdS
|
|
func (cfg *CGRConfig) ThresholdSCfg() *ThresholdSCfg {
|
|
cfg.lks[THRESHOLDS_JSON].Lock()
|
|
defer cfg.lks[THRESHOLDS_JSON].Unlock()
|
|
return cfg.thresholdSCfg
|
|
}
|
|
|
|
// RouteSCfg returns the config for RouteS
|
|
func (cfg *CGRConfig) RouteSCfg() *RouteSCfg {
|
|
cfg.lks[RouteSJson].Lock()
|
|
defer cfg.lks[RouteSJson].Unlock()
|
|
return cfg.routeSCfg
|
|
}
|
|
|
|
// SessionSCfg returns the config for SessionS
|
|
func (cfg *CGRConfig) SessionSCfg() *SessionSCfg {
|
|
cfg.lks[SessionSJson].Lock()
|
|
defer cfg.lks[SessionSJson].Unlock()
|
|
return cfg.sessionSCfg
|
|
}
|
|
|
|
// FsAgentCfg returns the config for FsAgent
|
|
func (cfg *CGRConfig) FsAgentCfg() *FsAgentCfg {
|
|
cfg.lks[FreeSWITCHAgentJSN].Lock()
|
|
defer cfg.lks[FreeSWITCHAgentJSN].Unlock()
|
|
return cfg.fsAgentCfg
|
|
}
|
|
|
|
// KamAgentCfg returns the config for KamAgent
|
|
func (cfg *CGRConfig) KamAgentCfg() *KamAgentCfg {
|
|
cfg.lks[KamailioAgentJSN].Lock()
|
|
defer cfg.lks[KamailioAgentJSN].Unlock()
|
|
return cfg.kamAgentCfg
|
|
}
|
|
|
|
// AsteriskAgentCfg returns the config for AsteriskAgent
|
|
func (cfg *CGRConfig) AsteriskAgentCfg() *AsteriskAgentCfg {
|
|
cfg.lks[AsteriskAgentJSN].Lock()
|
|
defer cfg.lks[AsteriskAgentJSN].Unlock()
|
|
return cfg.asteriskAgentCfg
|
|
}
|
|
|
|
// HTTPAgentCfg returns the config for HttpAgent
|
|
func (cfg *CGRConfig) HTTPAgentCfg() HTTPAgentCfgs {
|
|
cfg.lks[HttpAgentJson].Lock()
|
|
defer cfg.lks[HttpAgentJson].Unlock()
|
|
return cfg.httpAgentCfg
|
|
}
|
|
|
|
// FilterSCfg returns the config for FilterS
|
|
func (cfg *CGRConfig) FilterSCfg() *FilterSCfg {
|
|
cfg.lks[FilterSjsn].Lock()
|
|
defer cfg.lks[FilterSjsn].Unlock()
|
|
return cfg.filterSCfg
|
|
}
|
|
|
|
// CacheCfg returns the config for Cache
|
|
func (cfg *CGRConfig) CacheCfg() *CacheCfg {
|
|
cfg.lks[CACHE_JSN].Lock()
|
|
defer cfg.lks[CACHE_JSN].Unlock()
|
|
return cfg.cacheCfg
|
|
}
|
|
|
|
// LoaderCfg returns the Loader Service
|
|
func (cfg *CGRConfig) LoaderCfg() LoaderSCfgs {
|
|
cfg.lks[LoaderJson].Lock()
|
|
defer cfg.lks[LoaderJson].Unlock()
|
|
return cfg.loaderCfg
|
|
}
|
|
|
|
// LoaderCgrCfg returns the config for cgr-loader
|
|
func (cfg *CGRConfig) LoaderCgrCfg() *LoaderCgrCfg {
|
|
cfg.lks[CgrLoaderCfgJson].Lock()
|
|
defer cfg.lks[CgrLoaderCfgJson].Unlock()
|
|
return cfg.loaderCgrCfg
|
|
}
|
|
|
|
// DispatcherSCfg returns the config for DispatcherS
|
|
func (cfg *CGRConfig) DispatcherSCfg() *DispatcherSCfg {
|
|
cfg.lks[DispatcherSJson].Lock()
|
|
defer cfg.lks[DispatcherSJson].Unlock()
|
|
return cfg.dispatcherSCfg
|
|
}
|
|
|
|
// RegistrarCCfg returns the config for RegistrarC
|
|
func (cfg *CGRConfig) RegistrarCCfg() *RegistrarCCfgs {
|
|
cfg.lks[DispatcherSJson].Lock()
|
|
defer cfg.lks[DispatcherSJson].Unlock()
|
|
return cfg.registrarCCfg
|
|
}
|
|
|
|
// MigratorCgrCfg returns the config for Migrator
|
|
func (cfg *CGRConfig) MigratorCgrCfg() *MigratorCgrCfg {
|
|
cfg.lks[CgrMigratorCfgJson].Lock()
|
|
defer cfg.lks[CgrMigratorCfgJson].Unlock()
|
|
return cfg.migratorCgrCfg
|
|
}
|
|
|
|
// SchedulerCfg returns the config for Scheduler
|
|
func (cfg *CGRConfig) SchedulerCfg() *SchedulerCfg {
|
|
cfg.lks[SCHEDULER_JSN].Lock()
|
|
defer cfg.lks[SCHEDULER_JSN].Unlock()
|
|
return cfg.schedulerCfg
|
|
}
|
|
|
|
// DataDbCfg returns the config for DataDb
|
|
func (cfg *CGRConfig) DataDbCfg() *DataDbCfg {
|
|
cfg.lks[DATADB_JSN].Lock()
|
|
defer cfg.lks[DATADB_JSN].Unlock()
|
|
return cfg.dataDbCfg
|
|
}
|
|
|
|
// StorDbCfg returns the config for StorDb
|
|
func (cfg *CGRConfig) StorDbCfg() *StorDbCfg {
|
|
cfg.lks[STORDB_JSN].Lock()
|
|
defer cfg.lks[STORDB_JSN].Unlock()
|
|
return cfg.storDbCfg
|
|
}
|
|
|
|
// GeneralCfg returns the General config section
|
|
func (cfg *CGRConfig) GeneralCfg() *GeneralCfg {
|
|
cfg.lks[GENERAL_JSN].Lock()
|
|
defer cfg.lks[GENERAL_JSN].Unlock()
|
|
return cfg.generalCfg
|
|
}
|
|
|
|
// TLSCfg returns the config for Tls
|
|
func (cfg *CGRConfig) TLSCfg() *TLSCfg {
|
|
cfg.lks[TlsCfgJson].Lock()
|
|
defer cfg.lks[TlsCfgJson].Unlock()
|
|
return cfg.tlsCfg
|
|
}
|
|
|
|
// ListenCfg returns the server Listen config
|
|
func (cfg *CGRConfig) ListenCfg() *ListenCfg {
|
|
cfg.lks[LISTEN_JSN].Lock()
|
|
defer cfg.lks[LISTEN_JSN].Unlock()
|
|
return cfg.listenCfg
|
|
}
|
|
|
|
// HTTPCfg returns the config for HTTP
|
|
func (cfg *CGRConfig) HTTPCfg() *HTTPCfg {
|
|
cfg.lks[HTTP_JSN].Lock()
|
|
defer cfg.lks[HTTP_JSN].Unlock()
|
|
return cfg.httpCfg
|
|
}
|
|
|
|
// RalsCfg returns the config for Ral Service
|
|
func (cfg *CGRConfig) RalsCfg() *RalsCfg {
|
|
cfg.lks[RALS_JSN].Lock()
|
|
defer cfg.lks[RALS_JSN].Unlock()
|
|
return cfg.ralsCfg
|
|
}
|
|
|
|
// CdrsCfg returns the config for CDR Server
|
|
func (cfg *CGRConfig) CdrsCfg() *CdrsCfg {
|
|
cfg.lks[CDRS_JSN].Lock()
|
|
defer cfg.lks[CDRS_JSN].Unlock()
|
|
return cfg.cdrsCfg
|
|
}
|
|
|
|
// MailerCfg returns the config for Mailer
|
|
func (cfg *CGRConfig) MailerCfg() *MailerCfg {
|
|
cfg.lks[MAILER_JSN].Lock()
|
|
defer cfg.lks[MAILER_JSN].Unlock()
|
|
return cfg.mailerCfg
|
|
}
|
|
|
|
// AnalyzerSCfg returns the config for AnalyzerS
|
|
func (cfg *CGRConfig) AnalyzerSCfg() *AnalyzerSCfg {
|
|
cfg.lks[AnalyzerCfgJson].Lock()
|
|
defer cfg.lks[AnalyzerCfgJson].Unlock()
|
|
return cfg.analyzerSCfg
|
|
}
|
|
|
|
// ApierCfg reads the Apier configuration
|
|
func (cfg *CGRConfig) ApierCfg() *ApierCfg {
|
|
cfg.lks[ApierS].Lock()
|
|
defer cfg.lks[ApierS].Unlock()
|
|
return cfg.apier
|
|
}
|
|
|
|
// ERsCfg reads the EventReader configuration
|
|
func (cfg *CGRConfig) ERsCfg() *ERsCfg {
|
|
cfg.lks[ERsJson].RLock()
|
|
defer cfg.lks[ERsJson].RUnlock()
|
|
return cfg.ersCfg
|
|
}
|
|
|
|
// EEsCfg reads the EventExporter configuration
|
|
func (cfg *CGRConfig) EEsCfg() *EEsCfg {
|
|
cfg.lks[EEsJson].RLock()
|
|
defer cfg.lks[EEsJson].RUnlock()
|
|
return cfg.eesCfg
|
|
}
|
|
|
|
// EEsNoLksCfg reads the EventExporter configuration without locks
|
|
func (cfg *CGRConfig) EEsNoLksCfg() *EEsCfg {
|
|
return cfg.eesCfg
|
|
}
|
|
|
|
// SIPAgentCfg reads the Apier configuration
|
|
func (cfg *CGRConfig) SIPAgentCfg() *SIPAgentCfg {
|
|
cfg.lks[SIPAgentJson].Lock()
|
|
defer cfg.lks[SIPAgentJson].Unlock()
|
|
return cfg.sipAgentCfg
|
|
}
|
|
|
|
// RPCConns reads the RPCConns configuration
|
|
func (cfg *CGRConfig) RPCConns() RPCConns {
|
|
cfg.lks[RPCConnsJsonName].RLock()
|
|
defer cfg.lks[RPCConnsJsonName].RUnlock()
|
|
return cfg.rpcConns
|
|
}
|
|
|
|
// TemplatesCfg returns the config for templates
|
|
func (cfg *CGRConfig) TemplatesCfg() FcTemplates {
|
|
cfg.lks[TemplatesJson].Lock()
|
|
defer cfg.lks[TemplatesJson].Unlock()
|
|
return cfg.templates
|
|
}
|
|
|
|
// ConfigSCfg returns the configs configuration
|
|
func (cfg *CGRConfig) ConfigSCfg() *ConfigSCfg {
|
|
cfg.lks[ConfigSJson].RLock()
|
|
defer cfg.lks[ConfigSJson].RUnlock()
|
|
return cfg.configSCfg
|
|
}
|
|
|
|
// APIBanCfg reads the ApiBan configuration
|
|
func (cfg *CGRConfig) APIBanCfg() *APIBanCfg {
|
|
cfg.lks[APIBanCfgJson].Lock()
|
|
defer cfg.lks[APIBanCfgJson].Unlock()
|
|
return cfg.apiBanCfg
|
|
}
|
|
func (cfg *CGRConfig) SentryPeerCfg() *SentryPeerCfg {
|
|
cfg.lks[SentryPeerCfgJson].Lock()
|
|
defer cfg.lks[SentryPeerCfgJson].Unlock()
|
|
return cfg.sentryPeerCfg
|
|
}
|
|
|
|
// CoreSCfg reads the CoreS configuration
|
|
func (cfg *CGRConfig) CoreSCfg() *CoreSCfg {
|
|
cfg.lks[CoreSCfgJson].Lock()
|
|
defer cfg.lks[CoreSCfgJson].Unlock()
|
|
return cfg.coreSCfg
|
|
}
|
|
|
|
// GetReloadChan returns the reload chanel for the given section
|
|
func (cfg *CGRConfig) GetReloadChan(sectID string) chan struct{} {
|
|
return cfg.rldChans[sectID]
|
|
}
|
|
|
|
// Call implements birpc.ClientConnector interface for internal RPC
|
|
func (cfg *CGRConfig) Call(ctx *context.Context, serviceMethod string,
|
|
args any, reply any) error {
|
|
return utils.APIerRPCCall(cfg, serviceMethod, args, reply)
|
|
}
|
|
|
|
func (cfg *CGRConfig) rLockSections() {
|
|
for _, lk := range cfg.lks {
|
|
lk.RLock()
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) rUnlockSections() {
|
|
for _, lk := range cfg.lks {
|
|
lk.RUnlock()
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) lockSections() {
|
|
for _, lk := range cfg.lks {
|
|
lk.Lock()
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) unlockSections() {
|
|
for _, lk := range cfg.lks {
|
|
lk.Unlock()
|
|
}
|
|
}
|
|
|
|
// RLocks will read-lock locks with IDs.
|
|
// User needs to know what he is doing since this can panic
|
|
func (cfg *CGRConfig) RLocks(lkIDs ...string) {
|
|
for _, lkID := range lkIDs {
|
|
cfg.lks[lkID].RLock()
|
|
}
|
|
}
|
|
|
|
// RUnlocks will read-unlock locks with IDs.
|
|
// User needs to know what he is doing since this can panic
|
|
func (cfg *CGRConfig) RUnlocks(lkIDs ...string) {
|
|
for _, lkID := range lkIDs {
|
|
cfg.lks[lkID].RUnlock()
|
|
}
|
|
}
|
|
|
|
// LockSections will lock the given sections
|
|
// User needs to know what he is doing since this can panic
|
|
func (cfg *CGRConfig) LockSections(lkIDs ...string) {
|
|
for _, lkID := range lkIDs {
|
|
cfg.lks[lkID].Lock()
|
|
}
|
|
}
|
|
|
|
// UnlockSections will unlock the given sections
|
|
// User needs to know what he is doing since this can panic
|
|
func (cfg *CGRConfig) UnlockSections(lkIDs ...string) {
|
|
for _, lkID := range lkIDs {
|
|
cfg.lks[lkID].Unlock()
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) getLoadFunctions() map[string]func(*CgrJsonCfg) error {
|
|
return map[string]func(*CgrJsonCfg) error{
|
|
GENERAL_JSN: cfg.loadGeneralCfg,
|
|
DATADB_JSN: cfg.loadDataDBCfg,
|
|
STORDB_JSN: cfg.loadStorDBCfg,
|
|
LISTEN_JSN: cfg.loadListenCfg,
|
|
TlsCfgJson: cfg.loadTLSCgrCfg,
|
|
HTTP_JSN: cfg.loadHTTPCfg,
|
|
SCHEDULER_JSN: cfg.loadSchedulerCfg,
|
|
CACHE_JSN: cfg.loadCacheCfg,
|
|
FilterSjsn: cfg.loadFilterSCfg,
|
|
RALS_JSN: cfg.loadRalSCfg,
|
|
CDRS_JSN: cfg.loadCdrsCfg,
|
|
ERsJson: cfg.loadErsCfg,
|
|
EEsJson: cfg.loadEesCfg,
|
|
SessionSJson: cfg.loadSessionSCfg,
|
|
AsteriskAgentJSN: cfg.loadAsteriskAgentCfg,
|
|
FreeSWITCHAgentJSN: cfg.loadFreeswitchAgentCfg,
|
|
KamailioAgentJSN: cfg.loadKamAgentCfg,
|
|
DA_JSN: cfg.loadDiameterAgentCfg,
|
|
RA_JSN: cfg.loadRadiusAgentCfg,
|
|
HttpAgentJson: cfg.loadHTTPAgentCfg,
|
|
DNSAgentJson: cfg.loadDNSAgentCfg,
|
|
ATTRIBUTE_JSN: cfg.loadAttributeSCfg,
|
|
ChargerSCfgJson: cfg.loadChargerSCfg,
|
|
RESOURCES_JSON: cfg.loadResourceSCfg,
|
|
STATS_JSON: cfg.loadStatSCfg,
|
|
THRESHOLDS_JSON: cfg.loadThresholdSCfg,
|
|
RouteSJson: cfg.loadRouteSCfg,
|
|
LoaderJson: cfg.loadLoaderSCfg,
|
|
MAILER_JSN: cfg.loadMailerCfg,
|
|
SURETAX_JSON: cfg.loadSureTaxCfg,
|
|
CgrLoaderCfgJson: cfg.loadLoaderCgrCfg,
|
|
CgrMigratorCfgJson: cfg.loadMigratorCgrCfg,
|
|
DispatcherSJson: cfg.loadDispatcherSCfg,
|
|
RegistrarCJson: cfg.loadRegistrarCCfg,
|
|
AnalyzerCfgJson: cfg.loadAnalyzerCgrCfg,
|
|
ApierS: cfg.loadApierCfg,
|
|
RPCConnsJsonName: cfg.loadRPCConns,
|
|
SIPAgentJson: cfg.loadSIPAgentCfg,
|
|
TemplatesJson: cfg.loadTemplateSCfg,
|
|
ConfigSJson: cfg.loadConfigSCfg,
|
|
APIBanCfgJson: cfg.loadAPIBanCgrCfg,
|
|
SentryPeerCfgJson: cfg.loadSentryPeerCgrCfg,
|
|
CoreSCfgJson: cfg.loadCoreSCfg,
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) loadCfgWithLocks(path, section string) (err error) {
|
|
var loadFuncs []func(*CgrJsonCfg) error
|
|
loadMap := cfg.getLoadFunctions()
|
|
if section == utils.EmptyString || section == utils.MetaAll {
|
|
for _, sec := range sortedCfgSections {
|
|
cfg.lks[sec].Lock()
|
|
defer cfg.lks[sec].Unlock()
|
|
loadFuncs = append(loadFuncs, loadMap[sec])
|
|
}
|
|
} else if fnct, has := loadMap[section]; !has {
|
|
return fmt.Errorf("Invalid section: <%s>", section)
|
|
} else {
|
|
cfg.lks[section].Lock()
|
|
defer cfg.lks[section].Unlock()
|
|
loadFuncs = append(loadFuncs, fnct)
|
|
}
|
|
return cfg.loadConfigFromPath(path, loadFuncs, false)
|
|
}
|
|
|
|
func (*CGRConfig) loadConfigFromReader(rdr io.Reader, loadFuncs []func(jsnCfg *CgrJsonCfg) error, envOff bool) (err error) {
|
|
jsnCfg := new(CgrJsonCfg)
|
|
var rjr *RjReader
|
|
if rjr, err = NewRjReader(rdr); err != nil {
|
|
return
|
|
}
|
|
rjr.envOff = envOff
|
|
defer rjr.Close() // make sure we make the buffer nil
|
|
if err = rjr.Decode(jsnCfg); err != nil {
|
|
return
|
|
}
|
|
for _, loadFunc := range loadFuncs {
|
|
if err = loadFunc(jsnCfg); err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Reads all .json files out of a folder/subfolders and loads them up in lexical order
|
|
func (cfg *CGRConfig) loadConfigFromPath(path string, loadFuncs []func(jsnCfg *CgrJsonCfg) error, envOff bool) (err error) {
|
|
if utils.IsURL(path) {
|
|
return cfg.loadConfigFromHTTP(path, loadFuncs) // prefix protocol
|
|
}
|
|
var fi os.FileInfo
|
|
if fi, err = os.Stat(path); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return utils.ErrPathNotReachable(path)
|
|
}
|
|
return
|
|
} else if !fi.IsDir() && path != utils.ConfigPath { // If config dir defined, needs to exist, not checking for default
|
|
return fmt.Errorf("path: %s not a directory", path)
|
|
}
|
|
|
|
// safe to assume that path is a directory
|
|
return cfg.loadConfigFromFolder(path, loadFuncs, envOff)
|
|
}
|
|
|
|
func (cfg *CGRConfig) loadConfigFromFolder(cfgDir string, loadFuncs []func(jsnCfg *CgrJsonCfg) error, envOff bool) (err error) {
|
|
jsonFilesFound := false
|
|
if err = filepath.Walk(cfgDir, func(path string, info os.FileInfo, err error) (werr error) {
|
|
if !info.IsDir() || isHidden(info.Name()) { // also ignore hidden files and folders
|
|
return
|
|
}
|
|
var cfgFiles []string
|
|
if cfgFiles, werr = filepath.Glob(filepath.Join(path, "*.json")); werr != nil {
|
|
return
|
|
}
|
|
if cfgFiles == nil { // No need of processing further since there are no config files in the folder
|
|
return
|
|
}
|
|
if !jsonFilesFound {
|
|
jsonFilesFound = true
|
|
}
|
|
for _, jsonFilePath := range cfgFiles {
|
|
if werr = cfg.loadConfigFromFile(jsonFilePath, loadFuncs, envOff); werr != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}); err != nil {
|
|
return
|
|
}
|
|
if !jsonFilesFound {
|
|
return fmt.Errorf("No config file found on path %s", cfgDir)
|
|
}
|
|
return
|
|
}
|
|
|
|
// loadConfigFromFile loads the config from a file
|
|
// extracted from a loadConfigFromFolder in order to test all cases
|
|
func (cfg *CGRConfig) loadConfigFromFile(jsonFilePath string, loadFuncs []func(jsnCfg *CgrJsonCfg) error, envOff bool) (err error) {
|
|
var cfgFile *os.File
|
|
cfgFile, err = os.Open(jsonFilePath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = cfg.loadConfigFromReader(cfgFile, loadFuncs, envOff)
|
|
cfgFile.Close()
|
|
if err != nil {
|
|
err = fmt.Errorf("file <%s>:%s", jsonFilePath, err.Error())
|
|
}
|
|
return
|
|
}
|
|
|
|
func (cfg *CGRConfig) loadConfigFromHTTP(urlPaths string, loadFuncs []func(jsnCfg *CgrJsonCfg) error) (err error) {
|
|
for _, urlPath := range strings.Split(urlPaths, utils.InfieldSep) {
|
|
var myClient = &http.Client{
|
|
Timeout: CgrConfig().GeneralCfg().ReplyTimeout,
|
|
}
|
|
var cfgReq *http.Response
|
|
cfgReq, err = myClient.Get(urlPath)
|
|
if err != nil {
|
|
return utils.ErrPathNotReachable(urlPath)
|
|
}
|
|
err = cfg.loadConfigFromReader(cfgReq.Body, loadFuncs, false)
|
|
cfgReq.Body.Close()
|
|
if err != nil {
|
|
err = fmt.Errorf("url <%s>:%s", urlPath, err.Error())
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// populates the config locks and the reload channels
|
|
func (cfg *CGRConfig) initChanels() {
|
|
cfg.lks = make(map[string]*sync.RWMutex)
|
|
cfg.rldChans = make(map[string]chan struct{})
|
|
for _, section := range sortedCfgSections {
|
|
cfg.lks[section] = new(sync.RWMutex)
|
|
cfg.rldChans[section] = make(chan struct{})
|
|
}
|
|
}
|
|
|
|
func (cfg *CGRConfig) loadCfgFromJSONWithLocks(rdr io.Reader, sections []string) (err error) {
|
|
var loadFuncs []func(*CgrJsonCfg) error
|
|
loadMap := cfg.getLoadFunctions()
|
|
for _, section := range sections {
|
|
fnct, has := loadMap[section]
|
|
if !has {
|
|
return fmt.Errorf("Invalid section: <%s>", section)
|
|
}
|
|
cfg.lks[section].Lock()
|
|
defer cfg.lks[section].Unlock()
|
|
loadFuncs = append(loadFuncs, fnct)
|
|
}
|
|
return cfg.loadConfigFromReader(rdr, loadFuncs, false)
|
|
}
|
|
|
|
// reloadSections sends a signal to the reload channel for the needed sections
|
|
// the list of sections should be always valid because we load the config first with this list
|
|
func (cfg *CGRConfig) reloadSections(sections ...string) {
|
|
subsystemsThatNeedDataDB := utils.NewStringSet([]string{DATADB_JSN, SCHEDULER_JSN,
|
|
RALS_JSN, CDRS_JSN, SessionSJson, ATTRIBUTE_JSN,
|
|
ChargerSCfgJson, RESOURCES_JSON, STATS_JSON, THRESHOLDS_JSON,
|
|
RouteSJson, LoaderJson, DispatcherSJson, ApierS,
|
|
})
|
|
subsystemsThatNeedStorDB := utils.NewStringSet([]string{STORDB_JSN, RALS_JSN, CDRS_JSN, ApierS})
|
|
needsDataDB := false
|
|
needsStorDB := false
|
|
for _, section := range sections {
|
|
if !needsDataDB && subsystemsThatNeedDataDB.Has(section) {
|
|
needsDataDB = true
|
|
cfg.rldChans[DATADB_JSN] <- struct{}{} // reload datadb before
|
|
}
|
|
if !needsStorDB && subsystemsThatNeedStorDB.Has(section) {
|
|
needsStorDB = true
|
|
cfg.rldChans[STORDB_JSN] <- struct{}{} // reload stordb before
|
|
}
|
|
if needsDataDB && needsStorDB {
|
|
break
|
|
}
|
|
}
|
|
runtime.Gosched()
|
|
for _, section := range sections {
|
|
switch section {
|
|
case ConfigSJson:
|
|
case GENERAL_JSN: // nothing to reload
|
|
case RPCConnsJsonName: // nothing to reload
|
|
cfg.rldChans[RPCConnsJsonName] <- struct{}{}
|
|
case DATADB_JSN: // reloaded before
|
|
case STORDB_JSN: // reloaded before
|
|
case LISTEN_JSN:
|
|
case CACHE_JSN:
|
|
case FilterSjsn:
|
|
case MAILER_JSN:
|
|
case SURETAX_JSON:
|
|
case CgrLoaderCfgJson:
|
|
case CgrMigratorCfgJson:
|
|
case TemplatesJson:
|
|
case TlsCfgJson: // nothing to reload
|
|
case APIBanCfgJson: // nothing to reload
|
|
case SentryPeerCfgJson:
|
|
case CoreSCfgJson: // nothing to reload
|
|
case HTTP_JSN:
|
|
cfg.rldChans[HTTP_JSN] <- struct{}{}
|
|
case SCHEDULER_JSN:
|
|
cfg.rldChans[SCHEDULER_JSN] <- struct{}{}
|
|
case RALS_JSN:
|
|
cfg.rldChans[RALS_JSN] <- struct{}{}
|
|
case CDRS_JSN:
|
|
cfg.rldChans[CDRS_JSN] <- struct{}{}
|
|
case ERsJson:
|
|
cfg.rldChans[ERsJson] <- struct{}{}
|
|
case SessionSJson:
|
|
cfg.rldChans[SessionSJson] <- struct{}{}
|
|
case AsteriskAgentJSN:
|
|
cfg.rldChans[AsteriskAgentJSN] <- struct{}{}
|
|
case FreeSWITCHAgentJSN:
|
|
cfg.rldChans[FreeSWITCHAgentJSN] <- struct{}{}
|
|
case KamailioAgentJSN:
|
|
cfg.rldChans[KamailioAgentJSN] <- struct{}{}
|
|
case DA_JSN:
|
|
cfg.rldChans[DA_JSN] <- struct{}{}
|
|
case RA_JSN:
|
|
cfg.rldChans[RA_JSN] <- struct{}{}
|
|
case HttpAgentJson:
|
|
cfg.rldChans[HttpAgentJson] <- struct{}{}
|
|
case DNSAgentJson:
|
|
cfg.rldChans[DNSAgentJson] <- struct{}{}
|
|
case ATTRIBUTE_JSN:
|
|
cfg.rldChans[ATTRIBUTE_JSN] <- struct{}{}
|
|
case ChargerSCfgJson:
|
|
cfg.rldChans[ChargerSCfgJson] <- struct{}{}
|
|
case RESOURCES_JSON:
|
|
cfg.rldChans[RESOURCES_JSON] <- struct{}{}
|
|
case STATS_JSON:
|
|
cfg.rldChans[STATS_JSON] <- struct{}{}
|
|
case THRESHOLDS_JSON:
|
|
cfg.rldChans[THRESHOLDS_JSON] <- struct{}{}
|
|
case RouteSJson:
|
|
cfg.rldChans[RouteSJson] <- struct{}{}
|
|
case LoaderJson:
|
|
cfg.rldChans[LoaderJson] <- struct{}{}
|
|
case DispatcherSJson:
|
|
cfg.rldChans[DispatcherSJson] <- struct{}{}
|
|
case AnalyzerCfgJson:
|
|
cfg.rldChans[AnalyzerCfgJson] <- struct{}{}
|
|
case ApierS:
|
|
cfg.rldChans[ApierS] <- struct{}{}
|
|
case EEsJson:
|
|
cfg.rldChans[EEsJson] <- struct{}{}
|
|
case SIPAgentJson:
|
|
cfg.rldChans[SIPAgentJson] <- struct{}{}
|
|
case RegistrarCJson:
|
|
cfg.rldChans[RegistrarCJson] <- struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
// AsMapInterface returns the config as a map[string]any
|
|
func (cfg *CGRConfig) AsMapInterface(separator string) (mp map[string]any) {
|
|
return map[string]any{
|
|
LoaderJson: cfg.loaderCfg.AsMapInterface(separator),
|
|
HttpAgentJson: cfg.httpAgentCfg.AsMapInterface(separator),
|
|
RPCConnsJsonName: cfg.rpcConns.AsMapInterface(),
|
|
GENERAL_JSN: cfg.generalCfg.AsMapInterface(),
|
|
DATADB_JSN: cfg.dataDbCfg.AsMapInterface(),
|
|
STORDB_JSN: cfg.storDbCfg.AsMapInterface(),
|
|
TlsCfgJson: cfg.tlsCfg.AsMapInterface(),
|
|
CACHE_JSN: cfg.cacheCfg.AsMapInterface(),
|
|
LISTEN_JSN: cfg.listenCfg.AsMapInterface(),
|
|
HTTP_JSN: cfg.httpCfg.AsMapInterface(),
|
|
FilterSjsn: cfg.filterSCfg.AsMapInterface(),
|
|
RALS_JSN: cfg.ralsCfg.AsMapInterface(),
|
|
SCHEDULER_JSN: cfg.schedulerCfg.AsMapInterface(),
|
|
CDRS_JSN: cfg.cdrsCfg.AsMapInterface(),
|
|
SessionSJson: cfg.sessionSCfg.AsMapInterface(),
|
|
FreeSWITCHAgentJSN: cfg.fsAgentCfg.AsMapInterface(separator),
|
|
KamailioAgentJSN: cfg.kamAgentCfg.AsMapInterface(),
|
|
AsteriskAgentJSN: cfg.asteriskAgentCfg.AsMapInterface(),
|
|
DA_JSN: cfg.diameterAgentCfg.AsMapInterface(separator),
|
|
RA_JSN: cfg.radiusAgentCfg.AsMapInterface(separator),
|
|
DNSAgentJson: cfg.dnsAgentCfg.AsMapInterface(separator),
|
|
ATTRIBUTE_JSN: cfg.attributeSCfg.AsMapInterface(),
|
|
ChargerSCfgJson: cfg.chargerSCfg.AsMapInterface(),
|
|
RESOURCES_JSON: cfg.resourceSCfg.AsMapInterface(),
|
|
STATS_JSON: cfg.statsCfg.AsMapInterface(),
|
|
THRESHOLDS_JSON: cfg.thresholdSCfg.AsMapInterface(),
|
|
RouteSJson: cfg.routeSCfg.AsMapInterface(),
|
|
SURETAX_JSON: cfg.sureTaxCfg.AsMapInterface(separator),
|
|
DispatcherSJson: cfg.dispatcherSCfg.AsMapInterface(),
|
|
RegistrarCJson: cfg.registrarCCfg.AsMapInterface(),
|
|
CgrLoaderCfgJson: cfg.loaderCgrCfg.AsMapInterface(),
|
|
CgrMigratorCfgJson: cfg.migratorCgrCfg.AsMapInterface(),
|
|
MAILER_JSN: cfg.mailerCfg.AsMapInterface(),
|
|
AnalyzerCfgJson: cfg.analyzerSCfg.AsMapInterface(),
|
|
ApierS: cfg.apier.AsMapInterface(),
|
|
ERsJson: cfg.ersCfg.AsMapInterface(separator),
|
|
APIBanCfgJson: cfg.apiBanCfg.AsMapInterface(),
|
|
SentryPeerCfgJson: cfg.sentryPeerCfg.AsMapInterface(),
|
|
EEsJson: cfg.eesCfg.AsMapInterface(separator),
|
|
SIPAgentJson: cfg.sipAgentCfg.AsMapInterface(separator),
|
|
TemplatesJson: cfg.templates.AsMapInterface(separator),
|
|
ConfigSJson: cfg.configSCfg.AsMapInterface(),
|
|
CoreSCfgJson: cfg.coreSCfg.AsMapInterface(),
|
|
}
|
|
}
|
|
|
|
// ReloadArgs the API params for V1ReloadConfig
|
|
type ReloadArgs struct {
|
|
APIOpts map[string]any
|
|
Tenant string
|
|
Path string
|
|
Section string
|
|
DryRun bool
|
|
}
|
|
|
|
// V1ReloadConfig reloads the configuration
|
|
func (cfg *CGRConfig) V1ReloadConfig(ctx *context.Context, args *ReloadArgs, reply *string) (err error) {
|
|
if missing := utils.MissingStructFields(args, []string{"Path"}); len(missing) != 0 {
|
|
return utils.NewErrMandatoryIeMissing(missing...)
|
|
}
|
|
cfgV := cfg
|
|
if args.DryRun {
|
|
cfgV = cfg.Clone()
|
|
}
|
|
cfgV.reloadDPCache(args.Section)
|
|
if err = cfgV.loadCfgWithLocks(args.Path, args.Section); err != nil {
|
|
return
|
|
}
|
|
// lock all sections
|
|
cfgV.rLockSections()
|
|
|
|
err = cfgV.checkConfigSanity()
|
|
|
|
cfgV.rUnlockSections() // unlock before checking the error
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !args.DryRun {
|
|
if args.Section == utils.EmptyString || args.Section == utils.MetaAll {
|
|
cfgV.reloadSections(sortedCfgSections...)
|
|
} else {
|
|
cfgV.reloadSections(args.Section)
|
|
}
|
|
}
|
|
*reply = utils.OK
|
|
return
|
|
}
|
|
|
|
// SectionWithAPIOpts the API params for GetConfig
|
|
type SectionWithAPIOpts struct {
|
|
APIOpts map[string]any
|
|
Tenant string
|
|
Section string
|
|
}
|
|
|
|
// V1GetConfig will retrieve from CGRConfig a section
|
|
func (cfg *CGRConfig) V1GetConfig(ctx *context.Context, args *SectionWithAPIOpts, reply *map[string]any) (err error) {
|
|
args.Section = utils.FirstNonEmpty(args.Section, utils.MetaAll)
|
|
cfg.cacheDPMux.RLock()
|
|
if mp, has := cfg.cacheDP[args.Section]; has && mp != nil {
|
|
*reply = mp
|
|
cfg.cacheDPMux.RUnlock()
|
|
return
|
|
}
|
|
cfg.cacheDPMux.RUnlock()
|
|
defer func() {
|
|
if err != nil {
|
|
return
|
|
}
|
|
cfg.cacheDPMux.Lock()
|
|
cfg.cacheDP[args.Section] = *reply
|
|
cfg.cacheDPMux.Unlock()
|
|
}()
|
|
var mp any
|
|
switch args.Section {
|
|
case utils.MetaAll:
|
|
*reply = cfg.AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
return
|
|
case GENERAL_JSN:
|
|
mp = cfg.GeneralCfg().AsMapInterface()
|
|
case DATADB_JSN:
|
|
mp = cfg.DataDbCfg().AsMapInterface()
|
|
case STORDB_JSN:
|
|
mp = cfg.StorDbCfg().AsMapInterface()
|
|
case TlsCfgJson:
|
|
mp = cfg.TLSCfg().AsMapInterface()
|
|
case CACHE_JSN:
|
|
mp = cfg.CacheCfg().AsMapInterface()
|
|
case LISTEN_JSN:
|
|
mp = cfg.ListenCfg().AsMapInterface()
|
|
case HTTP_JSN:
|
|
mp = cfg.HTTPCfg().AsMapInterface()
|
|
case FilterSjsn:
|
|
mp = cfg.FilterSCfg().AsMapInterface()
|
|
case RALS_JSN:
|
|
mp = cfg.RalsCfg().AsMapInterface()
|
|
case SCHEDULER_JSN:
|
|
mp = cfg.SchedulerCfg().AsMapInterface()
|
|
case CDRS_JSN:
|
|
mp = cfg.CdrsCfg().AsMapInterface()
|
|
case SessionSJson:
|
|
mp = cfg.SessionSCfg().AsMapInterface()
|
|
case FreeSWITCHAgentJSN:
|
|
mp = cfg.FsAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case KamailioAgentJSN:
|
|
mp = cfg.KamAgentCfg().AsMapInterface()
|
|
case AsteriskAgentJSN:
|
|
mp = cfg.AsteriskAgentCfg().AsMapInterface()
|
|
case DA_JSN:
|
|
mp = cfg.DiameterAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case RA_JSN:
|
|
mp = cfg.RadiusAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case DNSAgentJson:
|
|
mp = cfg.DNSAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ATTRIBUTE_JSN:
|
|
mp = cfg.AttributeSCfg().AsMapInterface()
|
|
case ChargerSCfgJson:
|
|
mp = cfg.ChargerSCfg().AsMapInterface()
|
|
case RESOURCES_JSON:
|
|
mp = cfg.ResourceSCfg().AsMapInterface()
|
|
case STATS_JSON:
|
|
mp = cfg.StatSCfg().AsMapInterface()
|
|
case THRESHOLDS_JSON:
|
|
mp = cfg.ThresholdSCfg().AsMapInterface()
|
|
case RouteSJson:
|
|
mp = cfg.RouteSCfg().AsMapInterface()
|
|
case SURETAX_JSON:
|
|
mp = cfg.SureTaxCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case DispatcherSJson:
|
|
mp = cfg.DispatcherSCfg().AsMapInterface()
|
|
case RegistrarCJson:
|
|
mp = cfg.RegistrarCCfg().AsMapInterface()
|
|
case LoaderJson:
|
|
mp = cfg.LoaderCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case CgrLoaderCfgJson:
|
|
mp = cfg.LoaderCgrCfg().AsMapInterface()
|
|
case CgrMigratorCfgJson:
|
|
mp = cfg.MigratorCgrCfg().AsMapInterface()
|
|
case ApierS:
|
|
mp = cfg.ApierCfg().AsMapInterface()
|
|
case EEsJson:
|
|
mp = cfg.EEsCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ERsJson:
|
|
mp = cfg.ERsCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case RPCConnsJsonName:
|
|
mp = cfg.RPCConns().AsMapInterface()
|
|
case SIPAgentJson:
|
|
mp = cfg.SIPAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case TemplatesJson:
|
|
mp = cfg.TemplatesCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ConfigSJson:
|
|
mp = cfg.ConfigSCfg().AsMapInterface()
|
|
case APIBanCfgJson:
|
|
mp = cfg.APIBanCfg().AsMapInterface()
|
|
case SentryPeerCfgJson:
|
|
mp = cfg.SentryPeerCfg().AsMapInterface()
|
|
case HttpAgentJson:
|
|
mp = cfg.HTTPAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case MAILER_JSN:
|
|
mp = cfg.MailerCfg().AsMapInterface()
|
|
case AnalyzerCfgJson:
|
|
mp = cfg.AnalyzerSCfg().AsMapInterface()
|
|
case CoreSCfgJson:
|
|
mp = cfg.CoreSCfg().AsMapInterface()
|
|
default:
|
|
return errors.New("Invalid section")
|
|
}
|
|
*reply = map[string]any{args.Section: mp}
|
|
return
|
|
}
|
|
|
|
// SetConfigArgs the API params for V1SetConfig
|
|
type SetConfigArgs struct {
|
|
APIOpts map[string]any
|
|
Tenant string
|
|
Config map[string]any
|
|
DryRun bool
|
|
}
|
|
|
|
// V1SetConfig reloads the sections of config
|
|
func (cfg *CGRConfig) V1SetConfig(ctx *context.Context, args *SetConfigArgs, reply *string) (err error) {
|
|
if len(args.Config) == 0 {
|
|
*reply = utils.OK
|
|
return
|
|
}
|
|
sections := make([]string, 0, len(args.Config))
|
|
for section := range args.Config {
|
|
sections = append(sections, section)
|
|
}
|
|
var b []byte
|
|
if b, err = json.Marshal(args.Config); err != nil {
|
|
return
|
|
}
|
|
cfgV := cfg
|
|
if args.DryRun {
|
|
cfgV = cfg.Clone()
|
|
}
|
|
|
|
cfgV.reloadDPCache(sections...)
|
|
if err = cfgV.loadCfgFromJSONWithLocks(bytes.NewBuffer(b), sections); err != nil {
|
|
return
|
|
}
|
|
|
|
// lock all sections
|
|
cfgV.rLockSections()
|
|
|
|
err = cfgV.checkConfigSanity()
|
|
|
|
cfgV.rUnlockSections() // unlock before checking the error
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !args.DryRun {
|
|
cfgV.reloadSections(sections...)
|
|
}
|
|
*reply = utils.OK
|
|
return
|
|
}
|
|
|
|
// V1GetConfigAsJSON will retrieve from CGRConfig a section as a string
|
|
func (cfg *CGRConfig) V1GetConfigAsJSON(ctx *context.Context, args *SectionWithAPIOpts, reply *string) (err error) {
|
|
args.Section = utils.FirstNonEmpty(args.Section, utils.MetaAll)
|
|
cfg.cacheDPMux.RLock()
|
|
if mp, has := cfg.cacheDP[args.Section]; has && mp != nil {
|
|
*reply = utils.ToJSON(mp)
|
|
cfg.cacheDPMux.RUnlock()
|
|
return
|
|
}
|
|
cfg.cacheDPMux.RUnlock()
|
|
var rplyMap utils.MapStorage
|
|
defer func() {
|
|
if err != nil {
|
|
return
|
|
}
|
|
cfg.cacheDPMux.Lock()
|
|
cfg.cacheDP[args.Section] = rplyMap
|
|
cfg.cacheDPMux.Unlock()
|
|
}()
|
|
var mp any
|
|
switch args.Section {
|
|
case utils.MetaAll:
|
|
rplyMap = cfg.AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
*reply = utils.ToJSON(rplyMap)
|
|
return
|
|
case GENERAL_JSN:
|
|
mp = cfg.GeneralCfg().AsMapInterface()
|
|
case DATADB_JSN:
|
|
mp = cfg.DataDbCfg().AsMapInterface()
|
|
case STORDB_JSN:
|
|
mp = cfg.StorDbCfg().AsMapInterface()
|
|
case TlsCfgJson:
|
|
mp = cfg.TLSCfg().AsMapInterface()
|
|
case CACHE_JSN:
|
|
mp = cfg.CacheCfg().AsMapInterface()
|
|
case LISTEN_JSN:
|
|
mp = cfg.ListenCfg().AsMapInterface()
|
|
case HTTP_JSN:
|
|
mp = cfg.HTTPCfg().AsMapInterface()
|
|
case FilterSjsn:
|
|
mp = cfg.FilterSCfg().AsMapInterface()
|
|
case RALS_JSN:
|
|
mp = cfg.RalsCfg().AsMapInterface()
|
|
case SCHEDULER_JSN:
|
|
mp = cfg.SchedulerCfg().AsMapInterface()
|
|
case CDRS_JSN:
|
|
mp = cfg.CdrsCfg().AsMapInterface()
|
|
case SessionSJson:
|
|
mp = cfg.SessionSCfg().AsMapInterface()
|
|
case FreeSWITCHAgentJSN:
|
|
mp = cfg.FsAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case KamailioAgentJSN:
|
|
mp = cfg.KamAgentCfg().AsMapInterface()
|
|
case AsteriskAgentJSN:
|
|
mp = cfg.AsteriskAgentCfg().AsMapInterface()
|
|
case DA_JSN:
|
|
mp = cfg.DiameterAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case RA_JSN:
|
|
mp = cfg.RadiusAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case DNSAgentJson:
|
|
mp = cfg.DNSAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ATTRIBUTE_JSN:
|
|
mp = cfg.AttributeSCfg().AsMapInterface()
|
|
case ChargerSCfgJson:
|
|
mp = cfg.ChargerSCfg().AsMapInterface()
|
|
case RESOURCES_JSON:
|
|
mp = cfg.ResourceSCfg().AsMapInterface()
|
|
case STATS_JSON:
|
|
mp = cfg.StatSCfg().AsMapInterface()
|
|
case THRESHOLDS_JSON:
|
|
mp = cfg.ThresholdSCfg().AsMapInterface()
|
|
case RouteSJson:
|
|
mp = cfg.RouteSCfg().AsMapInterface()
|
|
case SURETAX_JSON:
|
|
mp = cfg.SureTaxCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case DispatcherSJson:
|
|
mp = cfg.DispatcherSCfg().AsMapInterface()
|
|
case RegistrarCJson:
|
|
mp = cfg.RegistrarCCfg().AsMapInterface()
|
|
case LoaderJson:
|
|
mp = cfg.LoaderCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case CgrLoaderCfgJson:
|
|
mp = cfg.LoaderCgrCfg().AsMapInterface()
|
|
case CgrMigratorCfgJson:
|
|
mp = cfg.MigratorCgrCfg().AsMapInterface()
|
|
case ApierS:
|
|
mp = cfg.ApierCfg().AsMapInterface()
|
|
case EEsJson:
|
|
mp = cfg.EEsCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ERsJson:
|
|
mp = cfg.ERsCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case SIPAgentJson:
|
|
mp = cfg.SIPAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case ConfigSJson:
|
|
mp = cfg.ConfigSCfg().AsMapInterface()
|
|
case APIBanCfgJson:
|
|
mp = cfg.APIBanCfg().AsMapInterface()
|
|
case SentryPeerCfgJson:
|
|
mp = cfg.SentryPeerCfg().AsMapInterface()
|
|
case RPCConnsJsonName:
|
|
mp = cfg.RPCConns().AsMapInterface()
|
|
case TemplatesJson:
|
|
mp = cfg.TemplatesCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case HttpAgentJson:
|
|
mp = cfg.HTTPAgentCfg().AsMapInterface(cfg.GeneralCfg().RSRSep)
|
|
case MAILER_JSN:
|
|
mp = cfg.MailerCfg().AsMapInterface()
|
|
case AnalyzerCfgJson:
|
|
mp = cfg.AnalyzerSCfg().AsMapInterface()
|
|
case CoreSCfgJson:
|
|
mp = cfg.CoreSCfg().AsMapInterface()
|
|
default:
|
|
return errors.New("Invalid section")
|
|
}
|
|
rplyMap = map[string]any{args.Section: mp}
|
|
*reply = utils.ToJSON(rplyMap)
|
|
return
|
|
}
|
|
|
|
// SetConfigFromJSONArgs the API params for V1SetConfigFromJSON
|
|
type SetConfigFromJSONArgs struct {
|
|
APIOpts map[string]any
|
|
Tenant string
|
|
Config string
|
|
DryRun bool
|
|
}
|
|
|
|
// V1SetConfigFromJSON reloads the sections of config
|
|
func (cfg *CGRConfig) V1SetConfigFromJSON(ctx *context.Context, args *SetConfigFromJSONArgs, reply *string) (err error) {
|
|
if len(args.Config) == 0 {
|
|
*reply = utils.OK
|
|
return
|
|
}
|
|
cfgV := cfg
|
|
if args.DryRun {
|
|
cfgV = cfg.Clone()
|
|
}
|
|
|
|
cfgV.reloadDPCache(sortedCfgSections...)
|
|
if err = cfgV.loadCfgFromJSONWithLocks(bytes.NewBufferString(args.Config), sortedCfgSections); err != nil {
|
|
return
|
|
}
|
|
|
|
// lock all sections
|
|
cfgV.rLockSections()
|
|
err = cfgV.checkConfigSanity()
|
|
cfgV.rUnlockSections() // unlock before checking the error
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !args.DryRun {
|
|
cfgV.reloadSections(sortedCfgSections...)
|
|
}
|
|
*reply = utils.OK
|
|
return
|
|
}
|
|
|
|
// Clone returns a deep copy of CGRConfig
|
|
func (cfg *CGRConfig) Clone() (cln *CGRConfig) {
|
|
cln = &CGRConfig{
|
|
DataFolderPath: cfg.DataFolderPath,
|
|
ConfigPath: cfg.ConfigPath,
|
|
|
|
dfltEvRdr: cfg.dfltEvRdr.Clone(),
|
|
dfltEvExp: cfg.dfltEvExp.Clone(),
|
|
loaderCfg: cfg.loaderCfg.Clone(),
|
|
httpAgentCfg: cfg.httpAgentCfg.Clone(),
|
|
rpcConns: cfg.rpcConns.Clone(),
|
|
templates: cfg.templates.Clone(),
|
|
generalCfg: cfg.generalCfg.Clone(),
|
|
dataDbCfg: cfg.dataDbCfg.Clone(),
|
|
storDbCfg: cfg.storDbCfg.Clone(),
|
|
tlsCfg: cfg.tlsCfg.Clone(),
|
|
cacheCfg: cfg.cacheCfg.Clone(),
|
|
listenCfg: cfg.listenCfg.Clone(),
|
|
httpCfg: cfg.httpCfg.Clone(),
|
|
filterSCfg: cfg.filterSCfg.Clone(),
|
|
ralsCfg: cfg.ralsCfg.Clone(),
|
|
schedulerCfg: cfg.schedulerCfg.Clone(),
|
|
cdrsCfg: cfg.cdrsCfg.Clone(),
|
|
sessionSCfg: cfg.sessionSCfg.Clone(),
|
|
fsAgentCfg: cfg.fsAgentCfg.Clone(),
|
|
kamAgentCfg: cfg.kamAgentCfg.Clone(),
|
|
asteriskAgentCfg: cfg.asteriskAgentCfg.Clone(),
|
|
diameterAgentCfg: cfg.diameterAgentCfg.Clone(),
|
|
radiusAgentCfg: cfg.radiusAgentCfg.Clone(),
|
|
dnsAgentCfg: cfg.dnsAgentCfg.Clone(),
|
|
attributeSCfg: cfg.attributeSCfg.Clone(),
|
|
chargerSCfg: cfg.chargerSCfg.Clone(),
|
|
resourceSCfg: cfg.resourceSCfg.Clone(),
|
|
statsCfg: cfg.statsCfg.Clone(),
|
|
thresholdSCfg: cfg.thresholdSCfg.Clone(),
|
|
routeSCfg: cfg.routeSCfg.Clone(),
|
|
sureTaxCfg: cfg.sureTaxCfg.Clone(),
|
|
dispatcherSCfg: cfg.dispatcherSCfg.Clone(),
|
|
registrarCCfg: cfg.registrarCCfg.Clone(),
|
|
loaderCgrCfg: cfg.loaderCgrCfg.Clone(),
|
|
migratorCgrCfg: cfg.migratorCgrCfg.Clone(),
|
|
mailerCfg: cfg.mailerCfg.Clone(),
|
|
analyzerSCfg: cfg.analyzerSCfg.Clone(),
|
|
apier: cfg.apier.Clone(),
|
|
ersCfg: cfg.ersCfg.Clone(),
|
|
eesCfg: cfg.eesCfg.Clone(),
|
|
sipAgentCfg: cfg.sipAgentCfg.Clone(),
|
|
configSCfg: cfg.configSCfg.Clone(),
|
|
apiBanCfg: cfg.apiBanCfg.Clone(),
|
|
sentryPeerCfg: cfg.sentryPeerCfg.Clone(),
|
|
coreSCfg: cfg.coreSCfg.Clone(),
|
|
|
|
cacheDP: make(map[string]utils.MapStorage),
|
|
}
|
|
cln.initChanels()
|
|
return
|
|
}
|
|
|
|
func (cfg *CGRConfig) reloadDPCache(sections ...string) {
|
|
cfg.cacheDPMux.Lock()
|
|
delete(cfg.cacheDP, utils.MetaAll)
|
|
for _, sec := range sections {
|
|
delete(cfg.cacheDP, sec)
|
|
}
|
|
cfg.cacheDPMux.Unlock()
|
|
}
|
|
|
|
// GetDataProvider returns the config as a data provider interface
|
|
func (cfg *CGRConfig) GetDataProvider() utils.MapStorage {
|
|
cfg.cacheDPMux.RLock()
|
|
val, has := cfg.cacheDP[utils.MetaAll]
|
|
cfg.cacheDPMux.RUnlock()
|
|
if !has || val == nil {
|
|
cfg.cacheDPMux.Lock()
|
|
val = utils.MapStorage(cfg.AsMapInterface(cfg.GeneralCfg().RSRSep))
|
|
cfg.cacheDP[utils.MetaAll] = val
|
|
cfg.cacheDPMux.Unlock()
|
|
}
|
|
return val
|
|
}
|