mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 21:59:53 +05:00
Also added tests for it. Added comment to the *HierarchyPath.AsString() function, addressing the issue of not being able to retrieve the element when the root path is equal to the path that is being processed.
628 lines
28 KiB
Go
628 lines
28 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 (
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
// Exported in cgr-engine
|
|
func (cfg *CGRConfig) CheckConfigSanity() error {
|
|
return cfg.checkConfigSanity()
|
|
}
|
|
|
|
func (cfg *CGRConfig) checkConfigSanity() error {
|
|
// Rater checks
|
|
if cfg.ralsCfg.Enabled {
|
|
for _, connID := range cfg.ralsCfg.StatSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.StatService, utils.RALService)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RALService, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.ralsCfg.ThresholdSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ThresholdS, utils.RALService)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RALService, connID)
|
|
}
|
|
}
|
|
}
|
|
// CDRServer checks
|
|
if cfg.cdrsCfg.Enabled {
|
|
for _, connID := range cfg.cdrsCfg.ChargerSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.chargerSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ChargerS, utils.CDRs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.CDRs, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.cdrsCfg.RaterConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.ralsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.RALService, utils.CDRs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.CDRs, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.cdrsCfg.AttributeSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.CDRs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.CDRs, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.cdrsCfg.StatSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.StatService, utils.CDRs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.CDRs, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.cdrsCfg.ThresholdSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ThresholdS, utils.CDRs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.CDRs, connID)
|
|
}
|
|
}
|
|
for _, cdrePrfl := range cfg.cdrsCfg.OnlineCDRExports {
|
|
if _, hasIt := cfg.CdreProfiles[cdrePrfl]; !hasIt {
|
|
return fmt.Errorf("<%s> cannot find CDR export template with ID: <%s>", utils.CDRs, cdrePrfl)
|
|
}
|
|
}
|
|
for prfl, cdre := range cfg.CdreProfiles {
|
|
for _, field := range cdre.Fields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.CDRs, utils.NewErrMandatoryIeMissing(utils.Path), prfl, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Loaders sanity checks
|
|
for _, ldrSCfg := range cfg.loaderCfg {
|
|
if !ldrSCfg.Enabled {
|
|
continue
|
|
}
|
|
for _, dir := range []string{ldrSCfg.TpInDir, ldrSCfg.TpOutDir} {
|
|
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
|
return fmt.Errorf("<%s> nonexistent folder: %s", utils.LoaderS, dir)
|
|
}
|
|
}
|
|
for _, data := range ldrSCfg.Data {
|
|
if !posibleLoaderTypes.Has(data.Type) {
|
|
return fmt.Errorf("<%s> unsupported data type %s", utils.LoaderS, data.Type)
|
|
}
|
|
|
|
for _, field := range data.Fields {
|
|
if field.Type != utils.META_COMPOSED && field.Type != utils.MetaString && field.Type != utils.MetaVariable {
|
|
return fmt.Errorf("<%s> invalid field type %s for %s at %s", utils.LoaderS, field.Type, data.Type, field.Tag)
|
|
}
|
|
if field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.LoaderS, utils.NewErrMandatoryIeMissing(utils.Path), data.Type, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// SessionS checks
|
|
if cfg.sessionSCfg.Enabled {
|
|
if cfg.sessionSCfg.TerminateAttempts < 1 {
|
|
return fmt.Errorf("<%s> 'terminate_attempts' should be at least 1", utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.ChargerSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.chargerSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ChargerS, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.RALsConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.ralsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.RALService, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.ResSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.resourceSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ResourceS, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.ThreshSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ThresholdS, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.StatSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.StatService, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.SupplSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.supplierSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SupplierS, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.AttrSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.CDRsConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.cdrsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.CDRs, utils.SessionS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.sessionSCfg.ReplicationConns {
|
|
if _, has := cfg.rpcConns[connID]; !has {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SessionS, connID)
|
|
}
|
|
}
|
|
if cfg.cacheCfg[utils.CacheClosedSessions].Limit == 0 {
|
|
return fmt.Errorf("<%s> %s needs to be != 0, received: %d", utils.CacheS, utils.CacheClosedSessions, cfg.cacheCfg[utils.CacheClosedSessions].Limit)
|
|
}
|
|
for alfld := range cfg.sessionSCfg.AlterableFields {
|
|
if utils.ProtectedSFlds.Has(alfld) {
|
|
return fmt.Errorf("<%s> the following protected field can't be altered by session: <%s>", utils.SessionS, alfld)
|
|
}
|
|
}
|
|
}
|
|
|
|
// FreeSWITCHAgent checks
|
|
if cfg.fsAgentCfg.Enabled {
|
|
if len(cfg.fsAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.FreeSWITCHAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.fsAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.FreeSWITCHAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.FreeSWITCHAgent, connID)
|
|
}
|
|
}
|
|
}
|
|
// KamailioAgent checks
|
|
if cfg.kamAgentCfg.Enabled {
|
|
if len(cfg.kamAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.KamailioAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.kamAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.KamailioAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.KamailioAgent, connID)
|
|
}
|
|
}
|
|
}
|
|
// AsteriskAgent checks
|
|
if cfg.asteriskAgentCfg.Enabled {
|
|
if len(cfg.asteriskAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.AsteriskAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.asteriskAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.AsteriskAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.AsteriskAgent, connID)
|
|
}
|
|
}
|
|
}
|
|
// DAgent checks
|
|
if cfg.diameterAgentCfg.Enabled {
|
|
if len(cfg.diameterAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.DiameterAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.diameterAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.DiameterAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.DiameterAgent, connID)
|
|
}
|
|
}
|
|
for prf, tmp := range cfg.diameterAgentCfg.Templates {
|
|
for _, field := range tmp {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for template %s at %s", utils.DiameterAgent, utils.NewErrMandatoryIeMissing(utils.Path), prf, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
for _, req := range cfg.diameterAgentCfg.RequestProcessors {
|
|
for _, field := range req.RequestFields {
|
|
if field.Type != utils.META_NONE &&
|
|
field.Type != utils.MetaTemplate &&
|
|
field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.DiameterAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
for _, field := range req.ReplyFields {
|
|
if field.Type != utils.META_NONE &&
|
|
field.Type != utils.MetaTemplate &&
|
|
field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.DiameterAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Radius Agent
|
|
if cfg.radiusAgentCfg.Enabled {
|
|
if len(cfg.radiusAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.RadiusAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.radiusAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.RadiusAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RadiusAgent, connID)
|
|
}
|
|
}
|
|
for _, req := range cfg.radiusAgentCfg.RequestProcessors {
|
|
for _, field := range req.RequestFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.RadiusAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
for _, field := range req.ReplyFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.RadiusAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//DNS Agent
|
|
if cfg.dnsAgentCfg.Enabled {
|
|
if len(cfg.dnsAgentCfg.SessionSConns) == 0 {
|
|
return fmt.Errorf("<%s> no %s connections defined",
|
|
utils.DNSAgent, utils.SessionS)
|
|
}
|
|
for _, connID := range cfg.dnsAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.DNSAgent)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.DNSAgent, connID)
|
|
}
|
|
}
|
|
for _, req := range cfg.dnsAgentCfg.RequestProcessors {
|
|
for _, field := range req.RequestFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.DNSAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
for _, field := range req.ReplyFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.DNSAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// HTTPAgent checks
|
|
for _, httpAgentCfg := range cfg.httpAgentCfg {
|
|
// httpAgent checks
|
|
for _, connID := range httpAgentCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> HTTPAgent Template.", utils.SessionS, httpAgentCfg.ID)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> template with ID <%s> has connection with id: <%s> not defined", utils.HTTPAgent, httpAgentCfg.ID, connID)
|
|
}
|
|
}
|
|
if !utils.SliceHasMember([]string{utils.MetaUrl, utils.MetaXml}, httpAgentCfg.RequestPayload) {
|
|
return fmt.Errorf("<%s> unsupported request payload %s", utils.HTTPAgent, httpAgentCfg.RequestPayload)
|
|
}
|
|
if !utils.SliceHasMember([]string{utils.MetaTextPlain, utils.MetaXml}, httpAgentCfg.ReplyPayload) {
|
|
return fmt.Errorf("<%s> unsupported reply payload %s", utils.HTTPAgent, httpAgentCfg.ReplyPayload)
|
|
}
|
|
for _, req := range httpAgentCfg.RequestProcessors {
|
|
for _, field := range req.RequestFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.HTTPAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
for _, field := range req.ReplyFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.HTTPAgent, utils.NewErrMandatoryIeMissing(utils.Path), req.ID, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if cfg.attributeSCfg.Enabled {
|
|
if cfg.attributeSCfg.ProcessRuns < 1 {
|
|
return fmt.Errorf("<%s> process_runs needs to be bigger than 0", utils.AttributeS)
|
|
}
|
|
}
|
|
if cfg.chargerSCfg.Enabled {
|
|
for _, connID := range cfg.chargerSCfg.AttributeSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.ChargerS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.ChargerS, connID)
|
|
}
|
|
}
|
|
}
|
|
// ResourceLimiter checks
|
|
if cfg.resourceSCfg.Enabled {
|
|
for _, connID := range cfg.resourceSCfg.ThresholdSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ThresholdS, utils.ResourceS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.ResourceS, connID)
|
|
}
|
|
}
|
|
}
|
|
// StatS checks
|
|
if cfg.statsCfg.Enabled {
|
|
for _, connID := range cfg.statsCfg.ThresholdSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ThresholdS, utils.StatS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.StatS, connID)
|
|
}
|
|
}
|
|
}
|
|
// SupplierS checks
|
|
if cfg.supplierSCfg.Enabled {
|
|
for _, connID := range cfg.supplierSCfg.AttributeSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.SupplierS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SupplierS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.supplierSCfg.StatSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.StatService, utils.SupplierS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SupplierS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.supplierSCfg.ResourceSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.resourceSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ResourceS, utils.SupplierS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SupplierS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.supplierSCfg.RALsConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.ralsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.RALService, utils.SupplierS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SupplierS, connID)
|
|
}
|
|
}
|
|
}
|
|
// Scheduler check connection with CDR Server
|
|
if cfg.schedulerCfg.Enabled {
|
|
for _, connID := range cfg.schedulerCfg.CDRsConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.cdrsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.CDRs, utils.SchedulerS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.SchedulerS, connID)
|
|
}
|
|
}
|
|
}
|
|
// EventReader sanity checks
|
|
if cfg.ersCfg.Enabled {
|
|
for _, connID := range cfg.ersCfg.SessionSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.sessionSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SessionS, utils.ERs)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.ERs, connID)
|
|
}
|
|
}
|
|
for _, rdr := range cfg.ersCfg.Readers {
|
|
if !possibleReaderTypes.Has(rdr.Type) {
|
|
return fmt.Errorf("<%s> unsupported data type: %s for reader with ID: %s", utils.ERs, rdr.Type, rdr.ID)
|
|
}
|
|
|
|
switch rdr.Type {
|
|
case utils.META_NONE:
|
|
case utils.MetaFileCSV, utils.MetaPartialCSV, utils.MetaFlatstore:
|
|
for _, dir := range []string{rdr.ProcessedPath, rdr.SourcePath} {
|
|
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
|
return fmt.Errorf("<%s> nonexistent folder: %s for reader with ID: %s", utils.ERs, dir, rdr.ID)
|
|
}
|
|
}
|
|
if rdr.FieldSep == utils.EmptyString {
|
|
return fmt.Errorf("<%s> empty FieldSep for reader with ID: %s", utils.ERs, rdr.ID)
|
|
}
|
|
case utils.MetaKafkajsonMap:
|
|
if rdr.RunDelay > 0 {
|
|
return fmt.Errorf("<%s> the RunDelay field can not be bigger than zero for reader with ID: %s", utils.ERs, rdr.ID)
|
|
}
|
|
case utils.MetaFileXML, utils.MetaFileFWV:
|
|
for _, dir := range []string{rdr.ProcessedPath, rdr.SourcePath} {
|
|
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
|
return fmt.Errorf("<%s> nonexistent folder: %s for reader with ID: %s", utils.ERs, dir, rdr.ID)
|
|
}
|
|
}
|
|
}
|
|
for _, field := range rdr.CacheDumpFields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.ERs, utils.NewErrMandatoryIeMissing(utils.Path), rdr.ID, field.Tag)
|
|
}
|
|
}
|
|
for _, field := range rdr.Fields {
|
|
if field.Type != utils.META_NONE && field.Path == utils.EmptyString {
|
|
return fmt.Errorf("<%s> %s for %s at %s", utils.ERs, utils.NewErrMandatoryIeMissing(utils.Path), rdr.ID, field.Tag)
|
|
}
|
|
|
|
// The following sanity check prevents a "slice bounds out of range" panic.
|
|
if rdr.Type == utils.MetaFileXML && len(field.Value) != 0 &&
|
|
!utils.IsSliceMember([]string{utils.META_NONE, utils.META_CONSTANT}, field.Type) {
|
|
|
|
// Find the minimum rule length for dynamic RSRParser within the field value.
|
|
minRuleLength := math.MaxInt
|
|
for _, parser := range field.Value {
|
|
if !strings.HasPrefix(parser.Rules, utils.DynamicDataPrefix) {
|
|
continue
|
|
}
|
|
ruleLen := len(strings.Split(parser.Rules, utils.NestingSep))
|
|
minRuleLength = min(minRuleLength, ruleLen)
|
|
}
|
|
|
|
// If a dynamic RSRParser is found, verify xml_root_path length against minRuleLength.
|
|
if minRuleLength != math.MaxInt && len(rdr.XmlRootPath) >= minRuleLength {
|
|
return fmt.Errorf("<%s> %s for reader %s at %s",
|
|
utils.ERs,
|
|
"xml_root_path length exceeds value rule elements",
|
|
rdr.ID, field.Tag)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// StorDB sanity checks
|
|
if cfg.storDbCfg.Type == utils.MetaPostgres {
|
|
if !utils.IsSliceMember([]string{utils.PostgressSSLModeDisable, utils.PostgressSSLModeAllow,
|
|
utils.PostgressSSLModePrefer, utils.PostgressSSLModeRequire, utils.PostgressSSLModeVerifyCa,
|
|
utils.PostgressSSLModeVerifyFull}, cfg.storDbCfg.SSLMode) {
|
|
return fmt.Errorf("<%s> unsuported sslmode for storDB", utils.StorDB)
|
|
}
|
|
}
|
|
// DataDB sanity checks
|
|
if cfg.dataDbCfg.DataDbType == utils.MetaInternal {
|
|
for key, config := range cfg.cacheCfg {
|
|
if utils.CacheDataDBPartitions.Has(key) && config.Limit != 0 {
|
|
return fmt.Errorf("<%s> %s needs to be 0 when DataBD is *internal, received : %d", utils.CacheS, key, config.Limit)
|
|
}
|
|
}
|
|
if cfg.resourceSCfg.Enabled == true && cfg.resourceSCfg.StoreInterval != -1 {
|
|
return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.ResourceS, cfg.resourceSCfg.StoreInterval)
|
|
}
|
|
if cfg.statsCfg.Enabled == true && cfg.statsCfg.StoreInterval != -1 {
|
|
return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.StatS, cfg.statsCfg.StoreInterval)
|
|
}
|
|
if cfg.thresholdSCfg.Enabled == true && cfg.thresholdSCfg.StoreInterval != -1 {
|
|
return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.ThresholdS, cfg.thresholdSCfg.StoreInterval)
|
|
}
|
|
}
|
|
for item, val := range cfg.dataDbCfg.Items {
|
|
if val.Remote == true && len(cfg.dataDbCfg.RmtConns) == 0 {
|
|
return fmt.Errorf("remote connections required by: <%s>", item)
|
|
}
|
|
if val.Replicate == true && len(cfg.dataDbCfg.RplConns) == 0 {
|
|
return fmt.Errorf("replicate connections required by: <%s>", item)
|
|
}
|
|
}
|
|
// APIer sanity checks
|
|
for _, connID := range cfg.apier.AttributeSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.APIerSv1)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.APIerSv1, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.apier.SchedulerConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.schedulerCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.SchedulerS, utils.APIerSv1)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.APIerSv1, connID)
|
|
}
|
|
}
|
|
// Dispatcher sanity check
|
|
if cfg.dispatcherSCfg.Enabled {
|
|
for _, connID := range cfg.dispatcherSCfg.AttributeSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.attributeSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.AttributeS, utils.DispatcherS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.DispatcherS, connID)
|
|
}
|
|
}
|
|
}
|
|
// Cache partitions check
|
|
for cacheID := range cfg.cacheCfg {
|
|
if !utils.CachePartitions.Has(cacheID) {
|
|
return fmt.Errorf("<%s> partition <%s> not defined", utils.CacheS, cacheID)
|
|
}
|
|
}
|
|
// FilterS sanity check
|
|
for _, connID := range cfg.filterSCfg.StatSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.StatS, utils.FilterS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.FilterS, connID)
|
|
}
|
|
}
|
|
for _, connID := range cfg.filterSCfg.ResourceSConns {
|
|
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.resourceSCfg.Enabled {
|
|
return fmt.Errorf("<%s> not enabled but requested by <%s> component.", utils.ResourceS, utils.FilterS)
|
|
}
|
|
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
|
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.FilterS, connID)
|
|
}
|
|
}
|
|
return nil
|
|
}
|