Updated routes APIs

This commit is contained in:
Trial97
2021-08-31 12:56:46 +03:00
committed by Dan Christian Bogos
parent 37e5481307
commit eab2338360
7 changed files with 157 additions and 60 deletions

View File

@@ -3592,26 +3592,26 @@ func testV1FIdxSetRouteSProfileWithFltr(t *testing.T) {
}
//we will set a RouteProfile with our filter and check the indexes
rtPrf := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "ROUTE_1",
FilterIDs: []string{"fltr_for_attr",
"*string:~*req.Account:1001"},
Sorting: utils.MetaWeight,
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "local",
RateProfileIDs: []string{"RP_LOCAL"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
{
ID: "mobile",
RateProfileIDs: []string{"RP_MOBILE"},
Weights: utils.DynamicWeights{{Weight: 30}},
Weights: ";30",
},
},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
}
if err := tFIdxRpc.Call(context.Background(), utils.AdminSv1SetRouteProfile,
@@ -3690,27 +3690,27 @@ func testV1FIdxSetRouteSMoreFltrsMoreIndexing(t *testing.T) {
t.Error("Unexpected reply result", reply)
}
// update our RoutesProfile with our filters
rtPrf := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "ROUTE_1",
FilterIDs: []string{"fltr_for_attr",
"fltr_for_attr2", "fltr_for_attr3",
"*string:~*req.Account:1001"},
Sorting: utils.MetaWeight,
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "local",
RateProfileIDs: []string{"RP_LOCAL"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
{
ID: "mobile",
RateProfileIDs: []string{"RP_MOBILE"},
Weights: utils.DynamicWeights{{Weight: 30}},
Weights: ";30",
},
},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
}
if err := tFIdxRpc.Call(context.Background(), utils.AdminSv1SetRouteProfile,
@@ -3800,38 +3800,38 @@ func testV1FIdxRouteSProfileComputeIndexes(t *testing.T) {
func testV1FIdxRouteSMoreProfilesForFltrs(t *testing.T) {
// will add more routes with our filters for matching indexes
rtPrf1 := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf1 := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "ROUTE_2",
FilterIDs: []string{"fltr_for_attr2", "fltr_for_attr3",
"*string:~*req.Account:1001"},
Sorting: utils.MetaWeight,
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "route1",
RateProfileIDs: []string{"RP_LOCAL"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
}
rtPrf2 := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf2 := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "ROUTE_3",
FilterIDs: []string{"fltr_for_attr",
"*string:~*req.Account:1001"},
Sorting: utils.MetaWeight,
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "route2",
RateProfileIDs: []string{"RP_LOCAL"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
}
var reply string

View File

@@ -799,22 +799,22 @@ func testLoadersGetRouteProfile(t *testing.T) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", expIDs, rtIDs)
}
expRtPrf := engine.RouteProfile{
expRtPrf := engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "ROUTE_ACNT_1001",
FilterIDs: []string{"FLTR_ACCOUNT_1001"},
Sorting: utils.MetaWeight,
SortingParameters: []string{},
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "route1",
Weights: utils.DynamicWeights{{Weight: 20}},
Weights: ";20",
},
},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
}
var rplyRtPrf engine.RouteProfile
var rplyRtPrf engine.APIRouteProfile
if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile,
utils.TenantID{
Tenant: "cgrates.org",
@@ -1116,7 +1116,7 @@ func testLoadersGetRouteProfileAfterRemove(t *testing.T) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
}
var rplyRtPrf engine.RouteProfile
var rplyRtPrf engine.APIRouteProfile
if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile,
utils.TenantID{
Tenant: "cgrates.org",

View File

@@ -24,7 +24,7 @@ import (
)
// GetRouteProfile returns a Route configuration
func (adms *AdminSv1) GetRouteProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.RouteProfile) error {
func (adms *AdminSv1) GetRouteProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.APIRouteProfile) error {
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
}
@@ -35,7 +35,7 @@ func (adms *AdminSv1) GetRouteProfile(ctx *context.Context, arg *utils.TenantIDW
if rp, err := adms.dm.GetRouteProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
return utils.APIErrorHandler(err)
} else {
*reply = *rp
*reply = *engine.NewAPIRouteProfile(rp)
}
return nil
}
@@ -81,20 +81,19 @@ func (adms *AdminSv1) GetRouteProfileCount(ctx *context.Context, args *utils.Ten
return nil
}
type RouteWithAPIOpts struct {
*engine.RouteProfile
APIOpts map[string]interface{}
}
//SetRouteProfile add a new Route configuration
func (adms *AdminSv1) SetRouteProfile(ctx *context.Context, args *RouteWithAPIOpts, reply *string) error {
if missing := utils.MissingStructFields(args.RouteProfile, []string{utils.ID}); len(missing) != 0 {
func (adms *AdminSv1) SetRouteProfile(ctx *context.Context, args *engine.APIRouteProfileWithAPIOpts, reply *string) error {
if missing := utils.MissingStructFields(args.APIRouteProfile, []string{utils.ID}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if args.Tenant == utils.EmptyString {
args.Tenant = adms.cfg.GeneralCfg().DefaultTenant
}
if err := adms.dm.SetRouteProfile(ctx, args.RouteProfile, true); err != nil {
rp, err := args.AsRouteProfile()
if err != nil {
return err
}
if err := adms.dm.SetRouteProfile(ctx, rp, true); err != nil {
return utils.APIErrorHandler(err)
}
//generate a loadID for CacheRouteProfiles and store it in database
@@ -103,7 +102,7 @@ func (adms *AdminSv1) SetRouteProfile(ctx *context.Context, args *RouteWithAPIOp
}
//handle caching for SupplierProfile
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.CacheOpt]), args.Tenant, utils.CacheRouteProfiles,
args.TenantID(), &args.FilterIDs, args.APIOpts); err != nil {
rp.TenantID(), &args.FilterIDs, args.APIOpts); err != nil {
return utils.APIErrorHandler(err)
}
*reply = utils.OK

View File

@@ -43,15 +43,16 @@ func TestRoutesSetGetRemRouteProfile(t *testing.T) {
ID: "routeID",
},
}
var result engine.RouteProfile
var result engine.APIRouteProfile
var reply string
rtPrf := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "routeID",
FilterIDs: []string{"*string:~*req.Account:1001"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
Routes: []*engine.ExternalRoute{{}},
},
}
@@ -63,9 +64,9 @@ func TestRoutesSetGetRemRouteProfile(t *testing.T) {
if err := adms.GetRouteProfile(context.Background(), arg, &result); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(result, *rtPrf.RouteProfile) {
} else if !reflect.DeepEqual(result, *rtPrf.APIRouteProfile) {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(rtPrf.RouteProfile), utils.ToJSON(result))
utils.ToJSON(rtPrf.APIRouteProfile), utils.ToJSON(result))
}
var rtPrfIDs []string
@@ -112,7 +113,7 @@ func TestRoutesGetRouteProfileCheckErrors(t *testing.T) {
cfg: cfg,
dm: dm,
}
var rcv engine.RouteProfile
var rcv engine.APIRouteProfile
experr := "MANDATORY_IE_MISSING: [ID]"
if err := adms.GetRouteProfile(context.Background(), &utils.TenantIDWithAPIOpts{
@@ -145,8 +146,10 @@ func TestRoutesSetRouteProfileCheckErrors(t *testing.T) {
dm: dm,
}
rtPrf := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{},
rtPrf := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
Routes: []*engine.ExternalRoute{{}},
},
}
var reply string
@@ -219,11 +222,12 @@ func TestRoutesRemoveRouteProfileCheckErrors(t *testing.T) {
dm: dm,
}
rtPrf := &RouteWithAPIOpts{
RouteProfile: &engine.RouteProfile{
rtPrf := &engine.APIRouteProfileWithAPIOpts{
APIRouteProfile: &engine.APIRouteProfile{
ID: "TestRoutesRemoveRouteProfileCheckErrors",
Tenant: "cgrates.org",
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
Routes: []*engine.ExternalRoute{{}},
},
}
var reply string
@@ -249,7 +253,7 @@ func TestRoutesRemoveRouteProfileCheckErrors(t *testing.T) {
cancel()
adms.cfg.GeneralCfg().DefaultCaching = utils.MetaNone
var rcv engine.RouteProfile
var rcv engine.APIRouteProfile
if err := adms.GetRouteProfile(context.Background(), &utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{

View File

@@ -180,7 +180,7 @@ func testCgrLdrGetSubsystemsNotLoadedLoad(t *testing.T) {
}
// routesPrf
var replyRts *engine.RouteProfile
var replyRts *engine.APIRouteProfile
if err := cgrLdrBIRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile,
&utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ROUTE_ACNT_1001"}},
&replyRts); err == nil || err.Error() != utils.ErrNotFound.Error() {
@@ -534,25 +534,25 @@ func testCgrLdrGetResourceAfterLoad(t *testing.T) {
}
func testCgrLdrGetRouteProfileAfterLoad(t *testing.T) {
expRoutePrf := &engine.RouteProfile{
expRoutePrf := &engine.APIRouteProfile{
ID: "ROUTE_ACNT_1001",
Tenant: "cgrates.org",
FilterIDs: []string{"FLTR_ACCOUNT_1001"},
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
Sorting: utils.MetaWeight,
SortingParameters: []string{},
Routes: []*engine.Route{
Routes: []*engine.ExternalRoute{
{
ID: "route1",
Weights: utils.DynamicWeights{{Weight: 20}},
Weights: ";20",
},
{
ID: "route2",
Weights: utils.DynamicWeights{{Weight: 10}},
Weights: ";10",
},
},
}
var replyRts *engine.RouteProfile
var replyRts *engine.APIRouteProfile
if err := cgrLdrBIRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile,
&utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ROUTE_ACNT_1001"}},
&replyRts); err != nil {

View File

@@ -60,6 +60,6 @@ func (self *CmdGetRoute) PostprocessRpcParams() error {
}
func (self *CmdGetRoute) RpcResult() interface{} {
var atr engine.RouteProfile
var atr engine.APIRouteProfile
return &atr
}

View File

@@ -320,3 +320,97 @@ type RouteWithWeight struct {
Weight float64
lazyCheckRules []*FilterRule
}
// ExternalRoute the attribute for external profile
type ExternalRoute struct {
ID string // RouteID
FilterIDs []string
AccountIDs []string
RateProfileIDs []string // used when computing price
ResourceIDs []string // queried in some strategies
StatIDs []string // queried in some strategies
Weights string
Blocker bool // do not process further route after this one
RouteParameters string
}
// APIRouteProfile used by APIs
type APIRouteProfile struct {
Tenant string
ID string // LCR Profile ID
FilterIDs []string
Sorting string // Sorting strategy
SortingParameters []string
Routes []*ExternalRoute
Weights string
}
type APIRouteProfileWithAPIOpts struct {
*APIRouteProfile
APIOpts map[string]interface{}
}
func NewAPIRouteProfile(attr *RouteProfile) (ext *APIRouteProfile) {
ext = &APIRouteProfile{
Tenant: attr.Tenant,
ID: attr.ID,
FilterIDs: attr.FilterIDs,
Sorting: attr.Sorting,
SortingParameters: attr.SortingParameters,
Routes: make([]*ExternalRoute, len(attr.Routes)),
Weights: attr.Weights.String(utils.InfieldSep, utils.ANDSep),
}
for i, r := range attr.Routes {
ext.Routes[i] = &ExternalRoute{
ID: r.ID,
FilterIDs: r.FilterIDs,
AccountIDs: r.AccountIDs,
RateProfileIDs: r.RateProfileIDs,
ResourceIDs: r.ResourceIDs,
StatIDs: r.StatIDs,
Weights: r.Weights.String(utils.InfieldSep, utils.ANDSep),
Blocker: r.Blocker,
RouteParameters: r.RouteParameters,
}
}
return
}
// AsAttributeProfile converts the external attribute format to the actual AttributeProfile
func (ext *APIRouteProfile) AsRouteProfile() (rp *RouteProfile, err error) {
if len(ext.Routes) == 0 {
return nil, utils.NewErrMandatoryIeMissing("Routes")
}
rp = &RouteProfile{
Tenant: ext.Tenant,
ID: ext.ID,
FilterIDs: ext.FilterIDs,
Sorting: ext.Sorting,
SortingParameters: ext.SortingParameters,
Routes: make([]*Route, len(ext.Routes)),
}
if ext.Weights != utils.EmptyString {
if rp.Weights, err = utils.NewDynamicWeightsFromString(ext.Weights, utils.InfieldSep, utils.ANDSep); err != nil {
return
}
}
for i, extR := range ext.Routes {
rp.Routes[i] = &Route{
ID: extR.ID,
FilterIDs: extR.FilterIDs,
AccountIDs: extR.AccountIDs,
RateProfileIDs: extR.RateProfileIDs,
ResourceIDs: extR.ResourceIDs,
StatIDs: extR.StatIDs,
Blocker: extR.Blocker,
RouteParameters: extR.RouteParameters,
}
if extR.Weights != utils.EmptyString {
if rp.Routes[i].Weights, err = utils.NewDynamicWeightsFromString(extR.Weights, utils.InfieldSep, utils.ANDSep); err != nil {
return
}
}
}
err = rp.Compile()
return
}