mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Add *reas/*reds strategy for SupplierS (+tests)
This commit is contained in:
committed by
Dan Christian Bogos
parent
1cb3e3984a
commit
7ae16a20d5
@@ -853,6 +853,21 @@ func startSupplierService(internalSupplierSChan chan rpcclient.RpcClientConnecti
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(cfg.SupplierSCfg().ResourceSConns) != 0 {
|
||||
resourceSConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST,
|
||||
cfg.TlsCfg().ClientKey,
|
||||
cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate,
|
||||
cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects,
|
||||
cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout,
|
||||
cfg.SupplierSCfg().ResourceSConns, internalRsChan,
|
||||
cfg.GeneralCfg().InternalTtl, false)
|
||||
if err != nil {
|
||||
utils.Logger.Crit(fmt.Sprintf("<%s> Could not connect to StatS: %s",
|
||||
utils.SupplierS, err.Error()))
|
||||
exitChan <- true
|
||||
return
|
||||
}
|
||||
}
|
||||
<-cacheS.GetPrecacheChannel(utils.CacheSupplierProfiles)
|
||||
|
||||
splS, err := engine.NewSupplierService(dm, cfg.GeneralCfg().DefaultTimezone,
|
||||
|
||||
@@ -133,7 +133,10 @@
|
||||
"suppliers": {
|
||||
"enabled": true,
|
||||
"stats_conns": [
|
||||
{"address": "*internal"},
|
||||
{"address": "127.0.0.1:2012", "transport":"*json"},
|
||||
],
|
||||
"resources_conns": [
|
||||
{"address": "127.0.0.1:2012", "transport":"*json"},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -256,10 +256,13 @@
|
||||
|
||||
"suppliers": {
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields":["Destination",],
|
||||
"prefix_indexed_fields":["Destination"],
|
||||
"stats_conns": [
|
||||
{"address": "*internal"},
|
||||
],
|
||||
"resources_conns": [
|
||||
{"address": "127.0.0.1:2012", "transport":"*json"},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -129,6 +129,28 @@ func (sSpls *SortedSuppliers) SortQOS(params []string) {
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceAscendent is part of sort interface,
|
||||
// sort ascendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedSuppliers) SortResourceAscendent() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
if sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) < sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceDescendent is part of sort interface,
|
||||
// sort descendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedSuppliers) SortResourceDescendent() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
if sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// Digest returns list of supplierIDs + parameters for easier outside access
|
||||
// format suppl1:suppl1params,suppl2:suppl2params
|
||||
func (sSpls *SortedSuppliers) Digest() string {
|
||||
@@ -152,6 +174,8 @@ func NewSupplierSortDispatcher(lcrS *SupplierService) (ssd SupplierSortDispatche
|
||||
ssd[utils.MetaLeastCost] = NewLeastCostSorter(lcrS)
|
||||
ssd[utils.MetaHighestCost] = NewHighestCostSorter(lcrS)
|
||||
ssd[utils.MetaQOS] = NewQOSSupplierSorter(lcrS)
|
||||
ssd[utils.MetaReas] = NewResourceAscendetSorter(lcrS)
|
||||
ssd[utils.MetaReds] = NewResourceDescendentSorter(lcrS)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
58
engine/spls_reas.go
Normal file
58
engine/spls_reas.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewResourceAscendetSorter(spS *SupplierService) *ResourceAscendentSorter {
|
||||
return &ResourceAscendentSorter{spS: spS,
|
||||
sorting: utils.MetaReas}
|
||||
}
|
||||
|
||||
// ResourceAscendentSorter orders suppliers based on their Resource Usage
|
||||
type ResourceAscendentSorter struct {
|
||||
sorting string
|
||||
spS *SupplierService
|
||||
}
|
||||
|
||||
func (ws *ResourceAscendentSorter) SortSuppliers(prflID string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: ws.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
if len(s.ResourceIDs) == 0 {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> supplier: <%s> - empty ResourceIDs",
|
||||
utils.SupplierS, s.ID))
|
||||
return nil, utils.NewErrMandatoryIeMissing("ResourceIDs")
|
||||
}
|
||||
if srtSpl, pass, err := ws.spS.populateSortingData(suplEv, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
}
|
||||
sortedSuppls.SortResourceAscendent()
|
||||
return
|
||||
}
|
||||
58
engine/spls_reds.go
Normal file
58
engine/spls_reds.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewResourceDescendentSorter(spS *SupplierService) *ResourceDescendentSorter {
|
||||
return &ResourceDescendentSorter{spS: spS,
|
||||
sorting: utils.MetaReds}
|
||||
}
|
||||
|
||||
// ResourceAscendentSorter orders suppliers based on their Resource Usage
|
||||
type ResourceDescendentSorter struct {
|
||||
sorting string
|
||||
spS *SupplierService
|
||||
}
|
||||
|
||||
func (ws *ResourceDescendentSorter) SortSuppliers(prflID string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: ws.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
if len(s.ResourceIDs) == 0 {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> supplier: <%s> - empty ResourceIDs",
|
||||
utils.SupplierS, s.ID))
|
||||
return nil, utils.NewErrMandatoryIeMissing("ResourceIDs")
|
||||
}
|
||||
if srtSpl, pass, err := ws.spS.populateSortingData(suplEv, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
}
|
||||
sortedSuppls.SortResourceDescendent()
|
||||
return
|
||||
}
|
||||
@@ -258,7 +258,7 @@ func (spS *SupplierService) statMetrics(statIDs []string, tenant string) (stsMet
|
||||
if spS.statS != nil {
|
||||
for _, statID := range statIDs {
|
||||
var metrics map[string]float64
|
||||
if err := spS.statS.Call(utils.StatSv1GetQueueFloatMetrics,
|
||||
if err = spS.statS.Call(utils.StatSv1GetQueueFloatMetrics,
|
||||
&utils.TenantID{Tenant: tenant, ID: statID}, &metrics); err != nil &&
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
utils.Logger.Warning(
|
||||
@@ -273,7 +273,19 @@ func (spS *SupplierService) statMetrics(statIDs []string, tenant string) (stsMet
|
||||
}
|
||||
|
||||
// resourceUsage returns sum of all resource usages out of list
|
||||
func (spS *SupplierService) resourceUsage(resIDs []string) (tUsage float64, err error) {
|
||||
func (spS *SupplierService) resourceUsage(resIDs []string, tenant string) (tUsage float64, err error) {
|
||||
if spS.resourceS != nil {
|
||||
for _, resID := range resIDs {
|
||||
var res *Resource
|
||||
if err = spS.resourceS.Call(utils.ApierV1GetResource,
|
||||
&utils.TenantID{Tenant: tenant, ID: resID}, &res); err != nil &&
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<SupplierS> error: %s getting resource for ID : %s", err.Error(), resID))
|
||||
}
|
||||
tUsage += res.totalUsage()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -343,6 +355,21 @@ func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplie
|
||||
}
|
||||
}
|
||||
}
|
||||
//calculate resourceUsage
|
||||
if len(spl.ResourceIDs) != 0 {
|
||||
resTotalUsage, err := spS.resourceUsage(spl.ResourceIDs, ev.Tenant)
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, spl.ID, err.Error()))
|
||||
return nil, false, nil
|
||||
} else {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
sortedSpl.SortingData[utils.ResourceUsage] = resTotalUsage
|
||||
}
|
||||
//filter the supplier
|
||||
if len(spl.FilterIDs) != 0 {
|
||||
//construct the DP and pass it to filterS
|
||||
|
||||
@@ -49,6 +49,14 @@ var sTestsSupplierSV1 = []func(t *testing.T){
|
||||
testV1SplSRpcConn,
|
||||
testV1SplSFromFolder,
|
||||
testV1SplSSetSupplierProfilesWithoutRatingPlanIDs,
|
||||
//tests for *reas sorting strategy
|
||||
testV1SplSAddNewSplPrf,
|
||||
testV1SplSAddNewResPrf,
|
||||
testV1SplSPopulateResUsage,
|
||||
testV1SplSGetSortedSuppliers,
|
||||
//tests for *reds sorting strategy
|
||||
testV1SplSAddNewSplPrf2,
|
||||
testV1SplSGetSortedSuppliers2,
|
||||
testV1SplSStopEngine,
|
||||
}
|
||||
|
||||
@@ -165,6 +173,351 @@ func testV1SplSSetSupplierProfilesWithoutRatingPlanIDs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSAddNewSplPrf(t *testing.T) {
|
||||
var reply *engine.SupplierProfile
|
||||
if err := splSv1Rpc.Call("ApierV1.GetSupplierProfile",
|
||||
&utils.TenantID{Tenant: "cgrates.org", ID: "SPL_ResourceTest"}, &reply); err == nil ||
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
t.Error(err)
|
||||
}
|
||||
//create a new Supplier Profile to test *reas and *reds sorting strategy
|
||||
splPrf = &engine.SupplierProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "SPL_ResourceTest",
|
||||
Sorting: utils.MetaReas,
|
||||
FilterIDs: []string{"*string:CustomField:ResourceTest"},
|
||||
Suppliers: []*engine.Supplier{
|
||||
//supplier1 will have ResourceUsage = 11
|
||||
{
|
||||
ID: "supplier1",
|
||||
ResourceIDs: []string{"ResourceSupplier1", "Resource2Supplier1"},
|
||||
Weight: 20,
|
||||
Blocker: false,
|
||||
},
|
||||
//supplier2 and supplier3 will have the same ResourceUsage = 7
|
||||
{
|
||||
ID: "supplier2",
|
||||
ResourceIDs: []string{"ResourceSupplier2"},
|
||||
Weight: 20,
|
||||
Blocker: false,
|
||||
},
|
||||
{
|
||||
ID: "supplier3",
|
||||
ResourceIDs: []string{"ResourceSupplier3"},
|
||||
Weight: 35,
|
||||
Blocker: false,
|
||||
},
|
||||
},
|
||||
Weight: 10,
|
||||
}
|
||||
var result string
|
||||
if err := splSv1Rpc.Call("ApierV1.SetSupplierProfile", splPrf, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
if err := splSv1Rpc.Call("ApierV1.GetSupplierProfile",
|
||||
&utils.TenantID{Tenant: "cgrates.org", ID: "SPL_ResourceTest"}, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(splPrf, reply) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", splPrf, reply)
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSAddNewResPrf(t *testing.T) {
|
||||
var result string
|
||||
//add ResourceSupplier1
|
||||
rPrf := &engine.ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ResourceSupplier1",
|
||||
FilterIDs: []string{"*string:Supplier:supplier1", "*string:ResID:ResourceSupplier1"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: time.Duration(1) * time.Minute,
|
||||
Limit: 10,
|
||||
Stored: true,
|
||||
Weight: 20,
|
||||
ThresholdIDs: []string{utils.META_NONE},
|
||||
}
|
||||
|
||||
if err := splSv1Rpc.Call("ApierV1.SetResourceProfile", rPrf, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
//add Resource2Supplier1
|
||||
rPrf2 := &engine.ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "Resource2Supplier1",
|
||||
FilterIDs: []string{"*string:Supplier:supplier1", "*string:ResID:Resource2Supplier1"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: time.Duration(1) * time.Minute,
|
||||
Limit: 10,
|
||||
Stored: true,
|
||||
Weight: 30,
|
||||
ThresholdIDs: []string{utils.META_NONE},
|
||||
}
|
||||
|
||||
if err := splSv1Rpc.Call("ApierV1.SetResourceProfile", rPrf2, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
//add ResourceSupplier2
|
||||
rPrf3 := &engine.ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ResourceSupplier2",
|
||||
FilterIDs: []string{"*string:Supplier:supplier2", "*string:ResID:ResourceSupplier2"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: time.Duration(1) * time.Minute,
|
||||
Limit: 10,
|
||||
Stored: true,
|
||||
Weight: 20,
|
||||
ThresholdIDs: []string{utils.META_NONE},
|
||||
}
|
||||
|
||||
if err := splSv1Rpc.Call("ApierV1.SetResourceProfile", rPrf3, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
//add ResourceSupplier2
|
||||
rPrf4 := &engine.ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ResourceSupplier3",
|
||||
FilterIDs: []string{"*string:Supplier:supplier3", "*string:ResID:ResourceSupplier3"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: time.Duration(1) * time.Minute,
|
||||
Limit: 10,
|
||||
Stored: true,
|
||||
Weight: 20,
|
||||
ThresholdIDs: []string{utils.META_NONE},
|
||||
}
|
||||
|
||||
if err := splSv1Rpc.Call("ApierV1.SetResourceProfile", rPrf4, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSPopulateResUsage(t *testing.T) {
|
||||
var reply string
|
||||
argsRU := utils.ArgRSv1ResourceUsage{
|
||||
UsageID: "RandomID",
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "Event1",
|
||||
Event: map[string]interface{}{
|
||||
"Account": "1002",
|
||||
"Supplier": "supplier1",
|
||||
"ResID": "ResourceSupplier1",
|
||||
},
|
||||
},
|
||||
Units: 4,
|
||||
}
|
||||
if err := splSv1Rpc.Call(utils.ResourceSv1AllocateResources,
|
||||
argsRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
eAllocationMsg := "ResourceSupplier1"
|
||||
if reply != eAllocationMsg {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eAllocationMsg, reply)
|
||||
}
|
||||
|
||||
argsRU = utils.ArgRSv1ResourceUsage{
|
||||
UsageID: "RandomID2",
|
||||
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "Event2",
|
||||
Event: map[string]interface{}{
|
||||
"Account": "1002",
|
||||
"Supplier": "supplier1",
|
||||
"ResID": "Resource2Supplier1",
|
||||
},
|
||||
},
|
||||
Units: 7,
|
||||
}
|
||||
if err := splSv1Rpc.Call(utils.ResourceSv1AllocateResources,
|
||||
argsRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
eAllocationMsg = "Resource2Supplier1"
|
||||
if reply != eAllocationMsg {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eAllocationMsg, reply)
|
||||
}
|
||||
|
||||
argsRU = utils.ArgRSv1ResourceUsage{
|
||||
UsageID: "RandomID3",
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "Event3",
|
||||
Event: map[string]interface{}{
|
||||
"Account": "1002",
|
||||
"Supplier": "supplier2",
|
||||
"ResID": "ResourceSupplier2",
|
||||
},
|
||||
},
|
||||
Units: 7,
|
||||
}
|
||||
if err := splSv1Rpc.Call(utils.ResourceSv1AllocateResources,
|
||||
argsRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
eAllocationMsg = "ResourceSupplier2"
|
||||
if reply != eAllocationMsg {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eAllocationMsg, reply)
|
||||
}
|
||||
|
||||
argsRU = utils.ArgRSv1ResourceUsage{
|
||||
UsageID: "RandomID4",
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "Event4",
|
||||
Event: map[string]interface{}{
|
||||
"Account": "1002",
|
||||
"Supplier": "supplier3",
|
||||
"ResID": "ResourceSupplier3",
|
||||
},
|
||||
},
|
||||
Units: 7,
|
||||
}
|
||||
if err := splSv1Rpc.Call(utils.ResourceSv1AllocateResources,
|
||||
argsRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
eAllocationMsg = "ResourceSupplier3"
|
||||
if reply != eAllocationMsg {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eAllocationMsg, reply)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testV1SplSGetSortedSuppliers(t *testing.T) {
|
||||
ev := &engine.ArgsGetSuppliers{
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "testV1SplSGetSortedSuppliers",
|
||||
Event: map[string]interface{}{
|
||||
"CustomField": "ResourceTest",
|
||||
},
|
||||
},
|
||||
}
|
||||
expSupplierIDs := []string{"supplier3", "supplier2", "supplier1"}
|
||||
var suplsReply engine.SortedSuppliers
|
||||
if err := splSv1Rpc.Call(utils.SupplierSv1GetSuppliers,
|
||||
ev, &suplsReply); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
rcvSupl := make([]string, len(suplsReply.SortedSuppliers))
|
||||
for i, supl := range suplsReply.SortedSuppliers {
|
||||
rcvSupl[i] = supl.SupplierID
|
||||
}
|
||||
if suplsReply.ProfileID != "SPL_ResourceTest" {
|
||||
t.Errorf("Expecting: SPL_ResourceTest, received: %s",
|
||||
suplsReply.ProfileID)
|
||||
}
|
||||
if !reflect.DeepEqual(rcvSupl, expSupplierIDs) {
|
||||
t.Errorf("Expecting: %+v, \n received: %+v",
|
||||
expSupplierIDs, utils.ToJSON(suplsReply))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSAddNewSplPrf2(t *testing.T) {
|
||||
var reply *engine.SupplierProfile
|
||||
if err := splSv1Rpc.Call("ApierV1.GetSupplierProfile",
|
||||
&utils.TenantID{Tenant: "cgrates.org", ID: "SPL_ResourceDescendent"}, &reply); err == nil ||
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
t.Error(err)
|
||||
}
|
||||
//create a new Supplier Profile to test *reas and *reds sorting strategy
|
||||
splPrf = &engine.SupplierProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "SPL_ResourceDescendent",
|
||||
Sorting: utils.MetaReds,
|
||||
FilterIDs: []string{"*string:CustomField:ResourceDescendent"},
|
||||
Suppliers: []*engine.Supplier{
|
||||
//supplier1 will have ResourceUsage = 11
|
||||
{
|
||||
ID: "supplier1",
|
||||
ResourceIDs: []string{"ResourceSupplier1", "Resource2Supplier1"},
|
||||
Weight: 20,
|
||||
Blocker: false,
|
||||
},
|
||||
//supplier2 and supplier3 will have the same ResourceUsage = 7
|
||||
{
|
||||
ID: "supplier2",
|
||||
ResourceIDs: []string{"ResourceSupplier2"},
|
||||
Weight: 20,
|
||||
Blocker: false,
|
||||
},
|
||||
{
|
||||
ID: "supplier3",
|
||||
ResourceIDs: []string{"ResourceSupplier3"},
|
||||
Weight: 35,
|
||||
Blocker: false,
|
||||
},
|
||||
},
|
||||
Weight: 10,
|
||||
}
|
||||
var result string
|
||||
if err := splSv1Rpc.Call("ApierV1.SetSupplierProfile", splPrf, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
if err := splSv1Rpc.Call("ApierV1.GetSupplierProfile",
|
||||
&utils.TenantID{Tenant: "cgrates.org", ID: "SPL_ResourceDescendent"}, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(splPrf, reply) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", splPrf, reply)
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSGetSortedSuppliers2(t *testing.T) {
|
||||
ev := &engine.ArgsGetSuppliers{
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "testV1SplSGetSortedSuppliers2",
|
||||
Event: map[string]interface{}{
|
||||
"CustomField": "ResourceDescendent",
|
||||
},
|
||||
},
|
||||
}
|
||||
expSupplierIDs := []string{"supplier1", "supplier3", "supplier2"}
|
||||
var suplsReply engine.SortedSuppliers
|
||||
if err := splSv1Rpc.Call(utils.SupplierSv1GetSuppliers,
|
||||
ev, &suplsReply); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
rcvSupl := make([]string, len(suplsReply.SortedSuppliers))
|
||||
for i, supl := range suplsReply.SortedSuppliers {
|
||||
rcvSupl[i] = supl.SupplierID
|
||||
}
|
||||
if suplsReply.ProfileID != "SPL_ResourceDescendent" {
|
||||
t.Errorf("Expecting: SPL_ResourceDescendent, received: %s",
|
||||
suplsReply.ProfileID)
|
||||
}
|
||||
if !reflect.DeepEqual(rcvSupl, expSupplierIDs) {
|
||||
t.Errorf("Expecting: %+v, \n received: %+v",
|
||||
expSupplierIDs, utils.ToJSON(suplsReply))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSStopEngine(t *testing.T) {
|
||||
if err := engine.KillEngine(100); err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -548,6 +548,7 @@ const (
|
||||
CGRDebitInterval = "CGRDebitInterval"
|
||||
Version = "Version"
|
||||
MetaTenant = "*tenant"
|
||||
ResourceUsage = "ResourceUsage"
|
||||
)
|
||||
|
||||
// Migrator Action
|
||||
|
||||
Reference in New Issue
Block a user