diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index d3a50baaa..a7b7e3bb0 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -25,6 +25,7 @@ import ( "io" "log" "os" + "sort" "strings" "time" @@ -49,9 +50,19 @@ func executeCommand(command string) { } if strings.TrimSpace(command) == "help" { commands := console.GetCommands() + orderedKeys := make([]string, len(commands)) fmt.Println("Commands:") - for name, cmd := range commands { - fmt.Print(name, cmd.Usage()) + for name, _ := range commands { + if name != "" { + orderedKeys = append(orderedKeys, name) + } + } + sort.Strings(orderedKeys) + for _, name := range orderedKeys { + if commands[name] == nil { + continue + } + fmt.Println(name, commands[name].Usage()) } return } diff --git a/config/cgrloadercfg.go b/config/cgrloadercfg.go new file mode 100644 index 000000000..e6eb3330a --- /dev/null +++ b/config/cgrloadercfg.go @@ -0,0 +1,191 @@ +/* +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 ( + "errors" + "fmt" + + "github.com/cgrates/cgrates/utils" + "github.com/dlintw/goconf" +) + +func NewLoaderConfig(cfgPath *string) (lCfg *LoaderCfg, err error) { + lCfg = NewDefaultLoaderConfig() + c, err := goconf.ReadConfigFile(*cfgPath) + if err != nil { + return nil, errors.New(fmt.Sprintf("Could not open the configuration file: %s", err)) + } + if err = lCfg.loadConfig(c); err != nil { + return lCfg, err + } + return +} + +func NewDefaultLoaderConfig() (lCfg *LoaderCfg) { + lCfg = new(LoaderCfg) + lCfg.setDefaults() + return lCfg +} + +type LoaderCfg struct { + DataDBType string + DataDBHost string + DataDBPort string + DataDBName string + DataDBUser string + DataDBPass string + DataDBEncoding string + StorDBType string + StorDBHost string + StorDBPort string + StorDBName string + StorDBUser string + StorDBPass string + Flush bool + Tpid string + DataPath string + Version bool + Verbose bool + DryRun bool + Validate bool + Stats bool + FromStorDB bool + ToStorDB bool + RpcEncoding string + RalsAddress string + CdrstatsAddress string + UsersAddress string + RunId string + LoadHistorySize int + Timezone string + DisableReverse bool + FlushStorDB bool + Remove bool +} + +func (lCfg *LoaderCfg) setDefaults() { + lCfg.DataDBType = cgrCfg.DataDbType + lCfg.DataDBHost = utils.MetaDynamic + lCfg.DataDBPort = utils.MetaDynamic + lCfg.DataDBName = utils.MetaDynamic + lCfg.DataDBUser = utils.MetaDynamic + lCfg.DataDBPass = utils.MetaDynamic + lCfg.StorDBType = cgrCfg.StorDBType + lCfg.StorDBHost = utils.MetaDynamic + lCfg.StorDBPort = utils.MetaDynamic + lCfg.StorDBName = utils.MetaDynamic + lCfg.StorDBUser = utils.MetaDynamic + lCfg.StorDBPass = utils.MetaDynamic + lCfg.Flush = false + lCfg.Tpid = "" + lCfg.DataPath = "./" + lCfg.Version = false + lCfg.Verbose = false + lCfg.DryRun = false + lCfg.Validate = false + lCfg.Stats = false + lCfg.FromStorDB = false + lCfg.ToStorDB = false + lCfg.RpcEncoding = "json" + lCfg.RalsAddress = cgrCfg.RPCJSONListen + lCfg.CdrstatsAddress = cgrCfg.RPCJSONListen + lCfg.UsersAddress = cgrCfg.RPCJSONListen + lCfg.RunId = "" + lCfg.LoadHistorySize = cgrCfg.LoadHistorySize + lCfg.Timezone = cgrCfg.DefaultTimezone + lCfg.DisableReverse = false + lCfg.FlushStorDB = false + lCfg.Remove = false +} + +func (ldrCfg *LoaderCfg) loadConfig(c *goconf.ConfigFile) (err error) { + var hasOpt bool + //dataDB + if hasOpt = c.HasOption("dataDB", "db_type"); hasOpt { + ldrCfg.DataDBType, err = c.GetString("dataDB", "db_type") + } + if hasOpt = c.HasOption("dataDB", "db_host"); hasOpt { + ldrCfg.DataDBHost, err = c.GetString("dataDB", "db_host") + } + if hasOpt = c.HasOption("dataDB", "db_port"); hasOpt { + ldrCfg.DataDBPort, err = c.GetString("dataDB", "db_port") + } + if hasOpt = c.HasOption("dataDB", "db_name"); hasOpt { + ldrCfg.DataDBName, err = c.GetString("dataDB", "db_name") + } + if hasOpt = c.HasOption("dataDB", "db_user"); hasOpt { + ldrCfg.DataDBUser, err = c.GetString("dataDB", "db_user") + } + if hasOpt = c.HasOption("dataDB", "db_password"); hasOpt { + ldrCfg.DataDBPass, err = c.GetString("dataDB", "db_password") + } + //storDB + if hasOpt = c.HasOption("storDB", "db_type"); hasOpt { + ldrCfg.StorDBType, err = c.GetString("storDB", "db_type") + } + if hasOpt = c.HasOption("storDB", "db_host"); hasOpt { + ldrCfg.StorDBHost, err = c.GetString("storDB", "db_host") + } + if hasOpt = c.HasOption("storDB", "db_port"); hasOpt { + ldrCfg.StorDBPort, err = c.GetString("storDB", "db_port") + } + if hasOpt = c.HasOption("storDB", "db_name"); hasOpt { + ldrCfg.StorDBName, err = c.GetString("storDB", "db_name") + } + if hasOpt = c.HasOption("storDB", "db_user"); hasOpt { + ldrCfg.StorDBUser, err = c.GetString("storDB", "db_user") + } + if hasOpt = c.HasOption("storDB", "db_password"); hasOpt { + ldrCfg.StorDBPass, err = c.GetString("storDB", "db_password") + } + //general + if hasOpt = c.HasOption("general", "tpid"); hasOpt { + ldrCfg.Tpid, err = c.GetString("general", "tpid") + } + if hasOpt = c.HasOption("general", "dataPath"); hasOpt { + ldrCfg.DataPath, err = c.GetString("general", "dataPath") + } + if hasOpt = c.HasOption("general", "rpcEncoding"); hasOpt { + ldrCfg.RpcEncoding, err = c.GetString("general", "rpcEncoding") + } + if hasOpt = c.HasOption("general", "ralsAddress"); hasOpt { + ldrCfg.RalsAddress, err = c.GetString("general", "ralsAddress") + } + if hasOpt = c.HasOption("general", "cdrstatsAddress"); hasOpt { + ldrCfg.CdrstatsAddress, err = c.GetString("general", "cdrstatsAddress") + } + if hasOpt = c.HasOption("general", "usersAddress"); hasOpt { + ldrCfg.UsersAddress, err = c.GetString("general", "usersAddress") + } + if hasOpt = c.HasOption("general", "runId"); hasOpt { + ldrCfg.RunId, err = c.GetString("general", "runId") + } + if hasOpt = c.HasOption("general", "loadHistorySize"); hasOpt { + ldrCfg.LoadHistorySize, err = c.GetInt("general", "loadHistorySize") + } + if hasOpt = c.HasOption("general", "timezone"); hasOpt { + ldrCfg.Timezone, err = c.GetString("general", "timezone") + } + if hasOpt = c.HasOption("general", "disable_reverse"); hasOpt { + ldrCfg.DisableReverse, err = c.GetBool("general", "disable_reverse") + } + + return err +} diff --git a/config/cgrloadercfg_test.go b/config/cgrloadercfg_test.go new file mode 100644 index 000000000..9bd8cd443 --- /dev/null +++ b/config/cgrloadercfg_test.go @@ -0,0 +1,150 @@ +/* +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" + "testing" + + "github.com/cgrates/cgrates/utils" + "github.com/dlintw/goconf" +) + +func TestCgrLoaderCfgSetDefault(t *testing.T) { + rcv := &LoaderCfg{} + rcv.setDefaults() + expected := &LoaderCfg{ + DataDBType: cgrCfg.DataDbType, + DataDBHost: utils.MetaDynamic, + DataDBPort: utils.MetaDynamic, + DataDBName: utils.MetaDynamic, + DataDBUser: utils.MetaDynamic, + DataDBPass: utils.MetaDynamic, + StorDBType: cgrCfg.StorDBType, + StorDBHost: utils.MetaDynamic, + StorDBPort: utils.MetaDynamic, + StorDBName: utils.MetaDynamic, + StorDBUser: utils.MetaDynamic, + StorDBPass: utils.MetaDynamic, + Flush: false, + Tpid: "", + DataPath: "./", + Version: false, + Verbose: false, + DryRun: false, + Validate: false, + Stats: false, + FromStorDB: false, + ToStorDB: false, + RpcEncoding: "json", + RalsAddress: cgrCfg.RPCJSONListen, + CdrstatsAddress: cgrCfg.RPCJSONListen, + UsersAddress: cgrCfg.RPCJSONListen, + RunId: "", + LoadHistorySize: cgrCfg.LoadHistorySize, + Timezone: cgrCfg.DefaultTimezone, + DisableReverse: false, + FlushStorDB: false, + Remove: false, + } + + if !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expected: %+v, received: %+v", expected, rcv) + } +} + +func TestCgrLoaderCfgNewDefault(t *testing.T) { + rcv := NewDefaultLoaderConfig() + expected := &LoaderCfg{ + DataDBType: cgrCfg.DataDbType, + DataDBHost: utils.MetaDynamic, + DataDBPort: utils.MetaDynamic, + DataDBName: utils.MetaDynamic, + DataDBUser: utils.MetaDynamic, + DataDBPass: utils.MetaDynamic, + StorDBType: cgrCfg.StorDBType, + StorDBHost: utils.MetaDynamic, + StorDBPort: utils.MetaDynamic, + StorDBName: utils.MetaDynamic, + StorDBUser: utils.MetaDynamic, + StorDBPass: utils.MetaDynamic, + Flush: false, + Tpid: "", + DataPath: "./", + Version: false, + Verbose: false, + DryRun: false, + Validate: false, + Stats: false, + FromStorDB: false, + ToStorDB: false, + RpcEncoding: "json", + RalsAddress: cgrCfg.RPCJSONListen, + CdrstatsAddress: cgrCfg.RPCJSONListen, + UsersAddress: cgrCfg.RPCJSONListen, + RunId: "", + LoadHistorySize: cgrCfg.LoadHistorySize, + Timezone: cgrCfg.DefaultTimezone, + DisableReverse: false, + FlushStorDB: false, + Remove: false, + } + + if !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expected: %+v, received: %+v", expected, rcv) + } +} + +func TestCgrLoaderCfgLoad(t *testing.T) { + cfgPath := "/usr/share/cgrates/conf/cgrates/cgr-loader.cfg" + c, err := goconf.ReadConfigFile(cfgPath) + if err != nil { + t.Error(err) + } + rcv := &LoaderCfg{} + if err := rcv.loadConfig(c); err != nil { + t.Error(err) + } + expected := &LoaderCfg{ + DataDBType: "redis", + DataDBHost: "127.0.0.1", + DataDBPort: "6379", + DataDBName: "10", + DataDBUser: "cgrates", + DataDBPass: "testdatapw", + StorDBType: "mysql", + StorDBHost: "127.0.0.1", + StorDBPort: "3306", + StorDBName: "cgrates", + StorDBUser: "cgrates", + StorDBPass: "teststorpw", + Tpid: "testtpid", + DataPath: "./", + RpcEncoding: "json", + RalsAddress: "testRALsAddress", + CdrstatsAddress: "testcdrstatsaddress", + UsersAddress: "testuseraddress", + RunId: "testrunId", + LoadHistorySize: 10, + Timezone: "Local", + DisableReverse: false, + } + if !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expected: %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rcv)) + } +} diff --git a/config/config.go b/config/config.go index c6de12f08..462a2789f 100755 --- a/config/config.go +++ b/config/config.go @@ -48,7 +48,7 @@ var ( dfltKamConnConfig *KamConnConfig // Default Kamailio Connection configuration dfltHaPoolConfig *HaPoolConfig dfltAstConnCfg *AsteriskConnCfg - dfltLoaderConfig *LoaderConfig + dfltLoaderConfig *LoaderSConfig dfltLoaderDataTypeConfig *LoaderDataType ) @@ -349,7 +349,7 @@ type CGRConfig struct { statsCfg *StatSCfg // Configuration for StatS thresholdSCfg *ThresholdSCfg // configuration for ThresholdS supplierSCfg *SupplierSCfg // configuration for SupplierS - loaderCfg []*LoaderConfig // configuration for Loader + 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 @@ -1183,9 +1183,9 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) { } if jsnLoaderCfg != nil { - self.loaderCfg = make([]*LoaderConfig, len(jsnLoaderCfg)) + self.loaderCfg = make([]*LoaderSConfig, len(jsnLoaderCfg)) for idx, profile := range jsnLoaderCfg { - self.loaderCfg[idx] = NewDfltLoaderConfig() + self.loaderCfg[idx] = NewDfltLoaderSConfig() self.loaderCfg[idx].loadFromJsonCfg(profile) } } @@ -1436,7 +1436,7 @@ func (cfg *CGRConfig) CacheCfg() CacheConfig { return cfg.cacheConfig } -func (cfg *CGRConfig) LoaderCfg() []*LoaderConfig { +func (cfg *CGRConfig) LoaderCfg() []*LoaderSConfig { return cfg.loaderCfg } diff --git a/config/config_test.go b/config/config_test.go index d1ec8198c..1dd760506 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -915,8 +915,8 @@ func TestDbDefaults(t *testing.T) { } func TestCgrCfgLoaderDefaults(t *testing.T) { - eCfg := []*LoaderConfig{ - &LoaderConfig{ + eCfg := []*LoaderSConfig{ + &LoaderSConfig{ Id: utils.META_DEFAULT, Enabled: false, DryRun: false, diff --git a/config/loadersconfig.go b/config/loadersconfig.go index 7463b1a61..4919c2c68 100644 --- a/config/loadersconfig.go +++ b/config/loadersconfig.go @@ -22,15 +22,15 @@ import ( "time" ) -func NewDfltLoaderConfig() *LoaderConfig { +func NewDfltLoaderSConfig() *LoaderSConfig { if dfltLoaderConfig == nil { - return new(LoaderConfig) + return new(LoaderSConfig) } dfltVal := *dfltLoaderConfig return &dfltVal } -type LoaderConfig struct { // rename to LoaderConfig +type LoaderSConfig struct { // rename to LoaderSConfig Id string Enabled bool DryRun bool @@ -78,7 +78,7 @@ func (self *LoaderDataType) loadFromJsonCfg(jsnCfg *LoaderJsonDataType) error { return nil } -func (self *LoaderConfig) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) error { +func (self *LoaderSConfig) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) error { if jsnCfg == nil { return nil } @@ -127,8 +127,8 @@ func (self *LoaderConfig) loadFromJsonCfg(jsnCfg *LoaderJsonCfg) error { } // Clone itself into a new LoadersConfig -func (self *LoaderConfig) Clone() *LoaderConfig { - clnLoader := new(LoaderConfig) +func (self *LoaderSConfig) Clone() *LoaderSConfig { + clnLoader := new(LoaderSConfig) clnLoader.Id = self.Id clnLoader.Enabled = self.Enabled clnLoader.DryRun = self.DryRun diff --git a/console/ping.go b/console/ping.go index d03fcfae8..2f9fc598f 100644 --- a/console/ping.go +++ b/console/ping.go @@ -49,21 +49,21 @@ func (self *CmdApierPing) Name() string { func (self *CmdApierPing) RpcMethod() string { switch strings.ToLower(self.rpcParams.Item) { - case utils.LowerSuppliers: + case utils.SuppliersLow: return utils.SupplierSv1Ping - case utils.LowerAttributes: + case utils.AttributesLow: return utils.AttributeSv1Ping - case utils.LowerResources: + case utils.ResourcesLow: return utils.ResourceSv1Ping - case utils.LowerStatService: + case utils.StatServiceLow: return utils.StatSv1Ping - case utils.LowerThresholds: + case utils.ThresholdsLow: return utils.ThresholdSv1Ping - case utils.LowerSessions: + case utils.SessionsLow: return utils.SessionSv1Ping - case utils.LowerLoader: + case utils.LoaderLow: return utils.LoaderSv1Ping - case utils.LowerDispatchers: + case utils.DispatchersLow: return utils.DispatcherSv1Ping default: } diff --git a/data/conf/cgrates/cgr-loader.cfg b/data/conf/cgrates/cgr-loader.cfg new file mode 100644 index 000000000..d94e23caa --- /dev/null +++ b/data/conf/cgrates/cgr-loader.cfg @@ -0,0 +1,29 @@ +# cgr-loader configuration file + +[dataDB] + db_type = redis + db_host = 127.0.0.1 + db_port = 6379 + db_name = 10 + db_user = cgrates + db_password = testdatapw + +[storDB] + db_type = mysql + db_host = 127.0.0.1 + db_port = 3306 + db_name = cgrates + db_user = cgrates + db_password = teststorpw + +[general] + tpid = testtpid + dataPath = ./ + rpcEncoding = json + ralsAddress = testRALsAddress + cdrstatsAddress = testcdrstatsaddress + usersAddress = testuseraddress + runId = testrunId + loadHistorySize = 10 + timezone = Local + disable_reverse = false \ No newline at end of file diff --git a/loaders/loader.go b/loaders/loader.go index 8a87d3c04..14bfeb9a8 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.LoaderConfig, +func NewLoader(dm *engine.DataManager, cfg *config.LoaderSConfig, timezone string) (ldr *Loader) { ldr = &Loader{ enabled: cfg.Enabled, diff --git a/loaders/loaders.go b/loaders/loaders.go index f44205a06..568f36367 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.LoaderConfig, +func NewLoaderService(dm *engine.DataManager, ldrsCfg []*config.LoaderSConfig, timezone string) (ldrS *LoaderService) { ldrS = &LoaderService{ldrs: make(map[string]*Loader)} for _, ldrCfg := range ldrsCfg { diff --git a/utils/consts.go b/utils/consts.go index 5fa11206a..a9a79c347 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -565,14 +565,14 @@ const ( // Lower service names const ( - LowerSessions = "sessions" - LowerAttributes = "attributes" - LowerSuppliers = "suppliers" - LowerResources = "resources" - LowerStatService = "stats" - LowerThresholds = "thresholds" - LowerDispatchers = "dispatchers" - LowerLoader = "loader" + SessionsLow = "sessions" + AttributesLow = "attributes" + SuppliersLow = "suppliers" + ResourcesLow = "resources" + StatServiceLow = "stats" + ThresholdsLow = "thresholds" + DispatchersLow = "dispatchers" + LoaderLow = "loader" ) //Migrator Metas