diff --git a/config/config.go b/config/config.go index 187ce4bbb..0bc365efe 100755 --- a/config/config.go +++ b/config/config.go @@ -37,7 +37,7 @@ var ( dfltKamConnConfig *KamConnConfig // Default Kamailio Connection configuration dfltHaPoolConfig *HaPoolConfig dfltAstConnCfg *AsteriskConnCfg - dfltLoaderConfig *LoaderSConfig + dfltLoaderConfig *LoaderSCfg dfltLoaderDataTypeConfig *LoaderDataType ) @@ -256,6 +256,7 @@ type CGRConfig struct { MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file CdreProfiles map[string]*CdreCfg + loaderCfg []*LoaderSCfg // configuration for Loader CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs} sessionSCfg *SessionSCfg @@ -276,7 +277,6 @@ type CGRConfig struct { statsCfg *StatSCfg // Configuration for StatS thresholdSCfg *ThresholdSCfg // configuration for ThresholdS supplierSCfg *SupplierSCfg // configuration for SupplierS - loaderCfg []*LoaderSConfig // configuration for Loader dispatcherSCfg *DispatcherSCfg // configuration for Dispatcher MailerServer string // The server to use when sending emails out MailerAuthUser string // Authenticate to email server using this user @@ -954,9 +954,9 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) { } if jsnLoaderCfg != nil { - self.loaderCfg = make([]*LoaderSConfig, len(jsnLoaderCfg)) + self.loaderCfg = make([]*LoaderSCfg, len(jsnLoaderCfg)) for idx, profile := range jsnLoaderCfg { - self.loaderCfg[idx] = NewDfltLoaderSConfig() + self.loaderCfg[idx] = NewDfltLoaderSCfg() self.loaderCfg[idx].loadFromJsonCfg(profile) } } @@ -1252,7 +1252,7 @@ func (cfg *CGRConfig) CacheCfg() CacheCfg { return cfg.cacheCfg } -func (cfg *CGRConfig) LoaderCfg() []*LoaderSConfig { +func (cfg *CGRConfig) LoaderCfg() []*LoaderSCfg { return cfg.loaderCfg } diff --git a/config/config_test.go b/config/config_test.go index 16c906b4a..5cef20a7c 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -1079,7 +1079,7 @@ func TestDbDefaults(t *testing.T) { } func TestCgrLoaderCfgITDefaults(t *testing.T) { - eCfg := []*LoaderSConfig{ + eCfg := []*LoaderSCfg{ { Id: utils.META_DEFAULT, Enabled: false, diff --git a/config/loadercfg.go b/config/loadercgrcfg.go similarity index 100% rename from config/loadercfg.go rename to config/loadercgrcfg.go diff --git a/config/loadersconfig.go b/config/loaderscfg.go similarity index 93% rename from config/loadersconfig.go rename to config/loaderscfg.go index fe94d0c9b..b7e496ba7 100644 --- a/config/loadersconfig.go +++ b/config/loaderscfg.go @@ -22,15 +22,15 @@ import ( "time" ) -func NewDfltLoaderSConfig() *LoaderSConfig { +func NewDfltLoaderSCfg() *LoaderSCfg { if dfltLoaderConfig == nil { - return new(LoaderSConfig) + return new(LoaderSCfg) } dfltVal := *dfltLoaderConfig return &dfltVal } -type LoaderSConfig struct { // rename to LoaderSConfig +type LoaderSCfg struct { Id string Enabled bool Tenant RSRParsers @@ -76,7 +76,7 @@ func (self *LoaderDataType) loadFromJsonCfg(jsnCfg *LoaderJsonDataType) (err err return nil } -func (self *LoaderSConfig) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) (err error) { +func (self *LoaderSCfg) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) (err error) { if jsnCfg == nil { return nil } @@ -130,8 +130,8 @@ func (self *LoaderSConfig) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) (err error) { } // Clone itself into a new LoadersConfig -func (self *LoaderSConfig) Clone() *LoaderSConfig { - clnLoader := new(LoaderSConfig) +func (self *LoaderSCfg) Clone() *LoaderSCfg { + clnLoader := new(LoaderSCfg) clnLoader.Id = self.Id clnLoader.Enabled = self.Enabled clnLoader.Tenant = self.Tenant diff --git a/config/loaderscfg_test.go b/config/loaderscfg_test.go new file mode 100644 index 000000000..1232eaa49 --- /dev/null +++ b/config/loaderscfg_test.go @@ -0,0 +1,107 @@ +/* +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 +*/ +package config + +import ( + "reflect" + "strings" + "testing" + + "github.com/cgrates/cgrates/utils" +) + +func TestLoaderSCfgloadFromJsonCfg(t *testing.T) { + var loadscfg, expected LoaderSCfg + if err := loadscfg.loadFromJsonCfg(nil); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(loadscfg, expected) { + t.Errorf("Expected: %+v ,recived: %+v", expected, loadscfg) + } + if err := loadscfg.loadFromJsonCfg(new(LoaderJsonCfg)); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(loadscfg, expected) { + t.Errorf("Expected: %+v ,recived: %+v", expected, loadscfg) + } + cfgJSONStr := `{ +"loaders": [ + { + "id": "*default", // identifier of the Loader + "enabled": false, // starts as service: . + "tenant": "cgrates.org", // tenant used in filterS.Pass + "dry_run": false, // do not send the CDRs to CDRS, just parse them + "run_delay": 0, // sleep interval in seconds between consecutive runs, 0 to use automation via inotify + "lock_filename": ".cgr.lck", // Filename containing concurrency lock in case of delayed processing + "caches_conns": [ + {"address": "*internal"}, // address where to reach the CacheS for data reload, empty for no reloads <""|*internal|x.y.z.y:1234> + ], + "field_separator": ",", // separator used in case of csv files + "tp_in_dir": "/var/spool/cgrates/loader/in", // absolute path towards the directory where the CDRs are stored + "tp_out_dir": "/var/spool/cgrates/loader/out", // absolute path towards the directory where processed CDRs will be moved + "data":[ // data profiles to load + { + "type": "*attributes", // data source type + "file_name": "Attributes.csv", // file name in the tp_in_dir + "fields": [ + {"tag": "TenantID", "field_id": "Tenant", "type": "*composed", "value": "~0", "mandatory": true}, + ], + },] + } + ] +}` + val, err := NewRSRParsers("~0", true) + if err != nil { + t.Error(err) + } + ten, err := NewRSRParsers("cgrates.org", true) + if err != nil { + t.Error(err) + } + expected = LoaderSCfg{ + Id: "*default", + Tenant: ten, + LockFileName: ".cgr.lck", + CacheSConns: []*HaPoolConfig{{Address: utils.MetaInternal}}, + FieldSeparator: ",", + TpInDir: "/var/spool/cgrates/loader/in", + TpOutDir: "/var/spool/cgrates/loader/out", + Data: []*LoaderDataType{ + { + Type: "*attributes", + Filename: "Attributes.csv", + Fields: []*FCTemplate{ + { + Tag: "TenantID", + FieldId: "Tenant", + Type: "*composed", + Value: val, + Mandatory: true, + }, + }, + }, + }, + } + if jsnCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnLoadersCfg, err := jsnCfg.LoaderJsonCfg(); err != nil { + t.Error(err) + } else if err = loadscfg.loadFromJsonCfg(jsnLoadersCfg[0]); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, loadscfg) { + t.Errorf("Expected: %+v , recived: %+v", utils.ToJSON(expected), utils.ToJSON(loadscfg)) + } +} diff --git a/loaders/loader.go b/loaders/loader.go index a84cceef5..65bc19fd7 100644 --- a/loaders/loader.go +++ b/loaders/loader.go @@ -38,7 +38,7 @@ type openedCSVFile struct { csvRdr *csv.Reader } -func NewLoader(dm *engine.DataManager, cfg *config.LoaderSConfig, +func NewLoader(dm *engine.DataManager, cfg *config.LoaderSCfg, timezone string, filterS *engine.FilterS) (ldr *Loader) { ldr = &Loader{ enabled: cfg.Enabled, diff --git a/loaders/loaders.go b/loaders/loaders.go index b98263a08..1f9557859 100644 --- a/loaders/loaders.go +++ b/loaders/loaders.go @@ -27,7 +27,7 @@ import ( "github.com/cgrates/cgrates/utils" ) -func NewLoaderService(dm *engine.DataManager, ldrsCfg []*config.LoaderSConfig, +func NewLoaderService(dm *engine.DataManager, ldrsCfg []*config.LoaderSCfg, timezone string, filterS *engine.FilterS) (ldrS *LoaderService) { ldrS = &LoaderService{ldrs: make(map[string]*Loader)} for _, ldrCfg := range ldrsCfg {