Adding *resources type for FilterS

This commit is contained in:
TeoV
2019-02-25 19:32:59 +02:00
committed by Dan Christian Bogos
parent a37cd65587
commit 2360aee3d1
4 changed files with 186 additions and 17 deletions

View File

@@ -57,7 +57,21 @@ func (rsv1 *ResourceSv1) ReleaseResources(args utils.ArgRSv1ResourceUsage, reply
return rsv1.rls.V1ReleaseResource(args, reply)
}
//func for getResource
// GetResource returns a resource configuration
func (apierV1 *ApierV1) GetResource(arg utils.TenantID, reply *engine.Resource) error {
if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
}
if res, err := apierV1.DataManager.GetResource(arg.Tenant, arg.ID, true, true, utils.NonTransactional); err != nil {
if err.Error() != utils.ErrNotFound.Error() {
err = utils.NewErrServerError(err)
}
return err
} else {
*reply = *res
}
return nil
}
// GetResourceProfile returns a resource configuration
func (apierV1 *ApierV1) GetResourceProfile(arg utils.TenantID, reply *engine.ResourceProfile) error {

View File

@@ -481,7 +481,7 @@ func (fltr *FilterRule) passStatS(dP config.DataProvider,
for key, val := range statValues {
ifaceStatValues[key] = val
}
//convert convert into a NavigableMap so we can send it to passGreaterThan
//convert ifaceStatValues into a NavigableMap so we can send it to passGreaterThan
nM := config.NewNavigableMap(ifaceStatValues)
//split the type in exact 2 parts
//special cases like *gt#sum#Usage
@@ -538,17 +538,30 @@ func (fltr *FilterRule) passResourceS(dP config.DataProvider,
if resourceS == nil || reflect.ValueOf(resourceS).IsNil() {
return false, errors.New("Missing ResourceS information")
}
// for _, resItem := range fltr.resourceItems {
// //take total usage for resource
// //compose the newFilter
// //send it to passGreaterThan
// // if val, err := fltr.passGreaterThan(nM); err != nil || !val {
// // //in case of error return false and error
// // //and in case of not pass return false and nil
// // return false, err
// // }
// }
for _, resItem := range fltr.resourceItems {
//take total usage for resource
var reply *Resource
if err := resourceS.Call(utils.ApierV1GetResource,
&utils.TenantID{Tenant: tenant, ID: resItem.ItemID}, &reply); err != nil {
return false, err
}
data := map[string]interface{}{
utils.Usage: reply.totalUsage(),
}
//convert data into a NavigableMap so we can send it to passGreaterThan
nM := config.NewNavigableMap(data)
//compose the newFilter
fltr, err := NewFilterRule(resItem.FilterType,
utils.Usage, []string{resItem.FilterValue})
if err != nil {
return false, err
}
// send it to passGreaterThan
if val, err := fltr.passGreaterThan(nM); err != nil || !val {
//in case of error return false and error
//and in case of not pass return false and nil
return false, err
}
}
return true, nil
}

View File

@@ -52,6 +52,7 @@ var sTestsFltr = []func(t *testing.T){
testV1FltrPupulateThreshold,
testV1FltrGetThresholdForEvent,
testV1FltrGetThresholdForEvent2,
testV1FltrPopulateResources,
testV1FltrStopEngine,
}
@@ -276,7 +277,6 @@ func testV1FltrPupulateThreshold(t *testing.T) {
},
MaxHits: -1,
MinSleep: time.Duration(1 * time.Millisecond),
Blocker: false,
Weight: 10.0,
ActionIDs: []string{"LOG"},
Async: true,
@@ -344,10 +344,8 @@ func testV1FltrGetThresholdForEvent2(t *testing.T) {
},
MaxHits: -1,
MinSleep: time.Duration(1 * time.Millisecond),
Blocker: false,
Weight: 10.0,
ActionIDs: []string{"LOG"},
Async: true,
}
if err := fltrRpc.Call("ApierV1.SetThresholdProfile", tPrfl, &result); err != nil {
t.Error(err)
@@ -368,6 +366,149 @@ func testV1FltrGetThresholdForEvent2(t *testing.T) {
}
}
func testV1FltrPopulateResources(t *testing.T) {
//create a resourceProfile
rlsConfig := &engine.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResTest",
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,
AllocationMessage: "MessageAllocation",
Stored: true,
Weight: 20,
ThresholdIDs: []string{utils.META_NONE},
}
var result string
if err := fltrRpc.Call("ApierV1.SetResourceProfile", rlsConfig, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
var reply *engine.ResourceProfile
if err := fltrRpc.Call("ApierV1.GetResourceProfile",
&utils.TenantID{Tenant: "cgrates.org", ID: rlsConfig.ID}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, rlsConfig) {
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(rlsConfig), utils.ToJSON(reply))
}
// Allocate 3 units for resource ResTest
argsRU := utils.ArgRSv1ResourceUsage{
CGREvent: utils.CGREvent{
Tenant: "cgrates.org",
Event: map[string]interface{}{
"Account": "3001",
"Destination": "3002"},
},
UsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21",
Units: 3,
}
if err := fltrRpc.Call(utils.ResourceSv1AllocateResources,
argsRU, &result); err != nil {
t.Error(err)
}
//we allocate 3 units to resource and add a filter for Usages > 2
//should match (3>2)
filter := &engine.Filter{
Tenant: "cgrates.org",
ID: "FLTR_TH_Resource",
Rules: []*engine.FilterRule{
{
Type: "*resources",
Values: []string{"*gt:ResTest:2.0"},
},
},
}
if err := fltrRpc.Call("ApierV1.SetFilter", filter, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
tPrfl := &engine.ThresholdProfile{
Tenant: "cgrates.org",
ID: "TH_ResTest",
FilterIDs: []string{"FLTR_TH_Resource", "*string:Account:2020"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
},
MaxHits: -1,
MinSleep: time.Duration(1 * time.Millisecond),
Weight: 10.0,
ActionIDs: []string{"LOG"},
Async: true,
}
if err := fltrRpc.Call("ApierV1.SetThresholdProfile", tPrfl, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
var rcvTh *engine.ThresholdProfile
if err := fltrRpc.Call("ApierV1.GetThresholdProfile",
&utils.TenantID{Tenant: tPrfl.Tenant, ID: tPrfl.ID}, &rcvTh); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(tPrfl, rcvTh) {
t.Errorf("Expecting: %+v, received: %+v", tPrfl, rcvTh)
}
// check the event
tEv := utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]interface{}{
utils.Account: "2020"},
}
var ids []string
eIDs := []string{"TH_ResTest"}
if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(ids, eIDs) {
t.Errorf("Expecting ids: %s, received: %s", eIDs, ids)
}
//change the filter
//we allocate 3 units to resource and add a filter for Usages < 2
//should fail (3<2)
filter = &engine.Filter{
Tenant: "cgrates.org",
ID: "FLTR_TH_Resource",
Rules: []*engine.FilterRule{
{
Type: "*resources",
Values: []string{"*lt:ResTest:2.0"},
},
},
}
if err := fltrRpc.Call("ApierV1.SetFilter", filter, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
//Overwrite the threshold
if err := fltrRpc.Call("ApierV1.SetThresholdProfile", tPrfl, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
}
//expect NotFound error because filter doesn't match
if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil ||
err.Error() != utils.ErrNotFound.Error() {
t.Error(err)
}
}
func testV1FltrStopEngine(t *testing.T) {
if err := engine.KillEngine(accDelay); err != nil {
t.Error(err)

View File

@@ -695,6 +695,7 @@ const (
ApierV1SetDispatcherProfile = "ApierV1.SetDispatcherProfile"
ApierV1GetDispatcherProfile = "ApierV1.GetDispatcherProfile"
ApierV1RemoveDispatcherProfile = "ApierV1.RemoveDispatcherProfile"
ApierV1GetResource = "ApierV1.GetResource"
)
const (