Added *profileIgnoreFilters for actions

This commit is contained in:
Trial97
2021-10-11 10:10:42 +03:00
committed by Dan Christian Bogos
parent 27d1882b09
commit 56f5ce07f3
7 changed files with 85 additions and 34 deletions

View File

@@ -92,11 +92,11 @@ func (aS *ActionS) schedInit() {
},
}
}
aS.scheduleActions(context.Background(), cgrEvs, nil, true)
aS.scheduleActions(context.Background(), cgrEvs, nil, false, true)
}
// scheduleActions will set up cron and load the matching data
func (aS *ActionS) scheduleActions(ctx *context.Context, cgrEvs []*utils.CGREvent, aPrflIDs []string, crnReset bool) (err error) {
func (aS *ActionS) scheduleActions(ctx *context.Context, cgrEvs []*utils.CGREvent, aPrflIDs []string, ignFilters, crnReset bool) (err error) {
aS.crnLk.Lock() // make sure we don't have parallel processes running setu
defer aS.crnLk.Unlock()
crn := aS.crn
@@ -106,7 +106,7 @@ func (aS *ActionS) scheduleActions(ctx *context.Context, cgrEvs []*utils.CGREven
var partExec bool
for _, cgrEv := range cgrEvs {
var schedActSet []*scheduledActs
if schedActSet, err = aS.scheduledActions(ctx, cgrEv.Tenant, cgrEv, aPrflIDs, false); err != nil {
if schedActSet, err = aS.scheduledActions(ctx, cgrEv.Tenant, cgrEv, aPrflIDs, ignFilters, false); err != nil {
utils.Logger.Warning(
fmt.Sprintf(
"<%s> scheduler init, ignoring tenant: <%s>, error: <%s>",
@@ -144,8 +144,9 @@ func (aS *ActionS) scheduleActions(ctx *context.Context, cgrEvs []*utils.CGREven
// matchingActionProfilesForEvent returns the matched ActionProfiles for the given event
func (aS *ActionS) matchingActionProfilesForEvent(ctx *context.Context, tnt string,
evNm utils.MapStorage, aPrflIDs []string) (aPfs engine.ActionProfiles, err error) {
evNm utils.MapStorage, aPrflIDs []string, ignoreFilters bool) (aPfs engine.ActionProfiles, err error) {
if len(aPrflIDs) == 0 {
ignoreFilters = false
var aPfIDMp utils.StringSet
if aPfIDMp, err = engine.MatchingItemIDsForEvent(
ctx,
@@ -173,11 +174,13 @@ func (aS *ActionS) matchingActionProfilesForEvent(ctx *context.Context, tnt stri
}
return
}
var pass bool
if pass, err = aS.fltrS.Pass(ctx, tnt, aPf.FilterIDs, evNm); err != nil {
return
} else if !pass {
continue
if !ignoreFilters {
var pass bool
if pass, err = aS.fltrS.Pass(ctx, tnt, aPf.FilterIDs, evNm); err != nil {
return
} else if !pass {
continue
}
}
aPfs = append(aPfs, aPf)
}
@@ -190,10 +193,10 @@ func (aS *ActionS) matchingActionProfilesForEvent(ctx *context.Context, tnt stri
// scheduledActions is responsible for scheduling the action profiles matching cgrEv
func (aS *ActionS) scheduledActions(ctx *context.Context, tnt string, cgrEv *utils.CGREvent, aPrflIDs []string,
forceASAP bool) (schedActs []*scheduledActs, err error) {
ignoreFilters, forceASAP bool) (schedActs []*scheduledActs, err error) {
var aPfs engine.ActionProfiles
evNm := cgrEv.AsDataProvider()
if aPfs, err = aS.matchingActionProfilesForEvent(ctx, tnt, evNm, aPrflIDs); err != nil {
if aPfs, err = aS.matchingActionProfilesForEvent(ctx, tnt, evNm, aPrflIDs, ignoreFilters); err != nil {
return
}
@@ -265,8 +268,13 @@ func (aS *ActionS) V1ScheduleActions(ctx *context.Context, args *utils.CGREvent,
utils.OptsActionsActionProfileIDs); err != nil {
return
}
var ignFilters bool
if ignFilters, err = engine.GetBoolOpts(ctx, args.Tenant, args, aS.fltrS, aS.cfg.ActionSCfg().Opts.ProfileIgnoreFilters,
utils.MetaProfileIgnoreFilters); err != nil {
return
}
if err = aS.scheduleActions(ctx, []*utils.CGREvent{args},
actPrfIDs, false); err != nil {
actPrfIDs, ignFilters, false); err != nil {
return
}
*rpl = utils.OK
@@ -280,9 +288,14 @@ func (aS *ActionS) V1ExecuteActions(ctx *context.Context, args *utils.CGREvent,
utils.OptsActionsActionProfileIDs); err != nil {
return
}
var ignFilters bool
if ignFilters, err = engine.GetBoolOpts(ctx, args.Tenant, args, aS.fltrS, aS.cfg.ActionSCfg().Opts.ProfileIgnoreFilters,
utils.MetaProfileIgnoreFilters); err != nil {
return
}
var schedActSet []*scheduledActs
if schedActSet, err = aS.scheduledActions(ctx, args.Tenant,
args, actPrfIDs, true); err != nil {
args, actPrfIDs, ignFilters, true); err != nil {
return
}
var partExec bool

View File

@@ -78,7 +78,7 @@ func TestMatchingActionProfilesForEvent(t *testing.T) {
expActionPrf := engine.ActionProfiles{actPrf}
if rcv, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, []string{}); err != nil {
evNM, []string{}, false); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, expActionPrf) {
t.Errorf("Expected %+v, received %+v", utils.ToJSON(expActionPrf), utils.ToJSON(rcv))
@@ -92,7 +92,7 @@ func TestMatchingActionProfilesForEvent(t *testing.T) {
}
//This Event is not matching with our filter
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, []string{}); err == nil || err != utils.ErrNotFound {
evNM, []string{}, false); err == nil || err != utils.ErrNotFound {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
@@ -105,26 +105,26 @@ func TestMatchingActionProfilesForEvent(t *testing.T) {
actPrfIDs := []string{"inexisting_id"}
//Unable to get from database an ActionProfile if the ID won't match
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, actPrfIDs); err == nil || err != utils.ErrNotFound {
evNM, actPrfIDs, false); err == nil || err != utils.ErrNotFound {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
actPrfIDs = []string{"test_id1"}
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, actPrfIDs); err == nil || err != utils.ErrNotFound {
evNM, actPrfIDs, false); err == nil || err != utils.ErrNotFound {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
actPrf.FilterIDs = append(actPrf.FilterIDs, "*ai:~*req.AnswerTime:2012-07-21T00:00:00Z|2012-08-21T00:00:00Z")
//this event is not active in this interval time
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, actPrfIDs); err == nil || err != utils.ErrNotFound {
evNM, actPrfIDs, false); err == nil || err != utils.ErrNotFound {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
//when dataManager is nil, it won't be able to get ActionsProfile from database
acts.dm = nil
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "INVALID_TENANT",
evNM, actPrfIDs); err == nil || err != utils.ErrNoDatabaseConn {
evNM, actPrfIDs, false); err == nil || err != utils.ErrNoDatabaseConn {
t.Errorf("Expected %+v, received %+v", utils.ErrNoDatabaseConn, err)
}
@@ -136,7 +136,7 @@ func TestMatchingActionProfilesForEvent(t *testing.T) {
}
expected := "NOT_FOUND:invalid_filters"
if _, err := acts.matchingActionProfilesForEvent(context.Background(), "cgrates.org",
evNM, actPrfIDs); err == nil || err.Error() != expected {
evNM, actPrfIDs, false); err == nil || err.Error() != expected {
t.Errorf("Expected %+v, received %+v", expected, err)
}
@@ -187,7 +187,7 @@ func TestScheduledActions(t *testing.T) {
t.Error(err)
}
if rcv, err := acts.scheduledActions(context.Background(), cgrEv.Tenant, cgrEv, []string{}, false); err != nil {
if rcv, err := acts.scheduledActions(context.Background(), cgrEv.Tenant, cgrEv, []string{}, false, false); err != nil {
t.Error(err)
} else {
expSchedActs := newScheduledActs(context.Background(), cgrEv.Tenant, cgrEv.ID, utils.MetaNone, utils.EmptyString,
@@ -204,7 +204,7 @@ func TestScheduledActions(t *testing.T) {
utils.Accounts: "10",
},
}
if _, err := acts.scheduledActions(context.Background(), cgrEv.Tenant, cgrEv, []string{}, false); err == nil || err != utils.ErrNotFound {
if _, err := acts.scheduledActions(context.Background(), cgrEv.Tenant, cgrEv, []string{}, false, false); err == nil || err != utils.ErrNotFound {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
}
@@ -248,12 +248,12 @@ func TestScheduleAction(t *testing.T) {
t.Error(err)
}
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, true); err != nil {
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, false, true); err != nil {
t.Error(err)
}
//Cannot schedule an action if the ID is invalid
if err := acts.scheduleActions(context.Background(), cgrEv, []string{"INVALID_ID1"}, true); err == nil || err != utils.ErrPartiallyExecuted {
if err := acts.scheduleActions(context.Background(), cgrEv, []string{"INVALID_ID1"}, false, true); err == nil || err != utils.ErrPartiallyExecuted {
t.Errorf("Expected %+v, received %+v", utils.ErrPartiallyExecuted, err)
}
@@ -262,7 +262,7 @@ func TestScheduleAction(t *testing.T) {
if err := acts.dm.SetActionProfile(context.Background(), actPrf, true); err != nil {
t.Error(err)
}
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, true); err != nil {
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, false, true); err != nil {
t.Error(err)
}
@@ -271,7 +271,7 @@ func TestScheduleAction(t *testing.T) {
if err := acts.dm.SetActionProfile(context.Background(), actPrf, true); err != nil {
t.Error(err)
}
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, true); err == nil || err != utils.ErrPartiallyExecuted {
if err := acts.scheduleActions(context.Background(), cgrEv, []string{}, false, true); err == nil || err != utils.ErrPartiallyExecuted {
t.Error(err)
}
}
@@ -1084,7 +1084,7 @@ func TestACScheduledActions(t *testing.T) {
acts := NewActionS(cfg, fltrs, dm, nil)
expected := "WARNING] <ActionS> ignoring ActionProfile with id: <cgrates.org:TestACScheduledActions> creating action: <TOPUP>, error: <unsupported action type: <inexistent_type>>"
if _, err := acts.scheduledActions(context.Background(), "cgrates.org", cgrEv, []string{}, true); err != nil {
if _, err := acts.scheduledActions(context.Background(), "cgrates.org", cgrEv, []string{}, false, true); err != nil {
t.Error(err)
} else if rcv := buff.String(); !strings.Contains(rcv, expected) {
t.Errorf("Expected %+v, received %+v", expected, rcv)
@@ -1117,7 +1117,7 @@ func TestACScheduledActions(t *testing.T) {
},
}
var schedActs []*scheduledActs
if schedActs, err = acts.scheduledActions(context.Background(), "cgrates.org", cgrEv, []string{}, true); err != nil {
if schedActs, err = acts.scheduledActions(context.Background(), "cgrates.org", cgrEv, []string{}, false, true); err != nil {
t.Error(err)
} else {

View File

@@ -24,7 +24,8 @@ import (
)
type ActionsOpts struct {
ActionProfileIDs []*utils.DynamicStringSliceOpt
ActionProfileIDs []*utils.DynamicStringSliceOpt
ProfileIgnoreFilters []*utils.DynamicBoolOpt
}
// ActionSCfg is the configuration of ActionS
@@ -61,6 +62,9 @@ func (actOpts *ActionsOpts) loadFromJSONCfg(jsnCfg *ActionsOptsJson) {
if jsnCfg.ActionProfileIDs != nil {
actOpts.ActionProfileIDs = append(actOpts.ActionProfileIDs, utils.MapToDynamicStringSliceOpts(jsnCfg.ActionProfileIDs)...)
}
if jsnCfg.ProfileIgnoreFilters != nil {
actOpts.ProfileIgnoreFilters = append(actOpts.ProfileIgnoreFilters, utils.MapToDynamicBoolOpts(jsnCfg.ProfileIgnoreFilters)...)
}
}
func (acS *ActionSCfg) loadFromJSONCfg(jsnCfg *ActionSJsonCfg) (err error) {
@@ -118,7 +122,8 @@ func (acS *ActionSCfg) loadFromJSONCfg(jsnCfg *ActionSJsonCfg) (err error) {
// AsMapInterface returns the config as a map[string]interface{}
func (acS ActionSCfg) AsMapInterface(string) interface{} {
opts := map[string]interface{}{
utils.MetaActionProfileIDsCfg: utils.DynamicStringSliceOptsToMap(acS.Opts.ActionProfileIDs),
utils.MetaActionProfileIDsCfg: utils.DynamicStringSliceOptsToMap(acS.Opts.ActionProfileIDs),
utils.MetaProfileIgnoreFilters: utils.DynamicBoolOptsToMap(acS.Opts.ProfileIgnoreFilters),
}
mp := map[string]interface{}{
utils.EnabledCfg: acS.Enabled,
@@ -165,8 +170,13 @@ func (actOpts *ActionsOpts) Clone() *ActionsOpts {
if actOpts.ActionProfileIDs != nil {
actPrfIDs = utils.CloneDynamicStringSliceOpt(actOpts.ActionProfileIDs)
}
var profileIgnoreFilters []*utils.DynamicBoolOpt
if actOpts.ProfileIgnoreFilters != nil {
profileIgnoreFilters = utils.CloneDynamicBoolOpt(actOpts.ProfileIgnoreFilters)
}
return &ActionsOpts{
ActionProfileIDs: actPrfIDs,
ActionProfileIDs: actPrfIDs,
ProfileIgnoreFilters: profileIgnoreFilters,
}
}
@@ -215,7 +225,8 @@ func (acS ActionSCfg) Clone() (cln *ActionSCfg) {
}
type ActionsOptsJson struct {
ActionProfileIDs map[string][]string `json:"*actionProfileIDs"`
ActionProfileIDs map[string][]string `json:"*actionProfileIDs"`
ProfileIgnoreFilters map[string]bool `json:"*profileIgnoreFilters"`
}
// Action service config section
@@ -243,6 +254,9 @@ func diffActionsOptsJsonCfg(d *ActionsOptsJson, v1, v2 *ActionsOpts) *ActionsOpt
if !utils.DynamicStringSliceOptEqual(v1.ActionProfileIDs, v2.ActionProfileIDs) {
d.ActionProfileIDs = utils.DynamicStringSliceOptsToMap(v2.ActionProfileIDs)
}
if !utils.DynamicBoolOptEqual(v1.ProfileIgnoreFilters, v2.ProfileIgnoreFilters) {
d.ProfileIgnoreFilters = utils.DynamicBoolOptsToMap(v2.ProfileIgnoreFilters)
}
return d
}

View File

@@ -62,6 +62,12 @@ func TestActionSCfgLoadFromJSONCfg(t *testing.T) {
Value: []string{},
},
},
ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
{
FilterIDs: []string{utils.MetaDefault},
Value: false,
},
},
},
}
jsnCfg := NewDefaultCGRConfig()
@@ -109,6 +115,9 @@ func TestActionSCfgAsMapInterface(t *testing.T) {
utils.MetaActionProfileIDsCfg: map[string][]string{
utils.MetaDefault: {},
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {

View File

@@ -1326,7 +1326,10 @@ const CGRATES_CFG_JSON = `
"opts":{ //
"*actionProfileIDs": { //
"*default": [],
},
},
"*profileIgnoreFilters": { // if we should check the filters
"*default": false,
}
},
},

View File

@@ -2344,6 +2344,9 @@ func TestDfActionSJsonCfg(t *testing.T) {
ActionProfileIDs: map[string][]string{
utils.MetaDefault: {},
},
ProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON))

File diff suppressed because one or more lines are too long