This commit is contained in:
DanB
2015-07-13 16:36:00 +02:00
56 changed files with 369 additions and 155 deletions

View File

@@ -77,11 +77,13 @@ func executeCommand(command string) {
}
if cmd.RpcMethod() != "" {
res := cmd.RpcResult()
param := cmd.RpcParams(true)
param := cmd.RpcParams(true, false)
//log.Print(reflect.TypeOf(param))
switch param.(type) {
case *console.StringWrapper:
param = param.(*console.StringWrapper).Item
case *console.StringSliceWrapper:
param = param.(*console.StringSliceWrapper).Items
}
//log.Printf("Param: %+v", param)

View File

@@ -459,12 +459,12 @@ func main() {
server.RpcRegister(&v1.CDRStatsV1{CdrStats: cdrStats}) // Public APIs
}
if cfg.PubSubEnabled {
if cfg.PubSubServerEnabled {
pubSubServer = engine.NewPubSub(accountDb, cfg.HttpSkipTlsVerify)
server.RpcRegisterName("PubSubV1", pubSubServer)
}
if cfg.HistoryEnabled {
if cfg.HistoryServerEnabled {
scribeServer, err = history.NewFileScribe(cfg.HistoryDir, cfg.HistorySaveInterval)
if err != nil {
engine.Logger.Crit(fmt.Sprintf("<HistoryServer> Could not start, error: %s", err.Error()))
@@ -474,7 +474,11 @@ func main() {
}
if cfg.UserServerEnabled {
userServer = engine.NewUserMap(ratingDb)
userServer, err = engine.NewUserMap(ratingDb)
if err != nil {
engine.Logger.Crit(fmt.Sprintf("<UsersService> Could not start, error: %s", err.Error()))
exitChan <- true
}
server.RpcRegisterName("UsersV1", userServer)
if len(cfg.UserServerIndexes) != 0 {
var s string

View File

@@ -208,8 +208,7 @@ type CGRConfig struct {
CDRSCdrReplication []*CdrReplicationCfg // Replicate raw CDRs to a number of servers
CDRStatsEnabled bool // Enable CDR Stats service
CDRStatsSaveInterval time.Duration // Save interval duration
PubSubEnabled bool
HistoryEnabled bool
//CDRStatConfig *CdrStatsConfig // Active cdr stats configuration instances, platform level
CdreProfiles map[string]*CdreConfig
CdrcProfiles map[string]map[string]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath]map[instanceName]{Configs}
SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration

View File

@@ -45,8 +45,8 @@ func (self *CmdAddAccount) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdAddAccount) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdAddAccount) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrSetAccount{Direction: utils.OUT}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdSetAccountActions) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdSetAccountActions) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdSetAccountActions) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.TPAccountActions{}
}
if ptr {

View File

@@ -49,8 +49,8 @@ func (self *CmdGetAccounts) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetAccounts) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetAccounts) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrGetAccounts{Direction: "*out"}
}
if ptr {

View File

@@ -48,8 +48,8 @@ func (self *CmdExecuteAction) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdExecuteAction) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdExecuteAction) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrExecuteAction{Direction: utils.OUT}
}
if ptr {

View File

@@ -48,8 +48,8 @@ func (self *CmdActiveSessions) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdActiveSessions) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdActiveSessions) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrGetSMASessions{}
}
if ptr {

View File

@@ -48,8 +48,8 @@ func (self *CmdDebitBalance) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdDebitBalance) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdDebitBalance) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.CallDescriptor{Direction: "*out"}
}
if ptr {

View File

@@ -48,8 +48,8 @@ func (self *CmdAddBalance) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdAddBalance) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdAddBalance) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrAddBalance{BalanceType: utils.MONETARY, Overwrite: false}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdGetCacheAge) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetCacheAge) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetCacheAge) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *CmdReloadCache) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdReloadCache) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdReloadCache) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.ApiReloadCache{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdGetCacheStats) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetCacheStats) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetCacheStats) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrCacheStats{}
}
if ptr {

View File

@@ -49,8 +49,8 @@ func (self *CmdGetCostDetails) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetCostDetails) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetCostDetails) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrGetCallCost{RunId: utils.DEFAULT_RUNID}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdExportCdrs) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdExportCdrs) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdExportCdrs) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrExportCdrsToFile{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdRemCdrs) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdRemCdrs) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdRemCdrs) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrRemCdrs{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdCdrStatsMetrics) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrStatsMetrics) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrStatsMetrics) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrGetMetrics{}
}
if ptr {

View File

@@ -44,8 +44,8 @@ func (self *CmdCdrStatsQueue) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrStatsQueue) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrStatsQueue) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -44,8 +44,8 @@ func (self *CmdCdrStatsQueueTriggers) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrStatsQueueTriggers) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrStatsQueueTriggers) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -42,8 +42,8 @@ func (self *CmdCdrStatsQueueIds) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrStatsQueueIds) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrStatsQueueIds) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -47,8 +47,8 @@ func (self *CmdCdrReloadQueues) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrReloadQueues) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrReloadQueues) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrCDRStatsReloadQueues{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdCdrResetQueues) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdCdrResetQueues) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdCdrResetQueues) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrCDRStatsReloadQueues{}
}
if ptr {

View File

@@ -33,7 +33,7 @@ type Commander interface {
FromArgs(args string, verbose bool) error // Load data from os arguments or flag.Args()
Usage() string // usage message
RpcMethod() string // Method which should be called remotely
RpcParams(bool) interface{} // Parameters to send out on rpc
RpcParams(bool, bool) interface{} // Parameters to send out on rpc
PostprocessRpcParams() error // Corrects rpc parameters when needed
RpcResult() interface{} // Only requirement is to have a String method to print on console
ClientArgs() []string // for autocompletion
@@ -84,3 +84,7 @@ func GetCommandValue(command string, verbose bool) (Commander, error) {
type StringWrapper struct {
Item string
}
type StringSliceWrapper struct {
Items []string
}

View File

@@ -40,17 +40,18 @@ type CommandExecuter struct {
}
func (ce *CommandExecuter) Usage() string {
jsn, _ := json.Marshal(ce.command.RpcParams(true))
jsn, _ := json.Marshal(ce.command.RpcParams(true, true))
return fmt.Sprintf("\n\tUsage: %s %s \n", ce.command.Name(), FromJSON(jsn, ce.command.ClientArgs()))
}
// Parses command line args and builds CmdBalance value
func (ce *CommandExecuter) FromArgs(args string, verbose bool) error {
if err := json.Unmarshal(ToJSON(args), ce.command.RpcParams(true)); err != nil {
params := ce.command.RpcParams(true, true)
if err := json.Unmarshal(ToJSON(args), params); err != nil {
return err
}
if verbose {
jsn, _ := json.Marshal(ce.command.RpcParams(true))
jsn, _ := json.Marshal(params)
fmt.Println(ce.command.Name(), FromJSON(jsn, ce.command.ClientArgs()))
}
return nil
@@ -73,7 +74,7 @@ func (ce *CommandExecuter) clientArgs(iface interface{}) (args []string) {
}
func (ce *CommandExecuter) ClientArgs() (args []string) {
return ce.clientArgs(ce.command.RpcParams(false))
return ce.clientArgs(ce.command.RpcParams(false, true))
}
// To be overwritten by commands that do not need a rpc call

View File

@@ -47,8 +47,8 @@ func (self *CmdGetCost) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetCost) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetCost) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.CallDescriptor{Direction: "*out"}
}
if ptr {

View File

@@ -51,8 +51,8 @@ func (self *CmdGetDataCost) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetDataCost) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetDataCost) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrGetDataCost{Direction: utils.OUT}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdGetDestination) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetDestination) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetDestination) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *CmdSetDestination) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdSetDestination) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdSetDestination) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrSetDestination{}
}
if ptr {

View File

@@ -48,8 +48,8 @@ func (self *CmdGetLcr) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetLcr) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetLcr) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.LcrRequest{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *LoadTpFromFolder) RpcMethod() string {
return self.rpcMethod
}
func (self *LoadTpFromFolder) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *LoadTpFromFolder) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrLoadTpFromFolder{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *LoadTpFromStorDb) RpcMethod() string {
return self.rpcMethod
}
func (self *LoadTpFromStorDb) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *LoadTpFromStorDb) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrLoadTpFromStorDb{}
}
if ptr {

View File

@@ -47,8 +47,8 @@ func (self *CmdGetMaxDuration) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetMaxDuration) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetMaxDuration) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.CallDescriptor{Direction: "*out"}
}
if ptr {

View File

@@ -49,8 +49,8 @@ func (self *CmdParse) RpcMethod() string {
return ""
}
func (self *CmdParse) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdParse) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &AttrParse{}
}
if ptr {

View File

@@ -44,8 +44,8 @@ func (self *CmdPublish) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdPublish) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdPublish) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.PublishInfo{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *CmdSetRatingProfile) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdSetRatingProfile) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdSetRatingProfile) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.TPRatingProfile{}
}
if ptr {

View File

@@ -43,8 +43,8 @@ func (self *CmdReloadScheduler) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdReloadScheduler) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdReloadScheduler) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdGetSharedGroup) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetSharedGroup) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetSharedGroup) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -42,8 +42,8 @@ func (self *CmdStatus) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdStatus) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdStatus) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -44,8 +44,8 @@ func (self *CmdSubscribe) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdSubscribe) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdSubscribe) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.SubscribeInfo{}
}
if ptr {

View File

@@ -22,7 +22,7 @@ import "github.com/cgrates/cgrates/engine"
func init() {
c := &CmdShowSubscribers{
name: "show_subscribers",
name: "subscribers",
rpcMethod: "PubSubV1.ShowSubscribers",
}
commands[c.Name()] = c
@@ -44,8 +44,8 @@ func (self *CmdShowSubscribers) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdShowSubscribers) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdShowSubscribers) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdAddTriggeredAction) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdAddTriggeredAction) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdAddTriggeredAction) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrAddActionTrigger{BalanceDirection: "*out"}
}
if ptr {

View File

@@ -44,8 +44,8 @@ func (self *CmdUnsubscribe) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdUnsubscribe) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdUnsubscribe) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.SubscribeInfo{}
}
if ptr {

View File

@@ -31,7 +31,7 @@ func init() {
type CmdUserAddIndex struct {
name string
rpcMethod string
rpcParams *[]string
rpcParams *StringSliceWrapper
*CommandExecuter
}
@@ -43,9 +43,9 @@ func (self *CmdUserAddIndex) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdUserAddIndex) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
self.rpcParams = &[]string{}
func (self *CmdUserAddIndex) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringSliceWrapper{}
}
if ptr {
return self.rpcParams

63
console/user_indexes.go Normal file
View File

@@ -0,0 +1,63 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2012-2015 ITsysCOM
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
func init() {
c := &CmdUserShowIndexes{
name: "user_indexes",
rpcMethod: "UsersV1.GetIndexes",
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
}
// Commander implementation
type CmdUserShowIndexes struct {
name string
rpcMethod string
rpcParams *StringWrapper
*CommandExecuter
}
func (self *CmdUserShowIndexes) Name() string {
return self.name
}
func (self *CmdUserShowIndexes) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdUserShowIndexes) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &StringWrapper{}
}
if ptr {
return self.rpcParams
}
return *self.rpcParams
}
func (self *CmdUserShowIndexes) PostprocessRpcParams() error {
return nil
}
func (self *CmdUserShowIndexes) RpcResult() interface{} {
s := map[string][]string{}
return &s
}

View File

@@ -45,8 +45,8 @@ func (self *CmdUserRemove) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdUserRemove) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdUserRemove) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.UserProfile{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdSetUser) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdSetUser) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdSetUser) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.UserProfile{}
}
if ptr {

View File

@@ -45,8 +45,8 @@ func (self *CmdUpdateUser) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdUpdateUser) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdUpdateUser) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.UserProfile{}
}
if ptr {

View File

@@ -46,8 +46,8 @@ func (self *CmdGetUsers) RpcMethod() string {
return self.rpcMethod
}
func (self *CmdGetUsers) RpcParams(ptr bool) interface{} {
if self.rpcParams == nil {
func (self *CmdGetUsers) RpcParams(ptr, reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &engine.UserProfile{}
}
if ptr {

View File

@@ -12,19 +12,20 @@
"rater": {
"enabled": true, // enable Rater service: <true|false>
"pubsubs": "internal",
"users": "internal",
},
"scheduler": {
"enabled": true, // start Scheduler service: <true|false>
},
"pubsub_server": {
"pubsubs": {
"enabled": true, // starts pubsub service: <true|false>.
},
"pubsub_agent": {
"enabled": true, // starts pubsub as a client: <true|false>.
"server": "internal", // address where to reach the master pubsub server: <internal|x.y.z.y:1234>
"users": {
"enabled": true, // starts users service: <true|false>.
},
}

View File

@@ -27,9 +27,10 @@ ln -s /root/code/bin/cgr-engine /usr/bin/cgr-engine
# expand freeswitch conf
cd /usr/share/cgrates/tutorials/fs_evsock/freeswitch/etc/ && tar xzf freeswitch_conf.tar.gz
cd /root/.oh-my-zsh; git pull
cd /root/cgr
echo "for cgradmin run: cgr-engine -config_dir data/conf/samples/cgradmin"
echo 'export GOROOT=/root/go; export GOPATH=/root/code; export PATH=$GOROOT/bin:$GOPATH/bin:$PATH'>>/root/.zshrc
#/bin/sh /root/.oh-my-zsh/tools/upgrade.sh
zsh
DISABLE_AUTO_UPDATE="true" zsh

View File

@@ -73,6 +73,7 @@ type RatingStorage interface {
GetAccountAliases(string, string, bool) ([]string, error)
SetUser(*UserProfile) error
GetUser(string) (*UserProfile, error)
GetUsers() ([]*UserProfile, error)
RemoveUser(string) error
}

View File

@@ -601,6 +601,19 @@ func (ms *MapStorage) GetUser(key string) (up *UserProfile, err error) {
}
return
}
func (ms *MapStorage) GetUsers() (result []*UserProfile, err error) {
for key, value := range ms.dict {
if strings.HasPrefix(key, utils.USERS_PREFIX) {
up := &UserProfile{}
if err = ms.ms.Unmarshal(value, up); err == nil {
result = append(result, up)
}
}
}
return
}
func (ms *MapStorage) RemoveUser(key string) error {
delete(ms.dict, utils.USERS_PREFIX+key)
return nil

View File

@@ -716,6 +716,23 @@ func (rs *RedisStorage) GetUser(key string) (up *UserProfile, err error) {
return
}
func (rs *RedisStorage) GetUsers() (result []*UserProfile, err error) {
keys, err := rs.db.Keys(utils.USERS_PREFIX + "*")
if err != nil {
return nil, err
}
for _, key := range keys {
if values, err := rs.db.Get(key); err == nil {
up := &UserProfile{}
err = rs.ms.Unmarshal(values, up)
result = append(result, up)
} else {
return nil, utils.ErrNotFound
}
}
return
}
func (rs *RedisStorage) SetSubscriber(key string, sub *SubscriberData) (err error) {
result, err := rs.ms.Marshal(sub)
rs.db.Set(utils.PUBSUB_SUBSCRIBERS_PREFIX+key, result)

View File

@@ -33,38 +33,55 @@ type UserService interface {
UpdateUser(UserProfile, *string) error
GetUsers(UserProfile, *[]*UserProfile) error
AddIndex([]string, *string) error
GetIndexes(string, *map[string][]string) error
}
type UserMap struct {
table map[string]map[string]string
index map[string][]string
ratingDb RatingStorage
table map[string]map[string]string
index map[string]map[string]bool
indexKeys []string
ratingDb RatingStorage
}
func NewUserMap(ratingDb RatingStorage) *UserMap {
func NewUserMap(ratingDb RatingStorage) (*UserMap, error) {
um := newUserMap(ratingDb)
// load from rating db
if ups, err := um.ratingDb.GetUsers(); err == nil {
for _, up := range ups {
um.table[up.GetId()] = up.Profile
}
} else {
return nil, err
}
return um, nil
}
func newUserMap(ratingDb RatingStorage) *UserMap {
return &UserMap{
table: make(map[string]map[string]string),
index: make(map[string][]string),
index: make(map[string]map[string]bool),
ratingDb: ratingDb,
}
}
func (um *UserMap) SetUser(up UserProfile, reply *string) error {
um.table[up.GetId()] = up.Profile
if err := um.ratingDb.SetUser(&up); err != nil {
*reply = err.Error()
return err
}
um.table[up.GetId()] = up.Profile
um.addIndex(&up)
*reply = utils.OK
return nil
}
func (um *UserMap) RemoveUser(up UserProfile, reply *string) error {
delete(um.table, up.GetId())
if err := um.ratingDb.RemoveUser(up.GetId()); err != nil {
*reply = err.Error()
return err
}
delete(um.table, up.GetId())
um.deleteIndex(&up)
*reply = utils.OK
return nil
}
@@ -76,20 +93,32 @@ func (um *UserMap) UpdateUser(up UserProfile, reply *string) error {
return utils.ErrNotFound
}
if m == nil {
um.table[up.GetId()] = make(map[string]string, 0)
m = make(map[string]string)
}
oldM := make(map[string]string, len(m))
for k, v := range m {
oldM[k] = v
}
oldUp := &UserProfile{
Tenant: up.Tenant,
UserName: up.UserName,
Profile: oldM,
}
for key, value := range up.Profile {
um.table[up.GetId()][key] = value
m[key] = value
}
finalUp := &UserProfile{
Tenant: up.Tenant,
UserName: up.UserName,
Profile: um.table[up.GetId()],
Profile: m,
}
if err := um.ratingDb.SetUser(finalUp); err != nil {
*reply = err.Error()
return err
}
um.table[up.GetId()] = m
um.deleteIndex(oldUp)
um.addIndex(finalUp)
*reply = utils.OK
return nil
}
@@ -101,21 +130,21 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error {
// search index
if up.Tenant != "" {
if keys, found := um.index[utils.ConcatenatedKey("Tenant", up.Tenant)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
}
if up.UserName != "" {
if keys, found := um.index[utils.ConcatenatedKey("UserName", up.UserName)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
}
for k, v := range up.Profile {
if keys, found := um.index[utils.ConcatenatedKey(k, v)]; found {
for _, key := range keys {
for key := range keys {
indexUnionKeys[key] = true
}
}
@@ -158,31 +187,98 @@ func (um *UserMap) GetUsers(up UserProfile, results *[]*UserProfile) error {
}
func (um *UserMap) AddIndex(indexes []string, reply *string) error {
um.indexKeys = indexes
for key, values := range um.table {
ud := &UserProfile{Profile: values}
ud.SetId(key)
for _, index := range indexes {
if index == "Tenant" {
if ud.Tenant != "" {
um.index[utils.ConcatenatedKey(index, ud.Tenant)] = append(um.index[utils.ConcatenatedKey(index, ud.Tenant)], key)
}
continue
}
if index == "UserName" {
if ud.UserName != "" {
um.index[utils.ConcatenatedKey(index, ud.UserName)] = append(um.index[utils.ConcatenatedKey(index, ud.UserName)], key)
}
continue
}
up := &UserProfile{Profile: values}
up.SetId(key)
um.addIndex(up)
}
*reply = utils.OK
return nil
}
for k, v := range ud.Profile {
if k == index && v != "" {
um.index[utils.ConcatenatedKey(k, v)] = append(um.index[utils.ConcatenatedKey(k, v)], key)
func (um *UserMap) addIndex(up *UserProfile) {
key := up.GetId()
for _, index := range um.indexKeys {
if index == "Tenant" {
if up.Tenant != "" {
indexKey := utils.ConcatenatedKey(index, up.Tenant)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
continue
}
if index == "UserName" {
if up.UserName != "" {
indexKey := utils.ConcatenatedKey(index, up.UserName)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
continue
}
for k, v := range up.Profile {
if k == index && v != "" {
indexKey := utils.ConcatenatedKey(k, v)
if um.index[indexKey] == nil {
um.index[indexKey] = make(map[string]bool)
}
um.index[indexKey][key] = true
}
}
}
}
func (um *UserMap) deleteIndex(up *UserProfile) {
key := up.GetId()
for _, index := range um.indexKeys {
if index == "Tenant" {
if up.Tenant != "" {
indexKey := utils.ConcatenatedKey(index, up.Tenant)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
continue
}
if index == "UserName" {
if up.UserName != "" {
indexKey := utils.ConcatenatedKey(index, up.UserName)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
continue
}
for k, v := range up.Profile {
if k == index && v != "" {
indexKey := utils.ConcatenatedKey(k, v)
delete(um.index[indexKey], key)
if len(um.index[indexKey]) == 0 {
delete(um.index, indexKey)
}
}
}
}
*reply = utils.OK
}
func (um *UserMap) GetIndexes(in string, reply *map[string][]string) error {
indexes := make(map[string][]string)
for key, values := range um.index {
var vs []string
for val := range values {
vs = append(vs, val)
}
indexes[key] = vs
}
*reply = indexes
return nil
}
@@ -219,3 +315,7 @@ func (ps *ProxyUserService) GetUsers(ud UserProfile, users *[]*UserProfile) erro
func (ps *ProxyUserService) AddIndex(indexes []string, reply *string) error {
return ps.Client.Call("UsersV1.AddIndex", indexes, reply)
}
func (ps *ProxyUserService) GetIndexes(in string, reply *map[string][]string) error {
return ps.Client.Call("UsersV1.AddIndex", in, reply)
}

View File

@@ -13,11 +13,11 @@ var testMap = UserMap{
"test:": map[string]string{"t": "v"},
"test1:user1": map[string]string{"t": "v", "x": "y"},
},
index: make(map[string][]string),
index: make(map[string]map[string]bool),
}
func TestUsersAdd(t *testing.T) {
tm := NewUserMap(ratingStorage)
tm := newUserMap(ratingStorage)
var r string
up := UserProfile{
Tenant: "test",
@@ -33,12 +33,12 @@ func TestUsersAdd(t *testing.T) {
p["t"] != "v" ||
len(tm.table) != 1 ||
len(p) != 1 {
t.Error("Error setting user: ", tm)
t.Error("Error setting user: ", tm, len(tm.table))
}
}
func TestUsersUpdate(t *testing.T) {
tm := NewUserMap(ratingStorage)
tm := newUserMap(ratingStorage)
var r string
up := UserProfile{
Tenant: "test",
@@ -69,7 +69,7 @@ func TestUsersUpdate(t *testing.T) {
}
func TestUsersUpdateNotFound(t *testing.T) {
tm := NewUserMap(ratingStorage)
tm := newUserMap(ratingStorage)
var r string
up := UserProfile{
Tenant: "test",
@@ -80,14 +80,14 @@ func TestUsersUpdateNotFound(t *testing.T) {
}
tm.SetUser(up, &r)
up.UserName = "test1"
err := tm.UpdateUser(up, &r)
err = tm.UpdateUser(up, &r)
if err != utils.ErrNotFound {
t.Error("Error detecting user not found on update: ", err)
}
}
func TestUsersUpdateInit(t *testing.T) {
tm := NewUserMap(ratingStorage)
tm := newUserMap(ratingStorage)
var r string
up := UserProfile{
Tenant: "test",
@@ -113,7 +113,7 @@ func TestUsersUpdateInit(t *testing.T) {
}
func TestUsersRemove(t *testing.T) {
tm := NewUserMap(ratingStorage)
tm := newUserMap(ratingStorage)
var r string
up := UserProfile{
Tenant: "test",
@@ -267,7 +267,7 @@ func TestUsersAddIndex(t *testing.T) {
func TestUsersAddIndexFull(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
if r != utils.OK ||
len(testMap.index) != 6 ||
@@ -278,7 +278,7 @@ func TestUsersAddIndexFull(t *testing.T) {
func TestUsersAddIndexNone(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"test"}, &r)
if r != utils.OK ||
len(testMap.index) != 0 {
@@ -288,7 +288,7 @@ func TestUsersAddIndexNone(t *testing.T) {
func TestUsersGetFullindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -306,7 +306,7 @@ func TestUsersGetFullindex(t *testing.T) {
func TestUsersGetTenantindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "testX",
@@ -324,7 +324,7 @@ func TestUsersGetTenantindex(t *testing.T) {
func TestUsersGetUserNameindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -342,7 +342,7 @@ func TestUsersGetUserNameindex(t *testing.T) {
func TestUsersGetNotFoundProfileindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -360,7 +360,7 @@ func TestUsersGetNotFoundProfileindex(t *testing.T) {
func TestUsersGetMissingTenantindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
UserName: "user",
@@ -377,7 +377,7 @@ func TestUsersGetMissingTenantindex(t *testing.T) {
func TestUsersGetMissingUserNameindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Tenant: "test",
@@ -394,7 +394,7 @@ func TestUsersGetMissingUserNameindex(t *testing.T) {
func TestUsersGetMissingIdindex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Profile: map[string]string{
@@ -410,7 +410,7 @@ func TestUsersGetMissingIdindex(t *testing.T) {
func TestUsersGetMissingIdTwoINdex(t *testing.T) {
var r string
testMap.index = make(map[string][]string) // reset index
testMap.index = make(map[string]map[string]bool) // reset index
testMap.AddIndex([]string{"t", "x", "UserName", "Tenant"}, &r)
up := UserProfile{
Profile: map[string]string{

View File

@@ -32,6 +32,14 @@ func IsSliceMember(ss []string, s string) bool {
return false
}
func SliceWithoutMember(ss []string, s string) []string {
sort.Strings(ss)
if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s {
ss[i], ss = ss[len(ss)-1], ss[:len(ss)-1]
}
return ss
}
//Iterates over slice members and returns true if one starts with prefix
func SliceMemberHasPrefix(ss []string, prfx string) bool {
for _, mbr := range ss {