AttributeProfile add Blocker for multiple runs and add tests

This commit is contained in:
TeoV
2018-07-24 07:03:45 -04:00
committed by Dan Christian Bogos
parent a6cac1de00
commit dea8810abc
12 changed files with 276 additions and 31 deletions

View File

@@ -1,3 +1,3 @@
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight
cgrates.org,ATTR_1,*sessions;*cdrs,*string:Account:1007,2014-01-14T00:00:00Z,Account,*any,1001,false,10
cgrates.org,ATTR_1,,,,Subject,*any,1001,true,
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
cgrates.org,ATTR_1,*sessions;*cdrs,*string:Account:1007,2014-01-14T00:00:00Z,Account,*any,1001,false,false,10
cgrates.org,ATTR_1,,,,Subject,*any,1001,true,,
1 #Tenant ID Contexts FilterIDs ActivationInterval FieldName Initial Substitute Append Blocker Weight
2 cgrates.org ATTR_1 *sessions;*cdrs *string:Account:1007 2014-01-14T00:00:00Z Account *any 1001 false false 10
3 cgrates.org ATTR_1 Subject *any 1001 true

View File

@@ -1,2 +1,2 @@
#Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight
cgrates.org,ATTR_ACNT_1001,*sessions,FLTR_ACCOUNT_1001,,OfficeGroup,*any,Marketing,true,10
#Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
cgrates.org,ATTR_ACNT_1001,*sessions,FLTR_ACCOUNT_1001,,OfficeGroup,*any,Marketing,true,false,10
1 #Tenant ID Context FilterIDs ActivationInterval FieldName Initial Substitute Append Blocker Weight
2 cgrates.org ATTR_ACNT_1001 *sessions FLTR_ACCOUNT_1001 OfficeGroup *any Marketing true false 10

View File

@@ -1,3 +1,3 @@
#,Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight
cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,20
cgrates.org,ALS1,,,,Field2,Initial2,Sub2,false,
#,Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,false,20
cgrates.org,ALS1,,,,Field2,Initial2,Sub2,false,,
1 #,Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight #,Tenant,ID,Context,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
2 cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,20 cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,false,20
3 cgrates.org,ALS1,,,,Field2,Initial2,Sub2,false, cgrates.org,ALS1,,,,Field2,Initial2,Sub2,false,,

View File

@@ -1,15 +1,15 @@
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight
cgrates.org,ATTR_1001_SIMPLEAUTH,simpleauth,*string:Account:1001,,Password,*any,CGRateS.org,true,20
cgrates.org,ATTR_1002_SIMPLEAUTH,simpleauth,*string:Account:1002,,Password,*any,CGRateS.org,true,20
cgrates.org,ATTR_1003_SIMPLEAUTH,simpleauth,*string:Account:1003,,Password,*any,CGRateS.org,true,20
cgrates.org,ATTR_1001_SESSIONAUTH,*sessions,*string:Account:1001,,Password,*any,CGRateS.org,true,10
cgrates.org,ATTR_1001_SESSIONAUTH,,,,RequestType,*any,*prepaid,true,
cgrates.org,ATTR_1001_SESSIONAUTH,,,,PaypalAccount,*any,cgrates@paypal.com,true,
cgrates.org,ATTR_1001_SESSIONAUTH,,,,LCRProfile,*any,premium_cli,true,
cgrates.org,ATTR_1002_SESSIONAUTH,*sessions,*string:Account:1002,,Password,*any,CGRateS.org,true,10
cgrates.org,ATTR_1002_SESSIONAUTH,,,,RequestType,*any,*postpaid,true,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,PaypalAccount,*any,cgrates@paypal.com,true,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,LCRProfile,*any,premium_cli,true,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,ResourceAllocation,*any,"ResGroup1",true,
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
cgrates.org,ATTR_1001_SIMPLEAUTH,simpleauth,*string:Account:1001,,Password,*any,CGRateS.org,true,false,20
cgrates.org,ATTR_1002_SIMPLEAUTH,simpleauth,*string:Account:1002,,Password,*any,CGRateS.org,true,false,20
cgrates.org,ATTR_1003_SIMPLEAUTH,simpleauth,*string:Account:1003,,Password,*any,CGRateS.org,true,false,20
cgrates.org,ATTR_1001_SESSIONAUTH,*sessions,*string:Account:1001,,Password,*any,CGRateS.org,true,false,10
cgrates.org,ATTR_1001_SESSIONAUTH,,,,RequestType,*any,*prepaid,true,,
cgrates.org,ATTR_1001_SESSIONAUTH,,,,PaypalAccount,*any,cgrates@paypal.com,true,,
cgrates.org,ATTR_1001_SESSIONAUTH,,,,LCRProfile,*any,premium_cli,true,,
cgrates.org,ATTR_1002_SESSIONAUTH,*sessions,*string:Account:1002,,Password,*any,CGRateS.org,true,false,10
cgrates.org,ATTR_1002_SESSIONAUTH,,,,RequestType,*any,*postpaid,true,,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,PaypalAccount,*any,cgrates@paypal.com,true,,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,LCRProfile,*any,premium_cli,true,,
cgrates.org,ATTR_1002_SESSIONAUTH,,,,ResourceAllocation,*any,"ResGroup1",true,,
1 #Tenant ID Contexts FilterIDs ActivationInterval FieldName Initial Substitute Append Blocker Weight
2 cgrates.org ATTR_1001_SIMPLEAUTH simpleauth *string:Account:1001 Password *any CGRateS.org true false 20
3 cgrates.org ATTR_1002_SIMPLEAUTH simpleauth *string:Account:1002 Password *any CGRateS.org true false 20
4 cgrates.org ATTR_1003_SIMPLEAUTH simpleauth *string:Account:1003 Password *any CGRateS.org true false 20
5 cgrates.org ATTR_1001_SESSIONAUTH *sessions *string:Account:1001 Password *any CGRateS.org true false 10
6 cgrates.org ATTR_1001_SESSIONAUTH RequestType *any *prepaid true
7 cgrates.org ATTR_1001_SESSIONAUTH PaypalAccount *any cgrates@paypal.com true
8 cgrates.org ATTR_1001_SESSIONAUTH LCRProfile *any premium_cli true
9 cgrates.org ATTR_1002_SESSIONAUTH *sessions *string:Account:1002 Password *any CGRateS.org true false 10
10 cgrates.org ATTR_1002_SESSIONAUTH RequestType *any *postpaid true
11 cgrates.org ATTR_1002_SESSIONAUTH PaypalAccount *any cgrates@paypal.com true
12 cgrates.org ATTR_1002_SESSIONAUTH LCRProfile *any premium_cli true
13 cgrates.org ATTR_1002_SESSIONAUTH ResourceAllocation *any ResGroup1 true
14
15

View File

@@ -125,7 +125,6 @@ func (dS *DispatcherService) authorize(method, tenant, apiKey string, evTime *ti
return
}
var apiMethods string
fmt.Printf("\nRPL EV : %+v\n", utils.ToJSON(rplyEv))
if apiMethods, err = rplyEv.CGREvent.FieldAsString(utils.APIMethods); err != nil {
return
}

View File

@@ -141,6 +141,7 @@ type AttrSProcessEventReply struct {
MatchedProfiles []string
AlteredFields []string
CGREvent *utils.CGREvent
blocker bool
}
// Digest returns serialized version of alteredFields in AttrSProcessEventReply
@@ -174,7 +175,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) (
}
rply = &AttrSProcessEventReply{
MatchedProfiles: []string{attrPrf.ID},
CGREvent: args.Clone()}
CGREvent: args.Clone(),
blocker: attrPrf.Blocker}
for fldName, initialMp := range attrPrf.attributesIdx {
initEvValIf, has := args.Event[fldName]
if !has {
@@ -255,6 +257,9 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent,
}
if apiRply == nil { // first reply
apiRply = evRply
if apiRply.blocker == true {
break
}
continue
}
if utils.IsSliceMember(apiRply.MatchedProfiles,
@@ -269,6 +274,9 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent,
}
apiRply.AlteredFields = append(apiRply.AlteredFields, fldName)
}
if evRply.blocker == true {
break
}
}
*reply = *apiRply
return

View File

@@ -966,3 +966,232 @@ func TestAttributeProcessWithMultipleRuns4(t *testing.T) {
t.Errorf("Expecting %+v, received: %+v", eRply.CGREvent.Event, reply.CGREvent.Event)
}
}
func TestAttributeMultipleProcessWithBlocker(t *testing.T) {
//refresh the DM
if err := dmAtr.DataDB().Flush(""); err != nil {
t.Error(err)
}
if test, err := dmAtr.DataDB().IsDBEmpty(); err != nil {
t.Error(err)
} else if test != true {
t.Errorf("\nExpecting: true got :%+v", test)
}
attrPrf1 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_1",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:InitialField:InitialValue"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field1",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value1", true),
Append: true,
},
},
Weight: 10,
}
attrPrf2 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_2",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:Field1:Value1"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field2",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value2", true),
Append: true,
},
},
Blocker: true,
Weight: 20,
}
attrPrf3 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_3",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:Field2:Value2"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field3",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value3", true),
Append: true,
},
},
Weight: 30,
}
// Add attribute in DM
if err := dmAtr.SetAttributeProfile(attrPrf1, true); err != nil {
t.Error(err)
}
if err = dmAtr.SetAttributeProfile(attrPrf2, true); err != nil {
t.Errorf("Error: %+v", err)
}
if err = dmAtr.SetAttributeProfile(attrPrf3, true); err != nil {
t.Errorf("Error: %+v", err)
}
attrArgs := &AttrArgsProcessEvent{
ProcessRuns: utils.IntPointer(4),
CGREvent: utils.CGREvent{
Tenant: config.CgrConfig().DefaultTenant,
ID: utils.GenUUID(),
Context: utils.StringPointer(utils.MetaSessionS),
Event: map[string]interface{}{
"InitialField": "InitialValue",
},
},
}
eRply := &AttrSProcessEventReply{
MatchedProfiles: []string{"ATTR_1", "ATTR_2"},
AlteredFields: []string{"Field1", "Field2"},
CGREvent: &utils.CGREvent{
Tenant: config.CgrConfig().DefaultTenant,
ID: utils.GenUUID(),
Context: utils.StringPointer(utils.MetaSessionS),
Event: map[string]interface{}{
"InitialField": "InitialValue",
"Field1": "Value1",
"Field2": "Value2",
},
},
}
var reply AttrSProcessEventReply
if err := attrService.V1ProcessEvent(attrArgs, &reply); err != nil {
t.Errorf("Error: %+v", err)
}
if !reflect.DeepEqual(eRply.MatchedProfiles, reply.MatchedProfiles) {
t.Errorf("Expecting %+v, received: %+v", eRply.MatchedProfiles, reply.MatchedProfiles)
}
if !reflect.DeepEqual(eRply.AlteredFields, reply.AlteredFields) {
t.Errorf("Expecting %+v, received: %+v", eRply.AlteredFields, reply.AlteredFields)
}
if !reflect.DeepEqual(eRply.CGREvent.Event, reply.CGREvent.Event) {
t.Errorf("Expecting %+v, received: %+v", eRply.CGREvent.Event, reply.CGREvent.Event)
}
}
func TestAttributeMultipleProcessWithBlocker2(t *testing.T) {
//refresh the DM
if err := dmAtr.DataDB().Flush(""); err != nil {
t.Error(err)
}
if test, err := dmAtr.DataDB().IsDBEmpty(); err != nil {
t.Error(err)
} else if test != true {
t.Errorf("\nExpecting: true got :%+v", test)
}
attrPrf1 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_1",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:InitialField:InitialValue"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field1",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value1", true),
Append: true,
},
},
Blocker: true,
Weight: 10,
}
attrPrf2 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_2",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:Field1:Value1"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field2",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value2", true),
Append: true,
},
},
Weight: 20,
}
attrPrf3 := &AttributeProfile{
Tenant: config.CgrConfig().DefaultTenant,
ID: "ATTR_3",
Contexts: []string{utils.MetaSessionS},
FilterIDs: []string{"*string:Field2:Value2"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Attributes: []*Attribute{
&Attribute{
FieldName: "Field3",
Initial: utils.META_ANY,
Substitute: utils.NewRSRParsersMustCompile("Value3", true),
Append: true,
},
},
Weight: 30,
}
// Add attribute in DM
if err := dmAtr.SetAttributeProfile(attrPrf1, true); err != nil {
t.Error(err)
}
if err = dmAtr.SetAttributeProfile(attrPrf2, true); err != nil {
t.Errorf("Error: %+v", err)
}
if err = dmAtr.SetAttributeProfile(attrPrf3, true); err != nil {
t.Errorf("Error: %+v", err)
}
attrArgs := &AttrArgsProcessEvent{
ProcessRuns: utils.IntPointer(4),
CGREvent: utils.CGREvent{
Tenant: config.CgrConfig().DefaultTenant,
ID: utils.GenUUID(),
Context: utils.StringPointer(utils.MetaSessionS),
Event: map[string]interface{}{
"InitialField": "InitialValue",
},
},
}
eRply := &AttrSProcessEventReply{
MatchedProfiles: []string{"ATTR_1"},
AlteredFields: []string{"Field1"},
CGREvent: &utils.CGREvent{
Tenant: config.CgrConfig().DefaultTenant,
ID: utils.GenUUID(),
Context: utils.StringPointer(utils.MetaSessionS),
Event: map[string]interface{}{
"InitialField": "InitialValue",
"Field1": "Value1",
},
},
}
var reply AttrSProcessEventReply
if err := attrService.V1ProcessEvent(attrArgs, &reply); err != nil {
t.Errorf("Error: %+v", err)
}
if !reflect.DeepEqual(eRply.MatchedProfiles, reply.MatchedProfiles) {
t.Errorf("Expecting %+v, received: %+v", eRply.MatchedProfiles, reply.MatchedProfiles)
}
if !reflect.DeepEqual(eRply.AlteredFields, reply.AlteredFields) {
t.Errorf("Expecting %+v, received: %+v", eRply.AlteredFields, reply.AlteredFields)
}
if !reflect.DeepEqual(eRply.CGREvent.Event, reply.CGREvent.Event) {
t.Errorf("Expecting %+v, received: %+v", eRply.CGREvent.Event, reply.CGREvent.Event)
}
}

View File

@@ -38,6 +38,7 @@ type AttributeProfile struct {
FilterIDs []string
ActivationInterval *utils.ActivationInterval // Activation interval
Attributes []*Attribute
Blocker bool // blocker flag to stop processing on multiple runs
Weight float64
attributesIdx map[string]map[interface{}]*Attribute // map[FieldName][InitialValue]*Attribute, used as event match index

View File

@@ -299,9 +299,9 @@ cgrates.org,SPP_1,,,,,supplier1,FLTR_DST_DE,Account2,RPL_3,ResGroup3,Stat2,10,,,
cgrates.org,SPP_1,,,,,supplier1,,,,ResGroup4,Stat3,10,,,
`
attributeProfiles = `
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Weight
cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,20
cgrates.org,ALS1,con2;con3,,,Field2,Initial2,Sub2,false,
#Tenant,ID,Contexts,FilterIDs,ActivationInterval,FieldName,Initial,Substitute,Append,Blocker,Weight
cgrates.org,ALS1,con1,FLTR_1,2014-07-29T15:00:00Z,Field1,Initial1,Sub1,true,true,20
cgrates.org,ALS1,con2;con3,,,Field2,Initial2,Sub2,false,,
`
chargerProfiles = `
#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
@@ -1771,7 +1771,8 @@ func TestLoadAttributeProfiles(t *testing.T) {
Append: false,
},
},
Weight: 20,
Blocker: true,
Weight: 20,
},
}
resKey := utils.TenantID{Tenant: "cgrates.org", ID: "ALS1"}
@@ -1789,6 +1790,8 @@ func TestLoadAttributeProfiles(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].ActivationInterval, csvr.attributeProfiles[resKey].ActivationInterval)
} else if !reflect.DeepEqual(eAttrProfiles[resKey].Attributes, csvr.attributeProfiles[resKey].Attributes) {
t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].Attributes, csvr.attributeProfiles[resKey].Attributes)
} else if !reflect.DeepEqual(eAttrProfiles[resKey].Blocker, csvr.attributeProfiles[resKey].Blocker) {
t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].Blocker, csvr.attributeProfiles[resKey].Blocker)
}
}

View File

@@ -2684,9 +2684,10 @@ func (tps TPAttributes) AsTPAttributes() (result []*utils.TPAttributeProfile) {
th, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]
if !found {
th = &utils.TPAttributeProfile{
TPid: tp.Tpid,
Tenant: tp.Tenant,
ID: tp.ID,
TPid: tp.Tpid,
Tenant: tp.Tenant,
ID: tp.ID,
Blocker: tp.Blocker,
}
}
if tp.Weight != 0 {
@@ -2756,6 +2757,7 @@ func APItoModelTPAttribute(th *utils.TPAttributeProfile) (mdls TPAttributes) {
ID: th.ID,
}
if i == 0 {
mdl.Blocker = th.Blocker
if th.ActivationInterval != nil {
if th.ActivationInterval.ActivationTime != "" {
mdl.ActivationInterval = th.ActivationInterval.ActivationTime
@@ -2794,6 +2796,7 @@ func APItoAttributeProfile(tpTH *utils.TPAttributeProfile, timezone string) (th
Tenant: tpTH.Tenant,
ID: tpTH.ID,
Weight: tpTH.Weight,
Blocker: tpTH.Blocker,
FilterIDs: []string{},
Contexts: []string{},
}

View File

@@ -555,7 +555,8 @@ type TPAttribute struct {
Initial string `index:"6" re:""`
Substitute string `index:"7" re:""`
Append bool `index:"8" re:""`
Weight float64 `index:"9" re:"\d+\.?\d*"`
Blocker bool `index:"9" re:""`
Weight float64 `index:"10" re:"\d+\.?\d*"`
CreatedAt time.Time
}

View File

@@ -1423,6 +1423,7 @@ type TPAttributeProfile struct {
ActivationInterval *TPActivationInterval // Time when this limit becomes active and expires
Contexts []string // bind this TPAttribute to multiple context
Attributes []*TPAttribute
Blocker bool
Weight float64
}