diff --git a/agents/diamagent.go b/agents/diamagent.go index dd87be829..fecfcead4 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -357,11 +357,12 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.ParamsSlice(utils.MetaStats, utils.MetaIDs), reqProcessor.Flags.GetBool(utils.MetaResources), reqProcessor.Flags.Has(utils.MetaAccounts), - reqProcessor.Flags.Has(utils.MetaRoutes), + reqProcessor.Flags.GetBool(utils.MetaRoutes), reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), ) rply := new(sessions.V1AuthorizeReply) err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1AuthorizeEvent, @@ -427,7 +428,9 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, - reqProcessor.Flags.Has(utils.MetaFD)) + reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1ProcessMessageReply) err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1ProcessMessage, msgArgs, rply) diff --git a/agents/dnsagent.go b/agents/dnsagent.go index ae8d445a6..6f7f39daf 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -226,6 +226,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), ) rply := new(sessions.V1AuthorizeReply) err = da.connMgr.Call(da.cgrCfg.DNSAgentCfg().SessionSConns, nil, @@ -294,7 +295,9 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.GetBool(utils.MetaRoutes), reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), - cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD)) + cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1ProcessMessageReply) // need it so rpcclient can clone err = da.connMgr.Call(da.cgrCfg.DNSAgentCfg().SessionSConns, nil, utils.SessionSv1ProcessMessage, diff --git a/agents/httpagent.go b/agents/httpagent.go index ddcf5dc34..2d70a8c6c 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -160,7 +160,9 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.GetBool(utils.MetaRoutes), reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), - cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD)) + cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1AuthorizeReply) err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1AuthorizeEvent, authArgs, rply) @@ -224,7 +226,9 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.GetBool(utils.MetaRoutes), reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), - cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD)) + cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1ProcessMessageReply) err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1ProcessMessage, evArgs, rply) diff --git a/agents/radagent.go b/agents/radagent.go index ff2897b78..e5b06b9e4 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -219,6 +219,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), ) rply := new(sessions.V1AuthorizeReply) err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1AuthorizeEvent, @@ -283,7 +284,9 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R reqProcessor.Flags.GetBool(utils.MetaRoutes), reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), - cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD)) + cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1ProcessMessageReply) err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1ProcessMessage, evArgs, rply) if utils.ErrHasPrefix(err, utils.RalsErrorPrfx) { diff --git a/agents/sipagent.go b/agents/sipagent.go index 7e3aa2f66..40978ca0c 100644 --- a/agents/sipagent.go +++ b/agents/sipagent.go @@ -426,6 +426,7 @@ func (sa *SIPAgent) processRequest(reqProcessor *config.RequestProcessor, reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), reqProcessor.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, reqProcessor.Flags.Has(utils.MetaFD), + reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), ) rply := new(sessions.V1AuthorizeReply) err = sa.connMgr.Call(sa.cfg.SIPAgentCfg().SessionSConns, nil, utils.SessionSv1AuthorizeEvent, @@ -494,6 +495,7 @@ func (sa *SIPAgent) processRequest(reqProcessor *config.RequestProcessor, // reqProcessor.Flags.Has(utils.MetaRoutesIgnoreErrors), // reqProcessor.Flags.Has(utils.MetaRoutesEventCost), // cgrEv, cgrArgs, // reqProcessor.Flags.Has(utils.MetaFD), + // reqProcessor.Flags.ParamValue(utils.MetaRoutesMaxCost), // opts) // rply := new(sessions.V1ProcessMessageReply) // err = sa.connMgr.Call(sa.cfg.SIPAgentCfg().SessionSConns, nil, utils.SessionSv1ProcessMessage, diff --git a/engine/datadbmock.go b/engine/datadbmock.go index 3a96341ff..8e2211321 100644 --- a/engine/datadbmock.go +++ b/engine/datadbmock.go @@ -19,8 +19,6 @@ along with this program. If not, see package engine import ( - "fmt" - "github.com/cgrates/cgrates/utils" ) @@ -277,7 +275,6 @@ func (dbM *DataDBMock) RemStatQueueDrv(tenant, id string) (err error) { } func (dbM *DataDBMock) GetThresholdProfileDrv(tenant string, ID string) (tp *ThresholdProfile, err error) { - fmt.Println(4) return nil, utils.ErrNotImplemented } diff --git a/engine/libroutes.go b/engine/libroutes.go index 65e7dd711..40f0eef49 100644 --- a/engine/libroutes.go +++ b/engine/libroutes.go @@ -74,50 +74,50 @@ func (sRoutes *SortedRoutes) SortWeight() { // SortLeastCost is part of sort interface, // sort ascendent based on Cost with fallback on Weight -func (sSpls *SortedRoutes) SortLeastCost() { - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { - if sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) { - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { +func (sRoutes *SortedRoutes) SortLeastCost() { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { + if sRoutes.SortedRoutes[i].SortingData[utils.Cost].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Cost].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) } - return sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) < sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Cost].(float64) < sRoutes.SortedRoutes[j].SortingData[utils.Cost].(float64) }) } // SortHighestCost is part of sort interface, // sort descendent based on Cost with fallback on Weight -func (sSpls *SortedRoutes) SortHighestCost() { - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { - if sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) { - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { +func (sRoutes *SortedRoutes) SortHighestCost() { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { + if sRoutes.SortedRoutes[i].SortingData[utils.Cost].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Cost].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) } - return sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Cost].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Cost].(float64) }) } // SortQOS is part of sort interface, // sort based on Stats -func (sSpls *SortedRoutes) SortQOS(params []string) { +func (sRoutes *SortedRoutes) SortQOS(params []string) { //sort routes - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { for _, param := range params { //in case we have the same value for the current param we skip to the next one - if sSpls.SortedRoutes[i].SortingData[param].(float64) == sSpls.SortedRoutes[j].SortingData[param].(float64) { + if sRoutes.SortedRoutes[i].SortingData[param].(float64) == sRoutes.SortedRoutes[j].SortingData[param].(float64) { continue } switch param { default: - if sSpls.SortedRoutes[i].SortingData[param].(float64) > sSpls.SortedRoutes[j].SortingData[param].(float64) { + if sRoutes.SortedRoutes[i].SortingData[param].(float64) > sRoutes.SortedRoutes[j].SortingData[param].(float64) { return true } return false case utils.MetaPDD: //in case of pdd the smallest value if the best - if sSpls.SortedRoutes[i].SortingData[param].(float64) < sSpls.SortedRoutes[j].SortingData[param].(float64) { + if sRoutes.SortedRoutes[i].SortingData[param].(float64) < sRoutes.SortedRoutes[j].SortingData[param].(float64) { return true } return false @@ -125,52 +125,52 @@ func (sSpls *SortedRoutes) SortQOS(params []string) { } //in case that we have the same value for all params we sort base on weight - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) }) } // SortResourceAscendent is part of sort interface, // sort ascendent based on ResourceUsage with fallback on Weight -func (sSpls *SortedRoutes) SortResourceAscendent() { - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { - if sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) { - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { +func (sRoutes *SortedRoutes) SortResourceAscendent() { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { + if sRoutes.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) } - return sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) < sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) < sRoutes.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) }) } // SortResourceDescendent is part of sort interface, // sort descendent based on ResourceUsage with fallback on Weight -func (sSpls *SortedRoutes) SortResourceDescendent() { - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { - if sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) { - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { +func (sRoutes *SortedRoutes) SortResourceDescendent() { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { + if sRoutes.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) } - return sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) > sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) }) } // SortLoadDistribution is part of sort interface, // sort based on the following formula (float64(ratio + metricVal) / float64(ratio)) -1 with fallback on Weight -func (sSpls *SortedRoutes) SortLoadDistribution() { - sort.Slice(sSpls.SortedRoutes, func(i, j int) bool { - splIVal := ((sSpls.SortedRoutes[i].SortingData[utils.Ratio].(float64)+sSpls.SortedRoutes[i].SortingData[utils.Load].(float64))/sSpls.SortedRoutes[i].SortingData[utils.Ratio].(float64) - 1.0) - splJVal := ((sSpls.SortedRoutes[j].SortingData[utils.Ratio].(float64)+sSpls.SortedRoutes[j].SortingData[utils.Load].(float64))/sSpls.SortedRoutes[j].SortingData[utils.Ratio].(float64) - 1.0) +func (sRoutes *SortedRoutes) SortLoadDistribution() { + sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool { + splIVal := ((sRoutes.SortedRoutes[i].SortingData[utils.Ratio].(float64)+sRoutes.SortedRoutes[i].SortingData[utils.Load].(float64))/sRoutes.SortedRoutes[i].SortingData[utils.Ratio].(float64) - 1.0) + splJVal := ((sRoutes.SortedRoutes[j].SortingData[utils.Ratio].(float64)+sRoutes.SortedRoutes[j].SortingData[utils.Load].(float64))/sRoutes.SortedRoutes[j].SortingData[utils.Ratio].(float64) - 1.0) if splIVal == splJVal { - if sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) { + if sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) == sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) { return utils.BoolGenerator().RandomBool() } - return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64) + return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64) } return splIVal < splJVal }) @@ -178,8 +178,8 @@ func (sSpls *SortedRoutes) SortLoadDistribution() { // Digest returns list of routeIDs + parameters for easier outside access // format route1:route1params,route2:route2params -func (sSpls *SortedRoutes) Digest() string { - return strings.Join(sSpls.RoutesWithParams(), utils.FieldsSep) +func (sRoutes *SortedRoutes) Digest() string { + return strings.Join(sRoutes.RoutesWithParams(), utils.FieldsSep) } func (ss *SortedRoute) AsNavigableMap() (nm utils.NavigableMap2) { @@ -194,14 +194,15 @@ func (ss *SortedRoute) AsNavigableMap() (nm utils.NavigableMap2) { nm[utils.SortingData] = sd return } -func (sSpls *SortedRoutes) AsNavigableMap() (nm utils.NavigableMap2) { + +func (sRoutes *SortedRoutes) AsNavigableMap() (nm utils.NavigableMap2) { nm = utils.NavigableMap2{ - utils.ProfileID: utils.NewNMData(sSpls.ProfileID), - utils.Sorting: utils.NewNMData(sSpls.Sorting), - utils.Count: utils.NewNMData(sSpls.Count), + utils.ProfileID: utils.NewNMData(sRoutes.ProfileID), + utils.Sorting: utils.NewNMData(sRoutes.Sorting), + utils.Count: utils.NewNMData(sRoutes.Count), } - sr := make(utils.NMSlice, len(sSpls.SortedRoutes)) - for i, ss := range sSpls.SortedRoutes { + sr := make(utils.NMSlice, len(sRoutes.SortedRoutes)) + for i, ss := range sRoutes.SortedRoutes { sr[i] = ss.AsNavigableMap() } nm[utils.SortedRoutes] = &sr diff --git a/ers/ers.go b/ers/ers.go index 068337bfe..bc7a9674c 100644 --- a/ers/ers.go +++ b/ers/ers.go @@ -203,6 +203,7 @@ func (erS *ERService) processEvent(cgrEv *utils.CGREvent, rdrCfg.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, rdrCfg.Flags.Has(utils.MetaFD), + rdrCfg.Flags.ParamValue(utils.MetaRoutesMaxCost), ) rply := new(sessions.V1AuthorizeReply) err = erS.connMgr.Call(erS.cfg.ERsCfg().SessionSConns, nil, utils.SessionSv1AuthorizeEvent, @@ -256,7 +257,9 @@ func (erS *ERService) processEvent(cgrEv *utils.CGREvent, rdrCfg.Flags.Has(utils.MetaRoutesIgnoreErrors), rdrCfg.Flags.Has(utils.MetaRoutesEventCost), cgrEv, cgrArgs, - rdrCfg.Flags.Has(utils.MetaFD)) + rdrCfg.Flags.Has(utils.MetaFD), + rdrCfg.Flags.ParamValue(utils.MetaRoutesMaxCost), + ) rply := new(sessions.V1ProcessMessageReply) // need it so rpcclient can clone err = erS.connMgr.Call(erS.cfg.ERsCfg().SessionSConns, nil, utils.SessionSv1ProcessMessage, evArgs, rply) diff --git a/packages/debian/changelog b/packages/debian/changelog index 2455fb638..c810602cb 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -141,6 +141,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [SessionS] Cloned the charging interval added on EventCost merge * [FilterS] Optimized the automated index fields matching * [AgentS] Added *cfg as DataProvider for AgentRequest + * [AgentS] Added *routes_maxcost flag -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/sessions/sessions.go b/sessions/sessions.go index 1abf1ad4c..d7c5e7bac 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -1758,7 +1758,7 @@ func NewV1AuthorizeArgs(attrs bool, attributeIDs []string, thrslds bool, thresholdIDs []string, statQueues bool, statIDs []string, res, maxUsage, routes, routesIgnoreErrs, routesEventCost bool, cgrEv *utils.CGREvent, routePaginator utils.Paginator, - forceDuration bool) (args *V1AuthorizeArgs) { + forceDuration bool, routesMaxCost string) (args *V1AuthorizeArgs) { args = &V1AuthorizeArgs{ GetAttributes: attrs, AuthorizeResources: res, @@ -1772,6 +1772,8 @@ func NewV1AuthorizeArgs(attrs bool, attributeIDs []string, } if routesEventCost { args.RoutesMaxCost = utils.MetaRoutesEventCost + } else { + args.RoutesMaxCost = routesMaxCost } args.Paginator = routePaginator if len(attributeIDs) != 0 { @@ -1819,6 +1821,8 @@ func (args *V1AuthorizeArgs) ParseFlags(flags string) { args.RoutesIgnoreErrors = true case subsystem == utils.MetaRoutesEventCost: args.RoutesMaxCost = utils.MetaEventCost + case strings.HasPrefix(subsystem, utils.MetaRoutesMaxCost): + args.RoutesMaxCost = strings.TrimPrefix(subsystem, utils.MetaRoutesMaxCost+utils.InInFieldSep) case strings.HasPrefix(subsystem, utils.MetaAttributes): args.GetAttributes = true args.AttributeIDs = getFlagIDs(subsystem) @@ -2683,7 +2687,7 @@ func (sS *SessionS) BiRPCv1ProcessCDR(clnt rpcclient.ClientConnector, func NewV1ProcessMessageArgs(attrs bool, attributeIDs []string, thds bool, thresholdIDs []string, stats bool, statIDs []string, resrc, acnts, routes, routesIgnoreErrs, routesEventCost bool, cgrEv *utils.CGREvent, - routePaginator utils.Paginator, forceDuration bool) (args *V1ProcessMessageArgs) { + routePaginator utils.Paginator, forceDuration bool, routesMaxCost string) (args *V1ProcessMessageArgs) { args = &V1ProcessMessageArgs{ AllocateResources: resrc, Debit: acnts, @@ -2697,6 +2701,8 @@ func NewV1ProcessMessageArgs(attrs bool, attributeIDs []string, } if routesEventCost { args.RoutesMaxCost = utils.MetaRoutesEventCost + } else { + args.RoutesMaxCost = routesMaxCost } args.Paginator = routePaginator if len(attributeIDs) != 0 { @@ -2743,6 +2749,8 @@ func (args *V1ProcessMessageArgs) ParseFlags(flags string) { args.RoutesIgnoreErrors = true case subsystem == utils.MetaRoutesEventCost: args.RoutesMaxCost = utils.MetaEventCost + case strings.HasPrefix(subsystem, utils.MetaRoutesMaxCost): + args.RoutesMaxCost = strings.TrimPrefix(subsystem, utils.MetaRoutesMaxCost+utils.InInFieldSep) case strings.Index(subsystem, utils.MetaAttributes) != -1: args.GetAttributes = true args.AttributeIDs = getFlagIDs(subsystem) @@ -3093,6 +3101,8 @@ func (sS *SessionS) BiRPCv1ProcessEvent(clnt rpcclient.ClientConnector, var maxCost string if flags.Has(utils.MetaEventCost) { maxCost = utils.MetaRoutesEventCost + } else { + maxCost = flags.ParamValue(utils.MetaRoutesMaxCost) } for runID, cgrEv := range getDerivedEvents(events, flags.Has(utils.MetaDerivedReply)) { routesReply, err := sS.getRoutes(cgrEv.Clone(), args.Paginator, ignoreErrors, maxCost, false) diff --git a/sessions/sessions_test.go b/sessions/sessions_test.go index 489569877..c8e44c992 100644 --- a/sessions/sessions_test.go +++ b/sessions/sessions_test.go @@ -906,7 +906,7 @@ func TestSessionSNewV1AuthorizeArgs(t *testing.T) { CGREvent: cgrEv, ForceDuration: true, } - rply := NewV1AuthorizeArgs(true, nil, false, nil, false, nil, true, false, false, false, false, cgrEv, utils.Paginator{}, true) + rply := NewV1AuthorizeArgs(true, nil, false, nil, false, nil, true, false, false, false, false, cgrEv, utils.Paginator{}, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", expected, rply) } @@ -922,7 +922,7 @@ func TestSessionSNewV1AuthorizeArgs(t *testing.T) { CGREvent: cgrEv, ForceDuration: true, } - rply = NewV1AuthorizeArgs(true, nil, false, nil, true, nil, false, true, false, true, true, cgrEv, utils.Paginator{}, true) + rply = NewV1AuthorizeArgs(true, nil, false, nil, true, nil, false, true, false, true, true, cgrEv, utils.Paginator{}, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v,\n received: %+v", expected, rply) } @@ -945,7 +945,26 @@ func TestSessionSNewV1AuthorizeArgs(t *testing.T) { StatIDs: []string{"test3", "test4"}, } rply = NewV1AuthorizeArgs(true, attributeIDs, false, thresholdIDs, - true, statIDs, false, true, false, true, true, cgrEv, utils.Paginator{}, false) + true, statIDs, false, true, false, true, true, cgrEv, utils.Paginator{}, false, "") + if !reflect.DeepEqual(expected, rply) { + t.Errorf("Expecting %+v,\n received: %+v", expected, rply) + } + expected = &V1AuthorizeArgs{ + GetAttributes: true, + AuthorizeResources: false, + GetMaxUsage: true, + ProcessThresholds: false, + ProcessStats: true, + GetRoutes: false, + RoutesIgnoreErrors: true, + RoutesMaxCost: "100", + CGREvent: cgrEv, + AttributeIDs: []string{"ATTR1", "ATTR2"}, + ThresholdIDs: []string{"ID1", "ID2"}, + StatIDs: []string{"test3", "test4"}, + } + rply = NewV1AuthorizeArgs(true, attributeIDs, false, thresholdIDs, + true, statIDs, false, true, false, true, false, cgrEv, utils.Paginator{}, false, "100") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v,\n received: %+v", expected, rply) } @@ -982,6 +1001,8 @@ func TestV1AuthorizeArgsParseFlags(t *testing.T) { } strArg = "*accounts,*fd,*resources,*routes,*routes_ignore_errors,*routes_event_cost,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1authArgs = new(V1AuthorizeArgs) + v1authArgs.CGREvent = new(utils.CGREvent) v1authArgs.ParseFlags(strArg) if !reflect.DeepEqual(eOut, v1authArgs) { t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1authArgs)) @@ -1006,6 +1027,32 @@ func TestV1AuthorizeArgsParseFlags(t *testing.T) { } strArg = "*accounts,*fd,*resources,,*dispatchers,*routes,*routes_ignore_errors,*routes_event_cost,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1authArgs = new(V1AuthorizeArgs) + v1authArgs.CGREvent = new(utils.CGREvent) + v1authArgs.ParseFlags(strArg) + if !reflect.DeepEqual(eOut, v1authArgs) { + t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1authArgs)) + } + eOut = &V1AuthorizeArgs{ + GetMaxUsage: true, + AuthorizeResources: true, + GetRoutes: true, + RoutesIgnoreErrors: true, + RoutesMaxCost: "100", + GetAttributes: true, + AttributeIDs: []string{"Attr1", "Attr2"}, + ProcessThresholds: true, + ThresholdIDs: []string{"tr1", "tr2", "tr3"}, + ProcessStats: true, + StatIDs: []string{"st1", "st2", "st3"}, + Paginator: cgrArgs, + CGREvent: eOut.CGREvent, + ForceDuration: true, + } + + strArg = "*accounts,*fd,*resources,,*dispatchers,*routes,*routes_ignore_errors,*routes_maxcost:100,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1authArgs = new(V1AuthorizeArgs) + v1authArgs.CGREvent = new(utils.CGREvent) v1authArgs.ParseFlags(strArg) if !reflect.DeepEqual(eOut, v1authArgs) { t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1authArgs)) @@ -1111,7 +1158,7 @@ func TestSessionSNewV1ProcessMessageArgs(t *testing.T) { ForceDuration: true, } rply := NewV1ProcessMessageArgs(true, nil, false, nil, false, - nil, true, true, true, false, false, cgrEv, utils.Paginator{}, true) + nil, true, true, true, false, false, cgrEv, utils.Paginator{}, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", expected, rply) } @@ -1125,7 +1172,7 @@ func TestSessionSNewV1ProcessMessageArgs(t *testing.T) { ForceDuration: true, } rply = NewV1ProcessMessageArgs(true, nil, false, nil, false, - nil, true, false, true, true, true, cgrEv, utils.Paginator{}, true) + nil, true, false, true, true, true, cgrEv, utils.Paginator{}, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", expected, rply) } @@ -1147,11 +1194,24 @@ func TestSessionSNewV1ProcessMessageArgs(t *testing.T) { ForceDuration: true, } rply = NewV1ProcessMessageArgs(true, attributeIDs, false, thresholdIDs, false, statIDs, - true, false, true, true, true, cgrEv, utils.Paginator{}, true) + true, false, true, true, true, cgrEv, utils.Paginator{}, true, "") + if !reflect.DeepEqual(expected, rply) { + t.Errorf("Expecting %+v, received: %+v", expected, rply) + } + expected = &V1ProcessMessageArgs{ + AllocateResources: true, + GetAttributes: true, + CGREvent: cgrEv, + GetRoutes: true, + RoutesMaxCost: "100", + RoutesIgnoreErrors: true, + ForceDuration: true, + } + rply = NewV1ProcessMessageArgs(true, nil, false, nil, false, + nil, true, false, true, true, false, cgrEv, utils.Paginator{}, true, "100") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", expected, rply) } - } func TestSessionSNewV1InitSessionArgs(t *testing.T) { @@ -1552,7 +1612,7 @@ func TestSessionSNewV1AuthorizeArgsWithOpts(t *testing.T) { } cgrArgs, _ := utils.GetRoutePaginatorFromOpts(cgrEv.Opts) rply := NewV1AuthorizeArgs(true, nil, false, nil, false, nil, true, false, - false, false, false, cgrEv, cgrArgs, true) + false, false, false, cgrEv, cgrArgs, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rply)) } @@ -1569,7 +1629,7 @@ func TestSessionSNewV1AuthorizeArgsWithOpts(t *testing.T) { ForceDuration: true, } rply = NewV1AuthorizeArgs(true, nil, false, nil, true, nil, false, true, - false, true, true, cgrEv, cgrArgs, true) + false, true, true, cgrEv, cgrArgs, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rply)) } @@ -1596,7 +1656,7 @@ func TestSessionSNewV1AuthorizeArgsWithOpts2(t *testing.T) { } cgrArgs, _ := utils.GetRoutePaginatorFromOpts(cgrEv.Opts) rply := NewV1AuthorizeArgs(true, nil, false, nil, false, nil, true, false, false, - false, false, cgrEv, cgrArgs, true) + false, false, cgrEv, cgrArgs, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rply)) } @@ -1613,7 +1673,7 @@ func TestSessionSNewV1AuthorizeArgsWithOpts2(t *testing.T) { ForceDuration: true, } rply = NewV1AuthorizeArgs(true, nil, false, nil, true, nil, false, true, false, - true, true, cgrEv, cgrArgs, true) + true, true, cgrEv, cgrArgs, true, "") if !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rply)) } @@ -1922,6 +1982,8 @@ func TestV1ProcessMessageArgsParseFlags(t *testing.T) { } strArg = "*accounts,*resources,*routes,*routes_ignore_errors,*routes_event_cost,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1ProcessMsgArgs = new(V1ProcessMessageArgs) + v1ProcessMsgArgs.CGREvent = new(utils.CGREvent) v1ProcessMsgArgs.ParseFlags(strArg) if !reflect.DeepEqual(eOut, v1ProcessMsgArgs) { t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1ProcessMsgArgs)) @@ -1944,6 +2006,31 @@ func TestV1ProcessMessageArgsParseFlags(t *testing.T) { } strArg = "*accounts,*resources,*dispatchers,*routes,*routes_ignore_errors,*routes_event_cost,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1ProcessMsgArgs = new(V1ProcessMessageArgs) + v1ProcessMsgArgs.CGREvent = new(utils.CGREvent) + v1ProcessMsgArgs.ParseFlags(strArg) + if !reflect.DeepEqual(eOut, v1ProcessMsgArgs) { + t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1ProcessMsgArgs)) + } + + eOut = &V1ProcessMessageArgs{ + Debit: true, + AllocateResources: true, + GetRoutes: true, + RoutesIgnoreErrors: true, + RoutesMaxCost: "100", + GetAttributes: true, + AttributeIDs: []string{"Attr1", "Attr2"}, + ProcessThresholds: true, + ThresholdIDs: []string{"tr1", "tr2", "tr3"}, + ProcessStats: true, + StatIDs: []string{"st1", "st2", "st3"}, + CGREvent: eOut.CGREvent, + } + + strArg = "*accounts,*resources,*dispatchers,*routes,*routes_ignore_errors,*routes_maxcost:100,*attributes:Attr1;Attr2,*thresholds:tr1;tr2;tr3,*stats:st1;st2;st3" + v1ProcessMsgArgs = new(V1ProcessMessageArgs) + v1ProcessMsgArgs.CGREvent = new(utils.CGREvent) v1ProcessMsgArgs.ParseFlags(strArg) if !reflect.DeepEqual(eOut, v1ProcessMsgArgs) { t.Errorf("Expecting %+v,\n received: %+v\n", utils.ToJSON(eOut), utils.ToJSON(v1ProcessMsgArgs)) diff --git a/utils/consts.go b/utils/consts.go index 860444ede..2cd51b864 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -735,6 +735,7 @@ const ( MetaPositiveExports = "*positive_exports" MetaNegativeExports = "*negative_exports" MetaRoutesEventCost = "*routes_event_cost" + MetaRoutesMaxCost = "*routes_maxcost" MetaRoutesIgnoreErrors = "*routes_ignore_errors" Freeswitch = "freeswitch" Kamailio = "kamailio" diff --git a/utils/map.go b/utils/map.go index e8601e7fa..439ec67ab 100644 --- a/utils/map.go +++ b/utils/map.go @@ -167,6 +167,16 @@ func (fWp FlagParams) Has(opt string) (has bool) { return } +// ParamValue returns the value of the flag +func (fWp FlagParams) ParamValue(opt string) (ps string) { + for _, ps = range fWp[opt] { + if ps != EmptyString { + return + } + } + return +} + // Add adds the options to the flag func (fWp FlagParams) Add(opts []string) { switch len(opts) { @@ -234,6 +244,14 @@ func (fWp FlagsWithParams) ParamsSlice(subs, opt string) (ps []string) { return } +// ParamValue returns the value of the flag +func (fWp FlagsWithParams) ParamValue(subs string) (ps string) { + for ps = range fWp[subs] { + return + } + return +} + // SliceFlags converts from FlagsWithParams back to []string func (fWp FlagsWithParams) SliceFlags() (sls []string) { for key, sub := range fWp { diff --git a/utils/map_test.go b/utils/map_test.go index c53faacf4..3331f4d6c 100644 --- a/utils/map_test.go +++ b/utils/map_test.go @@ -207,6 +207,44 @@ func TestFlagsWithParamsGetBool(t *testing.T) { } } +func TestFlagsWithParamsValue(t *testing.T) { + flagsWithParams := &FlagsWithParams{ + "test": map[string][]string{"string2": {}}, + "empty": map[string][]string{}, + } + key := "notpresent" + if rcv := flagsWithParams.ParamValue(key); rcv != EmptyString { + t.Errorf("Expecting: %q, received: %+v", EmptyString, rcv) + } + key = "empty" + if rcv := flagsWithParams.ParamValue(key); rcv != EmptyString { + t.Errorf("Expecting: %q, received: %+v", EmptyString, rcv) + } + key = "test" + if rcv := flagsWithParams.ParamValue(key); rcv != "string2" { + t.Errorf("Expecting: string2, received: %+v", rcv) + } +} + +func TestFlagParamsValue(t *testing.T) { + flagsWithParams := &FlagParams{ + "test": []string{"string2"}, + "empty": []string{}, + } + key := "notpresent" + if rcv := flagsWithParams.ParamValue(key); rcv != EmptyString { + t.Errorf("Expecting: %q, received: %+v", EmptyString, rcv) + } + key = "empty" + if rcv := flagsWithParams.ParamValue(key); rcv != EmptyString { + t.Errorf("Expecting: %q, received: %+v", EmptyString, rcv) + } + key = "test" + if rcv := flagsWithParams.ParamValue(key); rcv != "string2" { + t.Errorf("Expecting: string2, received: %+v", rcv) + } +} + func TestFlagParamsAdd(t *testing.T) { flgs := make(FlagParams) exp := FlagParams{