From 4bd036890975770d52ecb1b8d54d59e78b31515e Mon Sep 17 00:00:00 2001 From: adragusin Date: Mon, 4 May 2020 17:58:32 +0300 Subject: [PATCH] Added AsMapInterface method for some config fields --- config/cdrecfg.go | 10 +- config/cdrecfg_test.go | 50 +++++++++ config/config.go | 16 +-- config/config_test.go | 67 +++++++++++ config/datadbcfg.go | 19 +++- config/datadbcfg_test.go | 224 +++++++++++++++++++++++++++++++++++++ config/diametercfg.go | 6 +- config/dnsagntcfg.go | 35 ++++-- config/erscfg.go | 10 +- config/fctemplate.go | 94 +++++++++++----- config/filterscfg_test.go | 26 +++++ config/generalcfg.go | 27 ++++- config/httpagntcfg.go | 14 ++- config/httpagntcfg_test.go | 73 ++++++++++++ config/httpcfg.go | 7 +- config/httpcfg_test.go | 35 ++++++ config/loaderscfg.go | 29 +++-- config/loaderscfg_test.go | 75 +++++++++++++ config/radiuscfg.go | 4 +- config/ralscfg.go | 23 +++- config/ralscfg_test.go | 58 ++++++++++ config/rpcconn.go | 14 +-- config/rpcconn_test.go | 39 +++++++ config/stordbcfg.go | 12 +- config/stordbcfg_test.go | 56 ++++++++++ config/tlscfg_test.go | 66 +++++++++++ utils/consts.go | 22 ++-- 27 files changed, 1012 insertions(+), 99 deletions(-) diff --git a/config/cdrecfg.go b/config/cdrecfg.go index 9e92db639..f4b5a556f 100644 --- a/config/cdrecfg.go +++ b/config/cdrecfg.go @@ -18,7 +18,9 @@ along with this program. If not, see package config -import "github.com/cgrates/cgrates/utils" +import ( + "github.com/cgrates/cgrates/utils" +) // One instance of CdrExporter type CdreCfg struct { @@ -93,10 +95,10 @@ func (self *CdreCfg) Clone() *CdreCfg { return clnCdre } -func (cdre *CdreCfg) AsMapInterface() map[string]interface{} { +func (cdre *CdreCfg) AsMapInterface(separator string) map[string]interface{} { fields := make([]map[string]interface{}, len(cdre.Fields)) for i, item := range cdre.Fields { - fields[i] = item.AsMapInterface() + fields[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -107,7 +109,7 @@ func (cdre *CdreCfg) AsMapInterface() map[string]interface{} { utils.AttributeSContextCfg: cdre.AttributeSContext, utils.SynchronousCfg: cdre.Synchronous, utils.AttemptsCfg: cdre.Attempts, - utils.FieldSeparatorCfg: cdre.FieldSeparator, + utils.FieldSeparatorCfg: string(cdre.FieldSeparator), utils.FieldsCfg: fields, } } diff --git a/config/cdrecfg_test.go b/config/cdrecfg_test.go index c6bf8884a..57ca650de 100644 --- a/config/cdrecfg_test.go +++ b/config/cdrecfg_test.go @@ -135,3 +135,53 @@ func TestCdreCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(lstcfg)) } } + +func TestCdreCfgAsMapInterface(t *testing.T) { + var cdre CdreCfg + cfgJSONStr := `{ + "cdre": { + "*default": { + "export_format": "*file_csv", + "export_path": "/var/spool/cgrates/cdre", + "filters" :[], + "tenant": "", + "synchronous": false, + "attempts": 1, + "field_separator": ",", + "attributes_context": "", + "fields": [ + {"path": "*exp.CGRID", "type": "*variable", "value": "~*req.CGRID"}, + ], + }, + }, +}` + eMap := map[string]interface{}{ + "export_format": "*file_csv", + "export_path": "/var/spool/cgrates/cdre", + "filters": []string{}, + "tenant": "", + "synchronous": false, + "attempts": 1, + "field_separator": ",", + "attributes_context": "", + "fields": []map[string]interface{}{ + { + "path": "*exp.CGRID", + "tag": "*exp.CGRID", + "type": "*variable", + "value": "~*req.CGRID", + }, + }, + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if cdreCfg, err := jsnCfg.CdreJsonCfgs(); err != nil { + t.Error(err) + } else if err = cdre.loadFromJsonCfg(cdreCfg["*default"], utils.EmptyString); err != nil { + t.Error(err) + } else if rcv := cdre.AsMapInterface(""); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("\nExpected: %+v\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } + +} diff --git a/config/config.go b/config/config.go index d9c48eb6f..ce41b4b45 100755 --- a/config/config.go +++ b/config/config.go @@ -1466,7 +1466,7 @@ func (cfg *CGRConfig) reloadSections(sections ...string) (err error) { return } -func (cfg *CGRConfig) AsMapInterface() map[string]interface{} { +func (cfg *CGRConfig) AsMapInterface(separator string) map[string]interface{} { rpcConns := make(map[string]map[string]interface{}, len(cfg.rpcConns)) for key, val := range cfg.rpcConns { rpcConns[key] = val.AsMapInterface() @@ -1474,17 +1474,17 @@ func (cfg *CGRConfig) AsMapInterface() map[string]interface{} { cdreProfiles := make(map[string]map[string]interface{}) for key, val := range cfg.CdreProfiles { - cdreProfiles[key] = val.AsMapInterface() + cdreProfiles[key] = val.AsMapInterface(separator) } loaderCfg := make([]map[string]interface{}, len(cfg.loaderCfg)) for i, item := range cfg.loaderCfg { - loaderCfg[i] = item.AsMapInterface() + loaderCfg[i] = item.AsMapInterface(separator) } httpAgentCfg := make([]map[string]interface{}, len(cfg.httpAgentCfg)) for i, item := range cfg.httpAgentCfg { - httpAgentCfg[i] = item.AsMapInterface() + httpAgentCfg[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -1508,9 +1508,9 @@ func (cfg *CGRConfig) AsMapInterface() map[string]interface{} { utils.FsAgentCfg: cfg.fsAgentCfg.AsMapInterface(), utils.KamAgentCfg: cfg.kamAgentCfg.AsMapInterface(), utils.AsteriskAgentCfg: cfg.asteriskAgentCfg.AsMapInterface(), - utils.DiameterAgentCfg: cfg.diameterAgentCfg.AsMapInterface(), - utils.RadiusAgentCfg: cfg.radiusAgentCfg.AsMapInterface(), - utils.DnsAgentCfg: cfg.dnsAgentCfg.AsMapInterface(), + utils.DiameterAgentCfg: cfg.diameterAgentCfg.AsMapInterface(separator), + utils.RadiusAgentCfg: cfg.radiusAgentCfg.AsMapInterface(separator), + utils.DnsAgentCfg: cfg.dnsAgentCfg.AsMapInterface(separator), utils.AttributeSCfg: cfg.attributeSCfg.AsMapInterface(), utils.ChargerSCfg: cfg.chargerSCfg.AsMapInterface(), utils.ResourceSCfg: cfg.resourceSCfg.AsMapInterface(), @@ -1524,6 +1524,6 @@ func (cfg *CGRConfig) AsMapInterface() map[string]interface{} { utils.MailerCfg: cfg.mailerCfg.AsMapInterface(), utils.AnalyzerSCfg: cfg.analyzerSCfg.AsMapInterface(), utils.Apier: cfg.apier.AsMapInterface(), - utils.ErsCfg: cfg.ersCfg.AsMapInterface(), + utils.ErsCfg: cfg.ersCfg.AsMapInterface(separator), } } diff --git a/config/config_test.go b/config/config_test.go index 936d7d96c..21d6f9659 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -1851,3 +1851,70 @@ func TestCheckConfigSanity(t *testing.T) { t.Errorf("Expecting: %+q received: %+q", expected, err) } } + +func TestGeneralCfg(t *testing.T) { + var gencfg GeneralCfg + cfgJSONStr := `{ + "general": { + "node_id": "", + "logger":"*syslog", + "log_level": 6, + "http_skip_tls_verify": false, + "rounding_decimals": 5, + "dbdata_encoding": "*msgpack", + "tpexport_dir": "/var/spool/cgrates/tpe", + "poster_attempts": 3, + "failed_posts_dir": "/var/spool/cgrates/failed_posts", + "failed_posts_ttl": "5s", + "default_request_type": "*rated", + "default_category": "call", + "default_tenant": "cgrates.org", + "default_timezone": "Local", + "default_caching":"*reload", + "connect_attempts": 5, + "reconnects": -1, + "connect_timeout": "1s", + "reply_timeout": "2s", + "locking_timeout": "0", + "digest_separator": ",", + "digest_equal": ":", + "rsr_separator": ";", + "max_parralel_conns": 100, + }, +}` + eMap := map[string]interface{}{ + "node_id": "", + "logger": "*syslog", + "log_level": 6, + "http_skip_tls_verify": false, + "rounding_decimals": 5, + "dbdata_encoding": "*msgpack", + "tpexport_dir": "/var/spool/cgrates/tpe", + "poster_attempts": 3, + "failed_posts_dir": "/var/spool/cgrates/failed_posts", + "failed_posts_ttl": "5s", + "default_request_type": "*rated", + "default_category": "call", + "default_tenant": "cgrates.org", + "default_timezone": "Local", + "default_caching": "*reload", + "connect_attempts": 5, + "reconnects": -1, + "connect_timeout": "1s", + "reply_timeout": "2s", + "locking_timeout": "0", + "digest_separator": ",", + "digest_equal": ":", + "rsr_separator": ";", + "max_parralel_conns": 100, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnGenCfg, err := jsnCfg.GeneralJsonCfg(); err != nil { + t.Error(err) + } else if err = gencfg.loadFromJsonCfg(jsnGenCfg); err != nil { + t.Error(err) + } else if rcv := gencfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/datadbcfg.go b/config/datadbcfg.go index e945d8ddf..049c0577e 100644 --- a/config/datadbcfg.go +++ b/config/datadbcfg.go @@ -100,6 +100,7 @@ func (dbcfg *DataDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) { } } if jsnDbCfg.Items != nil { + dbcfg.Items = make(map[string]*ItemOpt) for kJsn, vJsn := range *jsnDbCfg.Items { val, has := dbcfg.Items[kJsn] if val == nil || !has { @@ -134,16 +135,21 @@ func (dbcfg *DataDbCfg) AsMapInterface() map[string]interface{} { for key, item := range dbcfg.Items { items[key] = item.AsMapInterface() } + var queryTimeout string = "0" + if dbcfg.QueryTimeout != 0 { + queryTimeout = dbcfg.QueryTimeout.String() + } + dbPort, _ := strconv.Atoi(dbcfg.DataDbPort) return map[string]interface{}{ - utils.DataDbTypeCfg: dbcfg.DataDbType, + utils.DataDbTypeCfg: utils.Meta + dbcfg.DataDbType, utils.DataDbHostCfg: dbcfg.DataDbHost, - utils.DataDbPortCfg: dbcfg.DataDbPort, + utils.DataDbPortCfg: dbPort, utils.DataDbNameCfg: dbcfg.DataDbName, utils.DataDbUserCfg: dbcfg.DataDbUser, utils.DataDbPassCfg: dbcfg.DataDbPass, utils.DataDbSentinelNameCfg: dbcfg.DataDbSentinelName, - utils.QueryTimeoutCfg: dbcfg.QueryTimeout, + utils.QueryTimeoutCfg: queryTimeout, utils.RmtConnsCfg: dbcfg.RmtConns, utils.RplConnsCfg: dbcfg.RplConns, utils.ItemsCfg: items, @@ -162,11 +168,16 @@ type ItemOpt struct { } func (itm *ItemOpt) AsMapInterface() map[string]interface{} { + var ttl string = "" + if itm.TTL != 0 { + ttl = itm.TTL.String() + } + return map[string]interface{}{ utils.RemoteCfg: itm.Remote, utils.ReplicateCfg: itm.Replicate, utils.LimitCfg: itm.Limit, - utils.TTLCfg: itm.TTL, + utils.TTLCfg: ttl, utils.StaticTTLCfg: itm.StaticTTL, } } diff --git a/config/datadbcfg_test.go b/config/datadbcfg_test.go index 516dfef28..3d9c4a638 100644 --- a/config/datadbcfg_test.go +++ b/config/datadbcfg_test.go @@ -218,3 +218,227 @@ func TestDataDBRemoteReplication(t *testing.T) { t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(expected), utils.ToJSON(dbcfg)) } } + +func TestDataDbCfgloadFromJsonCfgItems(t *testing.T) { + var dbcfg, expected DataDbCfg + cfgJSONStr := `{ +"data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "*redis", // data_db type: <*redis|*mongo|*internal> + "db_host": "127.0.0.1", // data_db host address + "db_port": -1, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + "db_user": "cgrates", // username to use when connecting to data_db + "db_password": "password", // password to use when connecting to data_db + "redis_sentinel":"sentinel", // redis_sentinel is the name of sentinel + "remote_conns":["Conn1"], + "items":{ + "*accounts":{"replicate":true, "limit": 5,"ttl": "6"}, + "*reverse_destinations": {"replicate":false}, + "*destinations": {"replicate":false}, + } + } +}` + + expected = DataDbCfg{ + DataDbType: "redis", + DataDbHost: "127.0.0.1", + DataDbPort: "6379", + DataDbName: "10", + DataDbUser: "cgrates", + DataDbPass: "password", + DataDbSentinelName: "sentinel", + RmtConns: []string{"Conn1"}, + Items: map[string]*ItemOpt{ + utils.MetaAccounts: &ItemOpt{ + Replicate: true, + TTL: 6, + Limit: 5, + }, + utils.MetaReverseDestinations: &ItemOpt{ + Replicate: false, + }, + utils.MetaDestinations: &ItemOpt{ + Replicate: false, + }, + }, + } + dbcfg.Items = make(map[string]*ItemOpt) + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN); err != nil { + t.Error(err) + } else if err = dbcfg.loadFromJsonCfg(jsnDataDbCfg); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, dbcfg) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(expected), utils.ToJSON(dbcfg)) + } + + cfgJSONStr = `{ + "data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "*redis", // data_db type: <*redis|*mongo|*internal> + "db_host": "127.0.0.1", // data_db host address + "db_port": -1, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + "db_user": "cgrates", // username to use when connecting to data_db + "db_password": "password", // password to use when connecting to data_db + "redis_sentinel":"sentinel", // redis_sentinel is the name of sentinel + "remote_conns":["Conn1"], + "items":{ + "*dispatcher_hosts":{"remote":true, "replicate":true, "limit": -1, "ttl": "", "static_ttl": true}, + "*filter_indexes" :{"remote":true, "replicate":true, "limit": -1, "ttl": "", "static_ttl": true}, + "*load_ids":{"remote":true, "replicate":true, "limit": -1, "ttl": "", "static_ttl": true}, + + } + } + }` + + expected = DataDbCfg{ + DataDbType: "redis", + DataDbHost: "127.0.0.1", + DataDbPort: "6379", + DataDbName: "10", + DataDbUser: "cgrates", + DataDbPass: "password", + DataDbSentinelName: "sentinel", + RmtConns: []string{"Conn1"}, + Items: map[string]*ItemOpt{ + utils.MetaDispatcherHosts: &ItemOpt{ + Remote: true, + Replicate: true, + Limit: -1, + StaticTTL: true, + }, + utils.MetaFilterIndexes: &ItemOpt{ + Remote: true, + Replicate: true, + Limit: -1, + StaticTTL: true, + }, + utils.MetaLoadIDs: &ItemOpt{ + Remote: true, + Replicate: true, + Limit: -1, + StaticTTL: true, + }, + }, + } + dbcfg.Items = make(map[string]*ItemOpt) + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN); err != nil { + t.Error(err) + } else if err = dbcfg.loadFromJsonCfg(jsnDataDbCfg); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, dbcfg) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(expected), utils.ToJSON(dbcfg)) + } + + cfgJSONStr = `{ + "data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "*redis", // data_db type: <*redis|*mongo|*internal> + "db_host": "127.0.0.1", // data_db host address + "db_port": -1, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + "db_user": "cgrates", // username to use when connecting to data_db + "db_password": "password", // password to use when connecting to data_db + "redis_sentinel":"sentinel", // redis_sentinel is the name of sentinel + "remote_conns":["Conn1"], + "items":{ + "*timings": {"remote":false, "replicate":false, "limit": 9, "ttl": "8", "static_ttl": true}, + "*resource_profiles":{"remote":false, "replicate":false, "limit": 9, "ttl": "8", "static_ttl": true}, + "*resources":{"remote":false, "replicate":false, "limit": 9, "ttl": "8", "static_ttl": true}, + "*statqueue_profiles": {"remote":false, "replicate":false, "limit": 9, "ttl": "8", "static_ttl": true}, + } + } + }` + + expected = DataDbCfg{ + DataDbType: "redis", + DataDbHost: "127.0.0.1", + DataDbPort: "6379", + DataDbName: "10", + DataDbUser: "cgrates", + DataDbPass: "password", + DataDbSentinelName: "sentinel", + RmtConns: []string{"Conn1"}, + Items: map[string]*ItemOpt{ + utils.MetaTimings: &ItemOpt{ + Limit: 9, + TTL: 8, + StaticTTL: true, + }, + utils.MetaResourceProfile: &ItemOpt{ + Limit: 9, + TTL: 8, + StaticTTL: true, + }, + utils.MetaResources: &ItemOpt{ + Limit: 9, + TTL: 8, + StaticTTL: true, + }, + utils.MetaStatQueueProfiles: &ItemOpt{ + Limit: 9, + TTL: 8, + StaticTTL: true, + }, + }, + } + dbcfg.Items = make(map[string]*ItemOpt) + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN); err != nil { + t.Error(err) + } else if err = dbcfg.loadFromJsonCfg(jsnDataDbCfg); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, dbcfg) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(expected), utils.ToJSON(dbcfg)) + } +} + +func TestDataDbCfgAsMapInterface(t *testing.T) { + var dbcfg DataDbCfg + cfgJSONStr := `{ + "data_db": { + "db_type": "*redis", + "db_host": "127.0.0.1", + "db_port": 6379, + "db_name": "10", + "db_user": "cgrates", + "db_password": "", + "redis_sentinel":"", + "query_timeout":"10s", + "remote_conns":[], + "replication_conns":[], + "items":{ + "*accounts":{"remote":true, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, + "*reverse_destinations": {"remote":false, "replicate":false, "limit": 7, "ttl": "", "static_ttl": true}, + }, + }, +}` + eMap := map[string]interface{}{ + "db_type": "*redis", + "db_host": "127.0.0.1", + "db_port": 6379, + "db_name": "10", + "db_user": "cgrates", + "db_password": "", + "redis_sentinel": "", + "query_timeout": "10s", + "remote_conns": []string{}, + "replication_conns": []string{}, + "items": map[string]interface{}{ + "*accounts": map[string]interface{}{"remote": true, "replicate": false, "limit": -1, "ttl": "", "static_ttl": false}, + "*reverse_destinations": map[string]interface{}{"remote": false, "replicate": false, "limit": 7, "ttl": "", "static_ttl": true}, + }, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN); err != nil { + t.Error(err) + } else if err = dbcfg.loadFromJsonCfg(jsnDataDbCfg); err != nil { + t.Error(err) + } else if rcv := dbcfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/diametercfg.go b/config/diametercfg.go index ef619f055..ac98fc441 100644 --- a/config/diametercfg.go +++ b/config/diametercfg.go @@ -117,12 +117,12 @@ func (da *DiameterAgentCfg) loadFromJsonCfg(jsnCfg *DiameterAgentJsonCfg, separa return nil } -func (ds *DiameterAgentCfg) AsMapInterface() map[string]interface{} { +func (ds *DiameterAgentCfg) AsMapInterface(separator string) map[string]interface{} { templates := make(map[string][]map[string]interface{}) for key, value := range ds.Templates { fcTemplate := make([]map[string]interface{}, len(value)) for i, val := range value { - fcTemplate[i] = val.AsMapInterface() + fcTemplate[i] = val.AsMapInterface(separator) } templates[key] = fcTemplate @@ -130,7 +130,7 @@ func (ds *DiameterAgentCfg) AsMapInterface() map[string]interface{} { requestProcessors := make([]map[string]interface{}, len(ds.RequestProcessors)) for i, item := range ds.RequestProcessors { - requestProcessors[i] = item.AsMapInterface() + requestProcessors[i] = item.AsMapInterface(separator) } return map[string]interface{}{ diff --git a/config/dnsagntcfg.go b/config/dnsagntcfg.go index 912c15b6b..e1a61b94d 100644 --- a/config/dnsagntcfg.go +++ b/config/dnsagntcfg.go @@ -19,6 +19,8 @@ along with this program. If not, see package config import ( + "strings" + "github.com/cgrates/cgrates/utils" ) @@ -80,10 +82,10 @@ func (da *DNSAgentCfg) loadFromJsonCfg(jsnCfg *DNSAgentJsonCfg, sep string) (err return nil } -func (da *DNSAgentCfg) AsMapInterface() map[string]interface{} { +func (da *DNSAgentCfg) AsMapInterface(separator string) map[string]interface{} { requestProcessors := make([]map[string]interface{}, len(da.RequestProcessors)) for i, item := range da.RequestProcessors { - requestProcessors[i] = item.AsMapInterface() + requestProcessors[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -147,23 +149,36 @@ func (rp *RequestProcessor) loadFromJsonCfg(jsnCfg *ReqProcessorJsnCfg, sep stri return nil } -func (rp *RequestProcessor) AsMapInterface() map[string]interface{} { +func (rp *RequestProcessor) AsMapInterface(separator string) map[string]interface{} { replyFields := make([]map[string]interface{}, len(rp.ReplyFields)) for i, item := range rp.ReplyFields { - replyFields[i] = item.AsMapInterface() + replyFields[i] = item.AsMapInterface(separator) } requestFields := make([]map[string]interface{}, len(rp.RequestFields)) for i, item := range rp.RequestFields { - requestFields[i] = item.AsMapInterface() + requestFields[i] = item.AsMapInterface(separator) + } + var tenant string + if rp.Tenant != nil { + values := make([]string, len(rp.Tenant)) + for i, item := range rp.Tenant { + values[i] = item.Rules + } + tenant = strings.Join(values, utils.EmptyString) + } + + flags := make(map[string][]string, len(rp.Flags)) + for key, item := range rp.Flags { + flags[key] = item } return map[string]interface{}{ - utils.ID: rp.ID, - utils.Tenant: rp.Tenant, - utils.Filters: rp.Filters, - utils.Flags: rp.Flags, - utils.TimezoneCfg: rp.Timezone, + utils.IDCfg: rp.ID, + utils.TenantCfg: tenant, + utils.FiltersCfg: rp.Filters, + utils.FlagsCfg: flags, + utils.TimezoneCfgC: rp.Timezone, utils.RequestFieldsCfg: requestFields, utils.ReplyFieldsCfg: replyFields, } diff --git a/config/erscfg.go b/config/erscfg.go index 2f4616f20..f55f7be34 100644 --- a/config/erscfg.go +++ b/config/erscfg.go @@ -98,11 +98,11 @@ func (erS *ERsCfg) Clone() (cln *ERsCfg) { return } -func (erS *ERsCfg) AsMapInterface() map[string]interface{} { +func (erS *ERsCfg) AsMapInterface(separator string) map[string]interface{} { readers := make([]map[string]interface{}, len(erS.Readers)) for i, item := range erS.Readers { - readers[i] = item.AsMapInterface() + readers[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -247,7 +247,7 @@ func (er *EventReaderCfg) Clone() (cln *EventReaderCfg) { return } -func (er *EventReaderCfg) AsMapInterface() map[string]interface{} { +func (er *EventReaderCfg) AsMapInterface(separator string) map[string]interface{} { xmlRootPath := make([]string, len(er.XmlRootPath)) for i, item := range er.XmlRootPath { xmlRootPath[i] = item @@ -262,11 +262,11 @@ func (er *EventReaderCfg) AsMapInterface() map[string]interface{} { } fields := make([]map[string]interface{}, len(er.Fields)) for i, item := range er.Fields { - fields[i] = item.AsMapInterface() + fields[i] = item.AsMapInterface(separator) } cacheDumpFields := make([]map[string]interface{}, len(er.CacheDumpFields)) for i, item := range er.CacheDumpFields { - cacheDumpFields[i] = item.AsMapInterface() + cacheDumpFields[i] = item.AsMapInterface(separator) } return map[string]interface{}{ diff --git a/config/fctemplate.go b/config/fctemplate.go index d09487f10..e999ccb8d 100755 --- a/config/fctemplate.go +++ b/config/fctemplate.go @@ -191,32 +191,74 @@ func (self *FCTemplate) Clone() *FCTemplate { return cln } -func (fc *FCTemplate) AsMapInterface() map[string]interface{} { - values := make([]string, len(fc.Value)) - for i, item := range fc.Value { - values[i] = item.Rules - } - - return map[string]interface{}{ - utils.TagCfg: fc.Tag, - utils.TypeCf: fc.Type, - utils.PathCfg: fc.Path, - utils.FiltersCfg: fc.Filters, - utils.ValueCfg: values, - utils.WidthCfg: fc.Width, - utils.StripCfg: fc.Strip, - utils.PaddingCfg: fc.Padding, - utils.MandatoryCfg: fc.Mandatory, - utils.AttributeIDCfg: fc.AttributeID, - utils.NewBranchCfg: fc.NewBranch, - utils.TimezoneCfg: fc.Timezone, - utils.BlockerCfg: fc.Blocker, - utils.BreakOnSuccessCfg: fc.BreakOnSuccess, - utils.LayoutCfg: fc.Layout, - utils.CostShiftDigitsCfg: fc.CostShiftDigits, - utils.RoundingDecimalsCfg: fc.RoundingDecimals, - utils.MaskDestIDCfg: fc.MaskDestID, - utils.MaskLenCfg: fc.MaskLen, +func (fc *FCTemplate) AsMapInterface(separator string) (mp map[string]interface{}) { + mp = make(map[string]interface{}) + if fc.Tag != utils.EmptyString { + mp[utils.TagCfg] = fc.Tag + } + if fc.Type != utils.EmptyString { + mp[utils.TypeCf] = fc.Type + } + if fc.Path != utils.EmptyString { + mp[utils.PathCfg] = fc.Path + } + if fc.Filters != nil { + mp[utils.FiltersCfg] = fc.Filters + } + if fc.Value != nil { + for i, item := range fc.Value { + if i != 0 { + mp[utils.ValueCfg] = mp[utils.ValueCfg].(string) + separator + } + if mp[utils.ValueCfg] == nil { + mp[utils.ValueCfg] = item.Rules + } else { + mp[utils.ValueCfg] = mp[utils.ValueCfg].(string) + item.Rules + } + } + } + if fc.Width != 0 { + mp[utils.WidthCfg] = fc.Width + } + if fc.Strip != utils.EmptyString { + mp[utils.StripCfg] = fc.Strip + } + if fc.Padding != utils.EmptyString { + mp[utils.PaddingCfg] = fc.Padding + } + if fc.Mandatory != false { + mp[utils.MandatoryCfg] = fc.Mandatory + } + if fc.AttributeID != utils.EmptyString { + mp[utils.AttributeIDCfg] = fc.AttributeID + } + if fc.NewBranch != false { + mp[utils.NewBranchCfg] = fc.NewBranch + } + if fc.Timezone != utils.EmptyString { + mp[utils.TimezoneCfg] = fc.Timezone + } + if fc.Blocker != false { + mp[utils.BlockerCfg] = fc.Blocker + } + if fc.BreakOnSuccess != false { + mp[utils.BreakOnSuccessCfg] = fc.BreakOnSuccess + } + if fc.Layout != time.RFC3339 { + mp[utils.LayoutCfg] = fc.Layout + } + if fc.CostShiftDigits != 0 { + mp[utils.CostShiftDigitsCfg] = fc.CostShiftDigits + } + if fc.RoundingDecimals != nil { + mp[utils.RoundingDecimalsCfg] = *fc.RoundingDecimals + } + if fc.MaskDestID != utils.EmptyString { + mp[utils.MaskDestIDCfg] = fc.MaskDestID + } + if fc.MaskLen != 0 { + mp[utils.MaskLenCfg] = fc.MaskLen } + return } diff --git a/config/filterscfg_test.go b/config/filterscfg_test.go index 9c1e01b5a..fe259da49 100644 --- a/config/filterscfg_test.go +++ b/config/filterscfg_test.go @@ -54,3 +54,29 @@ func TestFilterSCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(fscfg)) } } + +func TestFilterSCfgAsMapInterface(t *testing.T) { + var fscfg FilterSCfg + cfgJSONStr := `{ + "filters": { + "stats_conns": ["*localhost"], + "resources_conns": [], + "apiers_conns": [], + }, +}` + var emptySlice []string + eMap := map[string]interface{}{ + "stats_conns": []string{"*localhost"}, + "resources_conns": emptySlice, + "apiers_conns": emptySlice, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnFsCfg, err := jsnCfg.FilterSJsonCfg(); err != nil { + t.Error(err) + } else if err = fscfg.loadFromJsonCfg(jsnFsCfg); err != nil { + t.Error(err) + } else if rcv := fscfg.AsMapInterface(); reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/generalcfg.go b/config/generalcfg.go index 9a5ea9674..80b49a38d 100644 --- a/config/generalcfg.go +++ b/config/generalcfg.go @@ -144,17 +144,34 @@ func (gencfg *GeneralCfg) loadFromJsonCfg(jsnGeneralCfg *GeneralJsonCfg) (err er } func (gencfg *GeneralCfg) AsMapInterface() map[string]interface{} { + var lockingTimeout string = "0" + var failedPostsTTL string = "0" + var connectTimeout string = "0" + var replyTimeout string = "0" + if gencfg.LockingTimeout != 0 { + lockingTimeout = gencfg.LockingTimeout.String() + } + if gencfg.FailedPostsTTL != 0 { + failedPostsTTL = gencfg.FailedPostsTTL.String() + } + if gencfg.ConnectTimeout != 0 { + connectTimeout = gencfg.ConnectTimeout.String() + } + if gencfg.ReplyTimeout != 0 { + replyTimeout = gencfg.ReplyTimeout.String() + } + return map[string]interface{}{ utils.NodeIDCfg: gencfg.NodeID, utils.LoggerCfg: gencfg.Logger, utils.LogLevelCfg: gencfg.LogLevel, utils.HttpSkipTlsVerifyCfg: gencfg.HttpSkipTlsVerify, utils.RoundingDecimalsCfg: gencfg.RoundingDecimals, - utils.DBDataEncodingCfg: gencfg.DBDataEncoding, + utils.DBDataEncodingCfg: utils.Meta + gencfg.DBDataEncoding, utils.TpExportPathCfg: gencfg.TpExportPath, utils.PosterAttemptsCfg: gencfg.PosterAttempts, utils.FailedPostsDirCfg: gencfg.FailedPostsDir, - utils.FailedPostsTTLCfg: gencfg.FailedPostsTTL, + utils.FailedPostsTTLCfg: failedPostsTTL, utils.DefaultReqTypeCfg: gencfg.DefaultReqType, utils.DefaultCategoryCfg: gencfg.DefaultCategory, utils.DefaultTenantCfg: gencfg.DefaultTenant, @@ -162,9 +179,9 @@ func (gencfg *GeneralCfg) AsMapInterface() map[string]interface{} { utils.DefaultCachingCfg: gencfg.DefaultCaching, utils.ConnectAttemptsCfg: gencfg.ConnectAttempts, utils.ReconnectsCfg: gencfg.Reconnects, - utils.ConnectTimeoutCfg: gencfg.ConnectTimeout, - utils.ReplyTimeoutCfg: gencfg.ReplyTimeout, - utils.LockingTimeoutCfg: gencfg.LockingTimeout, + utils.ConnectTimeoutCfg: connectTimeout, + utils.ReplyTimeoutCfg: replyTimeout, + utils.LockingTimeoutCfg: lockingTimeout, utils.DigestSeparatorCfg: gencfg.DigestSeparator, utils.DigestEqualCfg: gencfg.DigestEqual, utils.RSRSepCfg: gencfg.RSRSep, diff --git a/config/httpagntcfg.go b/config/httpagntcfg.go index ce8caad0e..2a704827c 100644 --- a/config/httpagntcfg.go +++ b/config/httpagntcfg.go @@ -50,6 +50,14 @@ func (hcfgs *HttpAgentCfgs) loadFromJsonCfg(jsnHttpAgntCfg *[]*HttpAgentJsonCfg, return nil } +func (hcfgs *HttpAgentCfgs) AsMapInterface(separator string) []map[string]interface{} { + mp := make([]map[string]interface{}, len(*hcfgs)) + for i, item := range *hcfgs { + mp[i] = item.AsMapInterface(separator) + } + return mp +} + type HttpAgentCfg struct { ID string // identifier for the agent, so we can update it's processors Url string @@ -118,10 +126,10 @@ func (ca *HttpAgentCfg) loadFromJsonCfg(jsnCfg *HttpAgentJsonCfg, separator stri return nil } -func (ca *HttpAgentCfg) AsMapInterface() map[string]interface{} { +func (ca *HttpAgentCfg) AsMapInterface(separator string) map[string]interface{} { requestProcessors := make([]map[string]interface{}, len(ca.RequestProcessors)) for i, item := range ca.RequestProcessors { - requestProcessors[i] = item.AsMapInterface() + requestProcessors[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -130,6 +138,6 @@ func (ca *HttpAgentCfg) AsMapInterface() map[string]interface{} { utils.SessionSConnsCfg: ca.SessionSConns, utils.RequestPayloadCfg: ca.RequestPayload, utils.ReplyPayloadCfg: ca.ReplyPayload, - utils.RequestProcessorsCfg: ca.RequestProcessors, + utils.RequestProcessorsCfg: requestProcessors, } } diff --git a/config/httpagntcfg_test.go b/config/httpagntcfg_test.go index 45c721494..7388aa109 100644 --- a/config/httpagntcfg_test.go +++ b/config/httpagntcfg_test.go @@ -344,3 +344,76 @@ func TestHttpAgentCfgappendHttpAgntProcCfgs(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(initial)) } } + +func TestHttpAgentCfgAsMapInterface(t *testing.T) { + var httpcfg HttpAgentCfgs + cfgJSONStr := `{ + +"http_agent": [ + { + "id": "conecto1", + "url": "/conecto", + "sessions_conns": ["*localhost"], + "request_payload": "*url", + "reply_payload": "*xml", + "request_processors": [ + { + "id": "OutboundAUTHDryRun", + "filters": ["*string:~*req.request_type:OutboundAUTH","*string:~*req.Msisdn:497700056231"], + "tenant": "cgrates.org", + "flags": ["*dryrun"], + "request_fields":[ + ], + "reply_fields":[ + {"tag": "Allow", "path": "*rep.response.Allow", "type": "*constant", + "value": "1", "mandatory": true}, + {"tag": "Concatenated1", "path": "*rep.response.Concatenated", "type": "*composed", + "value": "~*req.MCC;/", "mandatory": true}, + {"tag": "Concatenated2", "path": "*rep.response.Concatenated", "type": "*composed", + "value": "Val1"}, + {"tag": "MaxDuration", "path": "*rep.response.MaxDuration", "type": "*constant", + "value": "1200", "blocker": true}, + {"tag": "Unused", "path": "*rep.response.Unused", "type": "*constant", + "value": "0"}, + ], + }, + ], + }, + ], +}` + eMap := []map[string]interface{}{ + { + "id": "conecto1", + "url": "/conecto", + "sessions_conns": []string{"*localhost"}, + "request_payload": "*url", + "reply_payload": "*xml", + "request_processors": []map[string]interface{}{ + { + "id": "OutboundAUTHDryRun", + "filters": []string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"}, + "tenant": "cgrates.org", + "flags": map[string][]string{"*dryrun": {}}, + "Timezone": "", + "request_fields": []map[string]interface{}{}, + "reply_fields": []map[string]interface{}{ + {"tag": "Allow", "path": "*rep.response.Allow", "type": "*constant", "value": "1", "mandatory": true}, + {"tag": "Concatenated1", "path": "*rep.response.Concatenated", "type": "*composed", "value": "~*req.MCC;/", "mandatory": true}, + {"tag": "Concatenated2", "path": "*rep.response.Concatenated", "type": "*composed", "value": "Val1"}, + {"tag": "MaxDuration", "path": "*rep.response.MaxDuration", "type": "*constant", "value": "1200", "blocker": true}, + {"tag": "Unused", "path": "*rep.response.Unused", "type": "*constant", "value": "0"}, + }, + }, + }, + }, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnhttpCfg, err := jsnCfg.HttpAgentJsonCfg(); err != nil { + t.Error(err) + } else if err = httpcfg.loadFromJsonCfg(jsnhttpCfg, utils.INFIELD_SEP); err != nil { + t.Error(err) + } else if rcv := httpcfg.AsMapInterface(";"); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v,\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/httpcfg.go b/config/httpcfg.go index d97db7061..258f0fe21 100644 --- a/config/httpcfg.go +++ b/config/httpcfg.go @@ -58,12 +58,17 @@ func (httpcfg *HTTPCfg) loadFromJsonCfg(jsnHttpCfg *HTTPJsonCfg) (err error) { } func (httpcfg *HTTPCfg) AsMapInterface() map[string]interface{} { + httpUsers := map[string]interface{}{} + for key, item := range httpcfg.HTTPAuthUsers { + httpUsers[key] = item + } + return map[string]interface{}{ utils.HTTPJsonRPCURLCfg: httpcfg.HTTPJsonRPCURL, utils.HTTPWSURLCfg: httpcfg.HTTPWSURL, utils.HTTPFreeswitchCDRsURLCfg: httpcfg.HTTPFreeswitchCDRsURL, utils.HTTPCDRsURLCfg: httpcfg.HTTPCDRsURL, utils.HTTPUseBasicAuthCfg: httpcfg.HTTPUseBasicAuth, - utils.HTTPAuthUsersCfg: httpcfg.HTTPAuthUsers, + utils.HTTPAuthUsersCfg: httpUsers, } } diff --git a/config/httpcfg_test.go b/config/httpcfg_test.go index 5b3f856c2..071c38c3d 100644 --- a/config/httpcfg_test.go +++ b/config/httpcfg_test.go @@ -20,6 +20,8 @@ package config import ( "reflect" "testing" + + "github.com/cgrates/cgrates/utils" ) func TestHTTPCfgloadFromJsonCfg(t *testing.T) { @@ -62,3 +64,36 @@ func TestHTTPCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", expected, httpcfg) } } + +func TestHTTPCfgAsMapInterface(t *testing.T) { + var httpcfg HTTPCfg + cfgJSONStr := `{ + "http": { + "json_rpc_url": "/jsonrpc", + "ws_url": "/ws", + "freeswitch_cdrs_url": "/freeswitch_json", + "http_cdrs": "/cdr_http", + "use_basic_auth": false, + "auth_users": {}, + }, +}` + + eMap := map[string]interface{}{ + "json_rpc_url": "/jsonrpc", + "ws_url": "/ws", + "freeswitch_cdrs_url": "/freeswitch_json", + "http_cdrs": "/cdr_http", + "use_basic_auth": false, + "auth_users": map[string]interface{}{}, + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnhttpCfg, err := jsnCfg.HttpJsonCfg(); err != nil { + t.Error(err) + } else if err = httpcfg.loadFromJsonCfg(jsnhttpCfg); err != nil { + t.Error(err) + } else if rcv := httpcfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/loaderscfg.go b/config/loaderscfg.go index 412c01121..4ed55b9ad 100644 --- a/config/loaderscfg.go +++ b/config/loaderscfg.go @@ -19,6 +19,7 @@ along with this program. If not, see package config import ( + "strings" "time" "github.com/cgrates/cgrates/utils" @@ -182,10 +183,10 @@ func (self *LoaderSCfg) Clone() *LoaderSCfg { return clnLoader } -func (lData *LoaderDataType) AsMapInterface() map[string]interface{} { +func (lData *LoaderDataType) AsMapInterface(separator string) map[string]interface{} { fields := make([]map[string]interface{}, len(lData.Fields)) for i, item := range lData.Fields { - fields[i] = item.AsMapInterface() + fields[i] = item.AsMapInterface(separator) } return map[string]interface{}{ @@ -195,25 +196,39 @@ func (lData *LoaderDataType) AsMapInterface() map[string]interface{} { } } -func (l *LoaderSCfg) AsMapInterface() map[string]interface{} { +func (l *LoaderSCfg) AsMapInterface(separator string) map[string]interface{} { tenant := make([]string, len(l.Tenant)) for i, item := range l.Tenant { tenant[i] = item.Rules } + strings.Join(tenant, utils.EmptyString) data := make([]map[string]interface{}, len(l.Data)) for i, item := range l.Data { - data[i] = item.AsMapInterface() + data[i] = item.AsMapInterface(separator) + } + var runDelay string = "0" + if l.RunDelay != 0 { + runDelay = l.RunDelay.String() + } + cacheSConns := make([]string, len(l.CacheSConns)) + for i, item := range l.CacheSConns { + buf := utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches) + if item == buf { + cacheSConns[i] = strings.ReplaceAll(item, ":*caches", utils.EmptyString) + } else { + cacheSConns[i] = item + } } return map[string]interface{}{ utils.IdCfg: l.Id, utils.EnabledCfg: l.Enabled, - utils.TenantCfg: tenant, + utils.TenantCfg: strings.Join(tenant, utils.EmptyString), utils.DryRunCfg: l.DryRun, - utils.RunDelayCfg: l.RunDelay, + utils.RunDelayCfg: runDelay, utils.LockFileNameCfg: l.LockFileName, - utils.CacheSConnsCfg: l.CacheSConns, + utils.CacheSConnsCfg: cacheSConns, utils.FieldSeparatorCfg: l.FieldSeparator, utils.TpInDirCfg: l.TpInDir, utils.TpOutDirCfg: l.TpOutDir, diff --git a/config/loaderscfg_test.go b/config/loaderscfg_test.go index 616a7e7ef..f3acf9869 100644 --- a/config/loaderscfg_test.go +++ b/config/loaderscfg_test.go @@ -102,3 +102,78 @@ func TestLoaderSCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(loadscfg)) } } + +func TestLoaderCfgAsMapInterface(t *testing.T) { + var loadscfg LoaderSCfg + cfgJSONStr := `{ + "loaders": [ + { + "id": "*default", + "enabled": false, + "tenant": "", + "dry_run": false, + "run_delay": 0, + "lock_filename": ".cgr.lck", + "caches_conns": ["*internal"], + "field_separator": ",", + "tp_in_dir": "/var/spool/cgrates/loader/in", + "tp_out_dir": "/var/spool/cgrates/loader/out", + "data":[ + { + "type": "*attributes", + "file_name": "Attributes.csv", + "fields": [ + {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, + {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, + ], + }, + ], + }, + ], + +}` + eMap := map[string]interface{}{ + "id": "*default", + "enabled": false, + "tenant": "", + "dry_run": false, + "run_delay": "0", + "lock_filename": ".cgr.lck", + "caches_conns": []string{"*internal"}, + "field_separator": ",", + "tp_in_dir": "/var/spool/cgrates/loader/in", + "tp_out_dir": "/var/spool/cgrates/loader/out", + "data": []map[string]interface{}{ + { + "type": "*attributes", + "file_name": "Attributes.csv", + "fields": []map[string]interface{}{ + { + "tag": "TenantID", + "path": "Tenant", + "type": "*variable", + "value": "~0", + "mandatory": true, + }, { + "tag": "ProfileID", + "path": "ID", + "type": "*variable", + "value": "~1", + "mandatory": true, + }, + }, + }, + }, + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnLoadersCfg, err := jsnCfg.LoaderJsonCfg(); err != nil { + t.Error(err) + } else if err = loadscfg.loadFromJsonCfg(jsnLoadersCfg[0], utils.INFIELD_SEP); err != nil { + t.Error(err) + } else if rcv := loadscfg.AsMapInterface(""); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("\nExpected: %+v\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } + +} diff --git a/config/radiuscfg.go b/config/radiuscfg.go index b2ce1aaa7..7c1ca7db7 100644 --- a/config/radiuscfg.go +++ b/config/radiuscfg.go @@ -96,7 +96,7 @@ func (self *RadiusAgentCfg) loadFromJsonCfg(jsnCfg *RadiusAgentJsonCfg, separato return nil } -func (ra *RadiusAgentCfg) AsMapInterface() map[string]interface{} { +func (ra *RadiusAgentCfg) AsMapInterface(separator string) map[string]interface{} { clientSecrets := make(map[string]interface{}, len(ra.ClientSecrets)) for key, val := range ra.ClientSecrets { clientSecrets[key] = val @@ -109,7 +109,7 @@ func (ra *RadiusAgentCfg) AsMapInterface() map[string]interface{} { requestProcessors := make([]map[string]interface{}, len(ra.RequestProcessors)) for i, item := range ra.RequestProcessors { - requestProcessors[i] = item.AsMapInterface() + requestProcessors[i] = item.AsMapInterface(separator) } return map[string]interface{}{ diff --git a/config/ralscfg.go b/config/ralscfg.go index 563d2a12b..7801cdc7d 100644 --- a/config/ralscfg.go +++ b/config/ralscfg.go @@ -19,6 +19,8 @@ along with this program. If not, see package config import ( + "strconv" + "strings" "time" "github.com/cgrates/cgrates/utils" @@ -85,6 +87,7 @@ func (ralsCfg *RalsCfg) loadFromJsonCfg(jsnRALsCfg *RalsJsonCfg) (err error) { ralsCfg.RemoveExpired = *jsnRALsCfg.Remove_expired } if jsnRALsCfg.Max_computed_usage != nil { + ralsCfg.MaxComputedUsage = make(map[string]time.Duration, len(*jsnRALsCfg.Max_computed_usage)) for k, v := range *jsnRALsCfg.Max_computed_usage { if ralsCfg.MaxComputedUsage[k], err = utils.ParseDurationWithNanosecs(v); err != nil { return @@ -95,6 +98,7 @@ func (ralsCfg *RalsCfg) loadFromJsonCfg(jsnRALsCfg *RalsJsonCfg) (err error) { ralsCfg.MaxIncrements = *jsnRALsCfg.Max_increments } if jsnRALsCfg.Balance_rating_subject != nil { + ralsCfg.BalanceRatingSubject = make(map[string]string, len(*jsnRALsCfg.Balance_rating_subject)) for k, v := range *jsnRALsCfg.Balance_rating_subject { ralsCfg.BalanceRatingSubject[k] = v } @@ -106,7 +110,21 @@ func (ralsCfg *RalsCfg) loadFromJsonCfg(jsnRALsCfg *RalsJsonCfg) (err error) { func (ralsCfg *RalsCfg) AsMapInterface() map[string]interface{} { maxComputed := make(map[string]interface{}) for key, item := range ralsCfg.MaxComputedUsage { - maxComputed[key] = item + if key == utils.ANY || key == utils.VOICE { + maxComputed[key] = item.String() + } else { + maxComputed[key] = strconv.Itoa(int(item)) + } + } + + cacheSConns := make([]string, len(ralsCfg.CacheSConns)) + for i, item := range ralsCfg.CacheSConns { + buf := utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches) + if item == buf { + cacheSConns[i] = strings.ReplaceAll(item, ":*caches", utils.EmptyString) + } else { + cacheSConns[i] = item + } } balanceRating := make(map[string]interface{}) @@ -118,11 +136,12 @@ func (ralsCfg *RalsCfg) AsMapInterface() map[string]interface{} { utils.EnabledCfg: ralsCfg.Enabled, utils.ThresholdSConnsCfg: ralsCfg.ThresholdSConns, utils.StatSConnsCfg: ralsCfg.StatSConns, - utils.CacheSConnsCfg: ralsCfg.CacheSConns, + utils.CacheSConnsCfg: cacheSConns, utils.RpSubjectPrefixMatchingCfg: ralsCfg.RpSubjectPrefixMatching, utils.RemoveExpiredCfg: ralsCfg.RemoveExpired, utils.MaxComputedUsageCfg: maxComputed, utils.BalanceRatingSubjectCfg: balanceRating, utils.MaxIncrementsCfg: ralsCfg.MaxIncrements, + utils.Dynaprepaid_actionplansCfg: ralsCfg.DynaprepaidActionPlans, } } diff --git a/config/ralscfg_test.go b/config/ralscfg_test.go index 6fb9e4541..835fbc2c1 100644 --- a/config/ralscfg_test.go +++ b/config/ralscfg_test.go @@ -75,3 +75,61 @@ func TestRalsCfgFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(ralscfg)) } } + +func TestRalsCfgAsMapInterface(t *testing.T) { + var ralscfg RalsCfg + cfgJSONStr := `{ + "rals": { + "enabled": false, + "thresholds_conns": [], + "stats_conns": [], + "caches_conns":["*internal"], + "rp_subject_prefix_matching": false, + "remove_expired":true, + "max_computed_usage": { + "*any": "189h", + "*voice": "72h", + "*data": "107374182400", + "*sms": "10000", + "*mms": "10000" + }, + "max_increments": 1000000, + "balance_rating_subject":{ + "*any": "*zero1ns", + "*voice": "*zero1s" + }, + "dynaprepaid_actionplans": [], + }, +}` + eMap := map[string]interface{}{ + "enabled": false, + "thresholds_conns": []string{}, + "stats_conns": []string{}, + "caches_conns": []string{"*internal"}, + "rp_subject_prefix_matching": false, + "remove_expired": true, + "max_computed_usage": map[string]interface{}{ + "*any": "189h0m0s", + "*voice": "72h0m0s", + "*data": "107374182400", + "*sms": "10000", + "*mms": "10000", + }, + "max_increments": 1000000, + "balance_rating_subject": map[string]interface{}{ + "*any": "*zero1ns", + "*voice": "*zero1s", + }, + "dynaprepaid_actionplans": []string{}, + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnRalsCfg, err := jsnCfg.RalsJsonCfg(); err != nil { + t.Error(err) + } else if err = ralscfg.loadFromJsonCfg(jsnRalsCfg); err != nil { + t.Error(err) + } else if rcv := ralscfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/rpcconn.go b/config/rpcconn.go index 1f13506e0..acf36d4e6 100644 --- a/config/rpcconn.go +++ b/config/rpcconn.go @@ -69,9 +69,9 @@ func (rC *RPCConn) AsMapInterface() map[string]interface{} { } return map[string]interface{}{ - utils.Strategy: rC.Strategy, - utils.PoolSize: rC.PoolSize, - utils.Conns: conns, + utils.StrategyCfg: rC.Strategy, + utils.PoolSize: rC.PoolSize, + utils.Conns: conns, } } @@ -104,9 +104,9 @@ func (self *RemoteHost) loadFromJsonCfg(jsnCfg *RemoteHostJson) error { func (rh *RemoteHost) AsMapInterface() map[string]interface{} { return map[string]interface{}{ - utils.Address: rh.Address, - utils.Transport: rh.Transport, - utils.Synchronous: rh.Synchronous, - utils.TLS: rh.TLS, + utils.AddressCfg: rh.Address, + utils.TransportCfg: rh.Transport, + utils.SynchronousCfg: rh.Synchronous, + utils.TLS: rh.TLS, } } diff --git a/config/rpcconn_test.go b/config/rpcconn_test.go index 6d55b49ee..f8ec2647f 100644 --- a/config/rpcconn_test.go +++ b/config/rpcconn_test.go @@ -17,3 +17,42 @@ along with this program. If not, see */ package config + +import ( + "reflect" + "testing" + + "github.com/cgrates/cgrates/utils" +) + +func TestRPCConnsAsMapInterface(t *testing.T) { + var cfg RPCConn + cfgJSONStr := `{ + "rpc_conns": { + "*localhost": { + "conns": [{"address": "127.0.0.1:2012", "transport":"*json"}], + }, + }, +}` + eMap := map[string]interface{}{ + "poolSize": 0, + "strategy": "", + "conns": []map[string]interface{}{ + { + "address": "127.0.0.1:2012", + "transport": "*json", + "synchronous": false, + "TLS": false, + }, + }, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnRPCCfg, err := jsnCfg.RPCConnJsonCfg(); err != nil { + t.Error(err) + } else if err = cfg.loadFromJsonCfg(jsnRPCCfg["*localhost"]); err != nil { + t.Error(err) + } else if rcv := cfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("\nExpected: %+v\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/stordbcfg.go b/config/stordbcfg.go index fd7f3cd94..1295d5ebe 100644 --- a/config/stordbcfg.go +++ b/config/stordbcfg.go @@ -95,6 +95,7 @@ func (dbcfg *StorDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) { dbcfg.SSLMode = *jsnDbCfg.Sslmode } if jsnDbCfg.Items != nil { + dbcfg.Items = make(map[string]*ItemOpt) for kJsn, vJsn := range *jsnDbCfg.Items { val := new(ItemOpt) if err := val.loadFromJsonCfg(vJsn); err != nil { @@ -131,11 +132,16 @@ func (dbcfg *StorDbCfg) AsMapInterface() map[string]interface{} { for key, item := range dbcfg.Items { items[key] = item.AsMapInterface() } + var queryTimeout string = "0" + if dbcfg.QueryTimeout != 0 { + queryTimeout = dbcfg.QueryTimeout.String() + } + dbPort, _ := strconv.Atoi(dbcfg.Port) return map[string]interface{}{ - utils.TypeCfg: dbcfg.Type, + utils.TypeCfg: utils.Meta + dbcfg.Type, utils.HostCfg: dbcfg.Host, - utils.PortCfg: dbcfg.Port, + utils.PortCfg: dbPort, utils.NameCfg: dbcfg.Name, utils.UserCfg: dbcfg.User, utils.PasswordCfg: dbcfg.Password, @@ -144,7 +150,7 @@ func (dbcfg *StorDbCfg) AsMapInterface() map[string]interface{} { utils.ConnMaxLifetimeCfg: dbcfg.ConnMaxLifetime, utils.StringIndexedFieldsCfg: dbcfg.StringIndexedFields, utils.PrefixIndexedFieldsCfg: dbcfg.PrefixIndexedFields, - utils.QueryTimeoutCfg: dbcfg.QueryTimeout, + utils.QueryTimeoutCfg: queryTimeout, utils.SSLModeCfg: dbcfg.SSLMode, utils.ItemsCfg: items, } diff --git a/config/stordbcfg_test.go b/config/stordbcfg_test.go index b05344dc5..1ef7e654d 100644 --- a/config/stordbcfg_test.go +++ b/config/stordbcfg_test.go @@ -20,6 +20,8 @@ package config import ( "reflect" "testing" + + "github.com/cgrates/cgrates/utils" ) func TestStoreDbCfgloadFromJsonCfg(t *testing.T) { @@ -130,3 +132,57 @@ func TestStoreDbCfgloadFromJsonCfgPort(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", expected, dbcfg) } } + +func TestStorDbCfgAsMapInterface(t *testing.T) { + var dbcfg StorDbCfg + cfgJSONStr := `{ + "stor_db": { + "db_type": "*mysql", + "db_host": "127.0.0.1", + "db_port": -1, + "db_name": "cgrates", + "db_user": "cgrates", + "db_password": "", + "max_open_conns": 100, + "max_idle_conns": 10, + "conn_max_lifetime": 0, + "string_indexed_fields": [], + "prefix_indexed_fields":[], + "query_timeout":"10s", + "sslmode":"disable", + "items":{ + "session_costs": {"limit": -1, "ttl": "", "static_ttl": false}, + "cdrs": {"limit": -1, "ttl": "", "static_ttl": false}, + }, + }, +}` + + eMap := map[string]interface{}{ + "db_type": "*mysql", + "db_host": "127.0.0.1", + "db_port": 3306, + "db_name": "cgrates", + "db_user": "cgrates", + "db_password": "", + "max_open_conns": 100, + "max_idle_conns": 10, + "conn_max_lifetime": 0, + "string_indexed_fields": []string{}, + "prefix_indexed_fields": []string{}, + "query_timeout": "10s", + "sslmode": "disable", + "items": map[string]interface{}{ + "session_costs": map[string]interface{}{"limit": -1, "ttl": "", "static_ttl": false, "remote": false, "replicate": false}, + "cdrs": map[string]interface{}{"limit": -1, "ttl": "", "static_ttl": false, "remote": false, "replicate": false}, + }, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnStoreDbCfg, err := jsnCfg.DbJsonCfg(STORDB_JSN); err != nil { + t.Error(err) + } else if err = dbcfg.loadFromJsonCfg(jsnStoreDbCfg); err != nil { + t.Error(err) + } else if rcv := dbcfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v ,\n recived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/tlscfg_test.go b/config/tlscfg_test.go index c72dcdf13..ef12e5964 100644 --- a/config/tlscfg_test.go +++ b/config/tlscfg_test.go @@ -20,6 +20,8 @@ package config import ( "reflect" "testing" + + "github.com/cgrates/cgrates/utils" ) func TestTlsCfgloadFromJsonCfg(t *testing.T) { @@ -65,3 +67,67 @@ func TestTlsCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected: %+v , recived: %+v", expected, tlscfg) } } +func TestTlsCfgAsMapInterface(t *testing.T) { + var tlscfg TlsCfg + cfgJSONStr := ` { + "tls": { + "server_certificate" : "", + "server_key":"", + "client_certificate" : "", + "client_key":"", + "ca_certificate":"", + "server_policy":4, + "server_name":"", + }, +}` + eMap := map[string]interface{}{ + "server_certificate": "", + "server_key": "", + "client_certificate": "", + "client_key": "", + "ca_certificate": "", + "server_policy": 4, + "server_name": "", + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsntlsCfg, err := jsnCfg.TlsCfgJson(); err != nil { + t.Error(err) + } else if err = tlscfg.loadFromJsonCfg(jsntlsCfg); err != nil { + t.Error(err) + } else if rcv := tlscfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v,\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } + + cfgJSONStr = ` { + "tls":{ + "server_certificate" : "path/To/Server/Cert", + "server_key":"path/To/Server/Key", + "client_certificate" : "path/To/Client/Cert", + "client_key":"path/To/Client/Key", + "ca_certificate":"path/To/CA/Cert", + "server_name":"TestServerName", + "server_policy":3, + }, +}` + eMap = map[string]interface{}{ + "server_certificate": "path/To/Server/Cert", + "server_key": "path/To/Server/Key", + "client_certificate": "path/To/Client/Cert", + "client_key": "path/To/Client/Key", + "ca_certificate": "path/To/CA/Cert", + "server_name": "TestServerName", + "server_policy": 3, + } + + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsntlsCfg, err := jsnCfg.TlsCfgJson(); err != nil { + t.Error(err) + } else if err = tlscfg.loadFromJsonCfg(jsntlsCfg); err != nil { + t.Error(err) + } else if rcv := tlscfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("Expected: %+v,\nRecived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/utils/consts.go b/utils/consts.go index 3bac5b500..dd5a57f39 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -1738,6 +1738,7 @@ const ( // KamAgentCfg EvapiConnsCfg = "evapi_conns" TimezoneCfg = "timezone" + TimezoneCfgC = "Timezone" // AsteriskConnCfg UserCf = "user" @@ -1763,8 +1764,8 @@ const ( RequestProcessorsCfg = "request_processors" // RequestProcessor - RequestFieldsCfg = "Request_fields" - ReplyFieldsCfg = "Reply_fields" + RequestFieldsCfg = "request_fields" + ReplyFieldsCfg = "reply_fields" // RadiusAgentCfg ListenAuthCfg = "listen_auth" @@ -1803,13 +1804,16 @@ const ( TpOutDirCfg = "tp_out_dir" DataCfg = "data" - DefaultRatioCfg = "default_ratio" - ReadersCfg = "readers" - PoolSize = "PoolSize" - Conns = "Conns" - FilenameCfg = "file_name" - RequestPayloadCfg = "Request_payload" - ReplyPayloadCfg = "Reply_payload" + DefaultRatioCfg = "default_ratio" + ReadersCfg = "readers" + PoolSize = "poolSize" + Conns = "conns" + FilenameCfg = "file_name" + RequestPayloadCfg = "request_payload" + ReplyPayloadCfg = "reply_payload" + TransportCfg = "transport" + StrategyCfg = "strategy" + Dynaprepaid_actionplansCfg = "dynaprepaid_actionplans" ) // FC Template