Add ConfigSv1 in Dispatcher

This commit is contained in:
TeoV
2019-04-18 12:23:57 +03:00
parent 55ee6a7c09
commit 3075b70d0b
10 changed files with 368 additions and 0 deletions

43
apier/v1/config.go Normal file
View File

@@ -0,0 +1,43 @@
/*
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 v1
import (
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
func NewConfigSv1(cfg *config.CGRConfig) *ConfigSv1 {
return &ConfigSv1{cfg: cfg}
}
// Exports RPC from ConfigSv1
type ConfigSv1 struct {
cfg *config.CGRConfig
}
func (cSv1 *ConfigSv1) GetJSONSection(section *config.StringWithArgDispatcher, reply *map[string]interface{}) (err error) {
return cSv1.cfg.V1GetConfigSection(section, reply)
}
// Call implements rpcclient.RpcClientConnection interface for internal RPC
func (cSv1 *ConfigSv1) Call(serviceMethod string,
args interface{}, reply interface{}) error {
return utils.APIerRPCCall(cSv1, serviceMethod, args, reply)
}

View File

@@ -21,6 +21,7 @@ package v1
import (
"time"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/dispatchers"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/sessions"
@@ -744,3 +745,17 @@ func (dS *DispatcherSServiceManagerV1) StopService(args dispatchers.ArgStartServ
func (dS *DispatcherSServiceManagerV1) ServiceStatus(args dispatchers.ArgStartServiceWithApiKey, reply *string) error {
return dS.dS.ServiceManagerV1ServiceStatus(args, reply)
}
func NewDispatcherConfigSv1(dps *dispatchers.DispatcherService) *DispatcherConfigSv1 {
return &DispatcherConfigSv1{dS: dps}
}
// Exports RPC from CDRsV1
type DispatcherConfigSv1 struct {
dS *dispatchers.DispatcherService
}
// Ping used to detreminate if component is active
func (dS *DispatcherConfigSv1) GetJSONSection(args *config.StringWithArgDispatcher, reply *map[string]interface{}) (err error) {
return dS.dS.ConfigSv1GetJSONSection(args, reply)
}

View File

@@ -1239,6 +1239,9 @@ func startDispatcherService(internalDispatcherSChan, internalAttributeSChan chan
server.RpcRegisterName(utils.CDRsV1,
v1.NewDispatcherSCDRsV1(dspS))
server.RpcRegisterName(utils.ConfigSv1,
v1.NewDispatcherConfigSv1(dspS))
internalDispatcherSChan <- dspS
}
@@ -1450,6 +1453,15 @@ func schedCDRsConns(internalCDRSChan, internalDispatcherSChan chan rpcclient.Rpc
engine.SetSchedCdrsConns(cdrsConn)
}
func initConfigSv1(internalConfigChan chan rpcclient.RpcClientConnection,
server *utils.Server) {
cfgSv1 := v1.NewConfigSv1(cfg)
if !cfg.DispatcherSCfg().Enabled {
server.RpcRegister(cfgSv1)
}
internalConfigChan <- cfgSv1
}
func memProfFile(memProfPath string) bool {
f, err := os.Create(memProfPath)
if err != nil {
@@ -1638,6 +1650,7 @@ func main() {
internalApierV1Chan := make(chan rpcclient.RpcClientConnection, 1)
internalApierV2Chan := make(chan rpcclient.RpcClientConnection, 1)
internalServeManagerChan := make(chan rpcclient.RpcClientConnection, 1)
internalConfigChan := make(chan rpcclient.RpcClientConnection, 1)
// init internalRPCSet
engine.IntRPC = engine.NewRPCClientSet()
@@ -1660,6 +1673,8 @@ func main() {
engine.IntRPC.AddInternalRPCClient(utils.SupplierSv1, internalSupplierSChan)
engine.IntRPC.AddInternalRPCClient(utils.ThresholdSv1, internalThresholdSChan)
engine.IntRPC.AddInternalRPCClient(utils.ServiceManagerV1, internalServeManagerChan)
engine.IntRPC.AddInternalRPCClient(utils.ServManagerV1, internalServeManagerChan)
engine.IntRPC.AddInternalRPCClient(utils.ConfigSv1, internalConfigChan)
}
// init CacheS
@@ -1675,6 +1690,8 @@ func main() {
// init SchedulerS
initSchedulerS(internalSchedSChan, srvManager, server)
initConfigSv1(internalConfigChan, server)
// Start Scheduler
if cfg.SchedulerCfg().Enabled {
go srvManager.StartScheduler(true)

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package config
import (
"encoding/json"
"errors"
"fmt"
"net/url"
@@ -216,6 +217,7 @@ func NewCGRConfigFromPath(path string) (*CGRConfig, error) {
if err != nil {
return nil, err
}
cfg.ConfigPath = path
if isUrl(path) {
return loadConfigFromHttp(cfg, path) // prefix protocol
}
@@ -296,6 +298,7 @@ func loadConfigFromHttp(cfg *CGRConfig, urlPaths string) (*CGRConfig, error) {
type CGRConfig struct {
MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file
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
dfltCdreProfile *CdreCfg // Default cdreConfig profile
@@ -1186,3 +1189,90 @@ func (cfg *CGRConfig) AnalyzerSCfg() *AnalyzerSCfg {
func (cfg *CGRConfig) ApierCfg() *ApierCfg {
return cfg.apier
}
// Call implements rpcclient.RpcClientConnection interface for internal RPC
func (cSv1 *CGRConfig) Call(serviceMethod string,
args interface{}, reply interface{}) error {
return utils.APIerRPCCall(cSv1, serviceMethod, args, reply)
}
type StringWithArgDispatcher struct {
*utils.ArgDispatcher
utils.TenantArg
Section string
}
//V1GetConfigSection will retrieve from CGRConfig a section
func (cfg *CGRConfig) V1GetConfigSection(args *StringWithArgDispatcher, reply *map[string]interface{}) (err error) {
var jsonString string
switch args.Section {
case GENERAL_JSN:
jsonString = utils.ToJSON(cfg.GeneralCfg())
case DATADB_JSN:
jsonString = utils.ToJSON(cfg.DataDbCfg())
case STORDB_JSN:
jsonString = utils.ToJSON(cfg.StorDbCfg())
case TlsCfgJson:
jsonString = utils.ToJSON(cfg.TlsCfg())
case CACHE_JSN:
jsonString = utils.ToJSON(cfg.CacheCfg())
case LISTEN_JSN:
jsonString = utils.ToJSON(cfg.ListenCfg())
case HTTP_JSN:
jsonString = utils.ToJSON(cfg.HTTPCfg())
case FILTERS_JSON:
jsonString = utils.ToJSON(cfg.FilterSCfg())
case RALS_JSN:
jsonString = utils.ToJSON(cfg.RalsCfg())
case SCHEDULER_JSN:
jsonString = utils.ToJSON(cfg.SchedulerCfg())
case CDRS_JSN:
jsonString = utils.ToJSON(cfg.CdrsCfg())
case SessionSJson:
jsonString = utils.ToJSON(cfg.SessionSCfg())
case FS_JSN:
jsonString = utils.ToJSON(cfg.FsAgentCfg())
case KamailioAgentJSN:
jsonString = utils.ToJSON(cfg.KamAgentCfg())
case AsteriskAgentJSN:
jsonString = utils.ToJSON(cfg.AsteriskAgentCfg())
case DA_JSN:
jsonString = utils.ToJSON(cfg.DiameterAgentCfg())
case RA_JSN:
jsonString = utils.ToJSON(cfg.RadiusAgentCfg())
case DNSAgentJson:
jsonString = utils.ToJSON(cfg.DNSAgentCfg())
case ATTRIBUTE_JSN:
jsonString = utils.ToJSON(cfg.AttributeSCfg())
case ChargerSCfgJson:
jsonString = utils.ToJSON(cfg.ChargerSCfg())
case RESOURCES_JSON:
jsonString = utils.ToJSON(cfg.ResourceSCfg())
case STATS_JSON:
jsonString = utils.ToJSON(cfg.StatSCfg())
case THRESHOLDS_JSON:
jsonString = utils.ToJSON(cfg.ThresholdSCfg())
case SupplierSJson:
jsonString = utils.ToJSON(cfg.SupplierSCfg())
case SURETAX_JSON:
jsonString = utils.ToJSON(cfg.SureTaxCfg())
case DispatcherJson:
jsonString = utils.ToJSON(cfg.DispatcherSCfg())
case LoaderJson:
jsonString = utils.ToJSON(cfg.LoaderCfg())
case CgrLoaderCfgJson:
jsonString = utils.ToJSON(cfg.LoaderCgrCfg())
case CgrMigratorCfgJson:
jsonString = utils.ToJSON(cfg.MigratorCgrCfg())
case Apier:
jsonString = utils.ToJSON(cfg.ApierCfg())
case CDRC_JSN:
jsonString = utils.ToJSON(cfg.CdrcProfiles)
case CDRE_JSN:
jsonString = utils.ToJSON(cfg.CdreProfiles)
default:
return errors.New("Invalid section")
}
json.Unmarshal([]byte(jsonString), reply)
return
}

View File

@@ -1754,3 +1754,30 @@ func TestCgrCfgJSONDefaultApierCfg(t *testing.T) {
t.Errorf("received: %+v, expecting: %+v", cgrCfg.apier, aCfg)
}
}
func TestCgrCfgV1GetConfigSection(t *testing.T) {
JSN_CFG := `
{
"listen": {
"rpc_json": ":2012",
"rpc_gob": ":2013",
"http": ":2080",
}
}`
expected := map[string]interface{}{
"HTTPListen": ":2080",
"HTTPTLSListen": "127.0.0.1:2280",
"RPCGOBListen": ":2013",
"RPCGOBTLSListen": "127.0.0.1:2023",
"RPCJSONListen": ":2012",
"RPCJSONTLSListen": "127.0.0.1:2022",
}
var rcv map[string]interface{}
if cgrCfg, err := NewCGRConfigFromJsonStringWithDefaults(JSN_CFG); err != nil {
t.Error(err)
} else if err := cgrCfg.V1GetConfigSection(&StringWithArgDispatcher{Section: LISTEN_JSN}, &rcv); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, rcv) {
t.Errorf("Expected: %+v, received: %+v", expected, rcv)
}
}

View File

@@ -0,0 +1,66 @@
/*
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 console
import (
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
func init() {
c := &CmdGetJSONConfig{
name: "get_json_section",
rpcMethod: utils.ConfigSv1GetJSONSection,
rpcParams: &config.StringWithArgDispatcher{},
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
}
// Commander implementation
type CmdGetJSONConfig struct {
name string
rpcMethod string
rpcParams *config.StringWithArgDispatcher
*CommandExecuter
}
func (self *CmdGetJSONConfig) Name() string {
return self.name
}
func (self *CmdGetJSONConfig) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetJSONConfig) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &config.StringWithArgDispatcher{}
}
return self.rpcParams
}
func (self *CmdGetJSONConfig) PostprocessRpcParams() error {
return nil
}
func (self *CmdGetJSONConfig) RpcResult() interface{} {
var s map[string]interface{}
return &s
}

View File

@@ -17,3 +17,4 @@ cgrates.org,ATTR_API_SCHD_AUTH,*auth,*string:~APIKey:sched12345,,,APIMethods,*co
cgrates.org,ATTR_API_CDRS_AUTH,*auth,*string:~APIKey:cdrs12345,,,APIMethods,*constant,CDRsV1.Ping&CDRsV1.ProcessEvent&CDRsV1.GetCDRs&CDRsV1.CountCDRs&CDRsV1.ProcessCDR&CDRsV1.ProcessExternalCDR,false,20
cgrates.org,ATTR_API_DSP_AUTH,*auth,*string:~APIKey:dsp12345,,,APIMethods,*constant,DispatcherSv1.Ping&DispatcherSv1.GetProfileForEvent,false,20
cgrates.org,ATTR_API_PSE_AUTH,*auth,*string:~APIKey:pse12345,,,APIMethods,*constant,SessionSv1.Ping&SessionSv1.AuthorizeEvent&SessionSv1.AuthorizeEventWithDigest&SessionSv1.InitiateSession&SessionSv1.InitiateSessionWithDigest&SessionSv1.UpdateSession&SessionSv1.SyncSessions&SessionSv1.TerminateSession&SessionSv1.ProcessCDR&SessionSv1.ProcessEvent&SessionSv1.GetActiveSessions&SessionSv1.GetActiveSessionsCount&SessionSv1.ForceDisconnect&SessionSv1.GetPassiveSessions&SessionSv1.GetPassiveSessionsCount&SessionSv1.ReplicateSessions&SessionSv1.SetPassiveSession&AttributeSv1.ProcessEvent&Responder.Debit&ResourceSv1.AllocateResources&ChargerSv1.ProcessEvent&Responder.MaxDebit,false,20
cgrates.org,ATTR_API_CFG_AUTH,*auth,*string:~APIKey:cfg12345,,,APIMethods,*constant,ConfigSv1.GetJSONSection,false,20
1 #Tenant ID Contexts FilterIDs ActivationInterval AttributeFilterIDs FieldName Type Value Blocker Weight
17 cgrates.org ATTR_API_CDRS_AUTH *auth *string:~APIKey:cdrs12345 APIMethods *constant CDRsV1.Ping&CDRsV1.ProcessEvent&CDRsV1.GetCDRs&CDRsV1.CountCDRs&CDRsV1.ProcessCDR&CDRsV1.ProcessExternalCDR false 20
18 cgrates.org ATTR_API_DSP_AUTH *auth *string:~APIKey:dsp12345 APIMethods *constant DispatcherSv1.Ping&DispatcherSv1.GetProfileForEvent false 20
19 cgrates.org ATTR_API_PSE_AUTH *auth *string:~APIKey:pse12345 APIMethods *constant SessionSv1.Ping&SessionSv1.AuthorizeEvent&SessionSv1.AuthorizeEventWithDigest&SessionSv1.InitiateSession&SessionSv1.InitiateSessionWithDigest&SessionSv1.UpdateSession&SessionSv1.SyncSessions&SessionSv1.TerminateSession&SessionSv1.ProcessCDR&SessionSv1.ProcessEvent&SessionSv1.GetActiveSessions&SessionSv1.GetActiveSessionsCount&SessionSv1.ForceDisconnect&SessionSv1.GetPassiveSessions&SessionSv1.GetPassiveSessionsCount&SessionSv1.ReplicateSessions&SessionSv1.SetPassiveSession&AttributeSv1.ProcessEvent&Responder.Debit&ResourceSv1.AllocateResources&ChargerSv1.ProcessEvent&Responder.MaxDebit false 20
20 cgrates.org ATTR_API_CFG_AUTH *auth *string:~APIKey:cfg12345 APIMethods *constant ConfigSv1.GetJSONSection false 20

40
dispatchers/config.go Normal file
View File

@@ -0,0 +1,40 @@
/*
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 dispatchers
import (
"time"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
func (dS *DispatcherService) ConfigSv1GetJSONSection(args *config.StringWithArgDispatcher, reply *map[string]interface{}) (err error) {
if args.ArgDispatcher == nil {
return utils.NewErrMandatoryIeMissing("ArgDispatcher")
}
if dS.attrS != nil {
if err = dS.authorize(utils.ConfigSv1GetJSONSection,
args.Tenant, args.APIKey, utils.TimePointer(time.Now())); err != nil {
return
}
}
return dS.Dispatch(&utils.CGREvent{Tenant: args.Tenant},
utils.MetaConfig, args.RouteID, utils.ConfigSv1GetJSONSection, args, reply)
}

View File

@@ -0,0 +1,63 @@
// +build integration
/*
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 dispatchers
import (
"reflect"
"testing"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
var sTestsDspConfig = []func(t *testing.T){
testDspConfigSv1GetJSONSection,
}
//Test start here
func TestDspConfigITMySQL(t *testing.T) {
testDsp(t, sTestsDspConfig, "TestDspConfigITMySQL", "all", "all2", "dispatchers", "tutorial", "oldtutorial", "dispatchers")
}
func testDspConfigSv1GetJSONSection(t *testing.T) {
expected := map[string]interface{}{
"HTTPListen": ":6080",
"HTTPTLSListen": "127.0.0.1:2280",
"RPCGOBListen": ":6013",
"RPCGOBTLSListen": "127.0.0.1:2023",
"RPCJSONListen": ":6012",
"RPCJSONTLSListen": "127.0.0.1:2022",
}
var reply map[string]interface{}
if err := dispEngine.RCP.Call(utils.ConfigSv1GetJSONSection, &config.StringWithArgDispatcher{
TenantArg: utils.TenantArg{
Tenant: "cgrates.org",
},
ArgDispatcher: &utils.ArgDispatcher{
APIKey: utils.StringPointer("cfg12345"),
},
Section: "listen",
}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, reply) {
t.Errorf("Expected: %+v, received: %+v", expected, reply)
}
}

View File

@@ -390,6 +390,7 @@ const (
MetaAttributes = "*attributes"
MetaServiceManager = "*servicemanager"
MetaChargers = "*chargers"
MetaConfig = "*config"
MetaDispatchers = "*dispatchers"
MetaDispatcherHosts = "*dispatcher_hosts"
MetaResources = "*resources"
@@ -752,6 +753,11 @@ const (
ServiceManagerV1Ping = "ServiceManagerV1.Ping"
)
const (
ConfigSv1 = "ConfigSv1"
ConfigSv1GetJSONSection = "ConfigSv1.GetJSONSection"
)
// SupplierS APIs
const (
SupplierSv1GetSuppliers = "SupplierSv1.GetSuppliers"