mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-21 15:18:44 +05:00
New admins package
This commit is contained in:
committed by
Dan Christian Bogos
parent
75cf4a75cc
commit
5e4b392bd0
163
admins/accounts.go
Normal file
163
admins/accounts.go
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetAccount returns an Account
|
||||
func (admS *AdminS) V1GetAccount(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *utils.Account) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
ap, err := admS.dm.GetAccount(ctx, tnt, arg.ID)
|
||||
if err != nil {
|
||||
if err.Error() != utils.ErrNotFound.Error() {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
*reply = *ap
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAccountIDs returns list of account profile IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetAccountIDs(ctx *context.Context, args *utils.ArgsItemIDs, actPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.AccountPrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*actPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAccounts returns a list of accounts registered for a tenant
|
||||
func (admS *AdminS) V1GetAccounts(ctx *context.Context, args *utils.ArgsItemIDs, accs *[]*utils.Account) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var accIDs []string
|
||||
if err = admS.V1GetAccountIDs(ctx, args, &accIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*accs = make([]*utils.Account, 0, len(accIDs))
|
||||
for _, accID := range accIDs {
|
||||
var acc *utils.Account
|
||||
acc, err = admS.dm.GetAccount(ctx, tnt, accID)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*accs = append(*accs, acc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAccountsCount sets in reply var the total number of AccountIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 AccountIDs
|
||||
func (admS *AdminS) V1GetAccountsCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.AccountPrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetAccount add/update a new Account
|
||||
func (admS *AdminS) V1SetAccount(ctx *context.Context, args *utils.AccountWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args.Account, []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.SetAccount(ctx, args.Account, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheAccountProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheAccounts: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheAccounts,
|
||||
args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAccount remove a specific Account
|
||||
func (admS *AdminS) V1RemoveAccount(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveAccount(ctx, tnt, arg.ID,
|
||||
true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheAccountProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheAccounts: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheAccounts,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
165
admins/actions.go
Normal file
165
admins/actions.go
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetActionProfile returns an Action Profile
|
||||
func (admS *AdminS) V1GetActionProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.ActionProfile) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
ap, err := admS.dm.GetActionProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
if err.Error() != utils.ErrNotFound.Error() {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
*reply = *ap
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetActionProfileIDs returns list of action profile IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetActionProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, actPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ActionProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*actPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetActionProfiles returns a list of action profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetActionProfiles(ctx *context.Context, args *utils.ArgsItemIDs, actPrfs *[]*engine.ActionProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var actPrfIDs []string
|
||||
if err = admS.V1GetActionProfileIDs(ctx, args, &actPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*actPrfs = make([]*engine.ActionProfile, 0, len(actPrfIDs))
|
||||
for _, actPrfID := range actPrfIDs {
|
||||
var ap *engine.ActionProfile
|
||||
ap, err = admS.dm.GetActionProfile(ctx, tnt, actPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*actPrfs = append(*actPrfs, ap)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetActionProfilesCount sets in reply var the total number of ActionProfileIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 ActionProfileIDs
|
||||
func (admS *AdminS) V1GetActionProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ActionProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetActionProfile add/update a new Action Profile
|
||||
func (admS *AdminS) V1SetActionProfile(ctx *context.Context, ap *engine.ActionProfileWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(ap.ActionProfile, []string{utils.ID, utils.Actions}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if ap.Tenant == utils.EmptyString {
|
||||
ap.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
|
||||
if err := admS.dm.SetActionProfile(ctx, ap.ActionProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheActionProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheActionProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(ap.APIOpts[utils.MetaCache]), ap.Tenant, utils.CacheActionProfiles,
|
||||
ap.TenantID(), utils.EmptyString, &ap.FilterIDs, ap.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveActionProfile remove a specific Action Profile
|
||||
func (admS *AdminS) V1RemoveActionProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveActionProfile(ctx, tnt, arg.ID,
|
||||
true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheActionProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheActionProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheActionProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
50
admins/admins.go
Normal file
50
admins/admins.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
)
|
||||
|
||||
func NewAdminS(cfg *config.CGRConfig, dm *engine.DataManager, connMgr *engine.ConnManager, fltrS *engine.FilterS,
|
||||
storDBChan chan engine.StorDB) *AdminS {
|
||||
storDB := <-storDBChan
|
||||
return &AdminS{
|
||||
cfg: cfg,
|
||||
dm: dm,
|
||||
storDB: storDB,
|
||||
connMgr: connMgr,
|
||||
fltrS: fltrS,
|
||||
|
||||
// TODO: Might be a good idea to pass the storDB channel to AdminSv1
|
||||
// to be able to close the service the moment storDB is down (inside
|
||||
// a ListenAndServe goroutine maybe)
|
||||
|
||||
// storDBChan: storDBChan,
|
||||
}
|
||||
}
|
||||
|
||||
type AdminS struct {
|
||||
cfg *config.CGRConfig
|
||||
dm *engine.DataManager
|
||||
storDB engine.StorDB
|
||||
connMgr *engine.ConnManager
|
||||
fltrS *engine.FilterS
|
||||
}
|
||||
168
admins/attributes.go
Normal file
168
admins/attributes.go
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetAttributeProfile returns an Attribute Profile based on the tenant and ID received
|
||||
func (admS *AdminS) V1GetAttributeProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.APIAttributeProfile) (err error) {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if attrPrf, err := admS.dm.GetAttributeProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
} else {
|
||||
attr := engine.NewAPIAttributeProfile(attrPrf)
|
||||
*reply = *attr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttributeProfileIDs returns list of attributeProfile IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetAttributeProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, attrPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.AttributeProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*attrPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAttributeProfiles returns a list of attribute profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetAttributeProfiles(ctx *context.Context, args *utils.ArgsItemIDs, attrPrfs *[]*engine.APIAttributeProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var attrPrfIDs []string
|
||||
if err = admS.V1GetAttributeProfileIDs(ctx, args, &attrPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*attrPrfs = make([]*engine.APIAttributeProfile, 0, len(attrPrfIDs))
|
||||
for _, attrPrfID := range attrPrfIDs {
|
||||
var ap *engine.AttributeProfile
|
||||
ap, err = admS.dm.GetAttributeProfile(ctx, tnt, attrPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
attr := engine.NewAPIAttributeProfile(ap)
|
||||
*attrPrfs = append(*attrPrfs, attr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAttributeProfilesCount returns the total number of AttributeProfileIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 AttributeProfileIDs
|
||||
func (admS *AdminS) V1GetAttributeProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.AttributeProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetAttributeProfile add/update a new Attribute Profile
|
||||
func (admS *AdminS) V1SetAttributeProfile(ctx *context.Context, arg *engine.APIAttributeProfileWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg.APIAttributeProfile, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if arg.Tenant == utils.EmptyString {
|
||||
arg.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
alsPrf, err := arg.APIAttributeProfile.AsAttributeProfile()
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.dm.SetAttributeProfile(ctx, alsPrf, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheAttributeProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx,
|
||||
map[string]int64{utils.CacheAttributeProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), alsPrf.Tenant, utils.CacheAttributeProfiles,
|
||||
alsPrf.TenantID(), utils.EmptyString, &alsPrf.FilterIDs, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAttributeProfile remove a specific Attribute Profile based on tenant an ID
|
||||
func (admS *AdminS) V1RemoveAttributeProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveAttributeProfile(ctx, tnt, arg.ID,
|
||||
true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheAttributeProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheAttributeProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheAttributeProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
61
admins/cdrs.go
Normal file
61
admins/cdrs.go
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetCDRs retrieves a list of CDRs matching the specified filters.
|
||||
func (admS AdminS) V1GetCDRs(ctx *context.Context, args *utils.CDRFilters, reply *[]*utils.CDR) error {
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
fltrs, err := engine.GetFilters(ctx, args.FilterIDs, args.Tenant, admS.dm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("preparing filters failed: %w", err)
|
||||
}
|
||||
cdrs, err := admS.storDB.GetCDRs(ctx, fltrs, args.APIOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("retrieving CDRs failed: %w", err)
|
||||
}
|
||||
*reply = cdrs
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveCDRs removes CDRs matching the specified filters.
|
||||
func (admS AdminS) V1RemoveCDRs(ctx *context.Context, args *utils.CDRFilters, reply *string) (err error) {
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
fltrs, err := engine.GetFilters(ctx, args.FilterIDs, args.Tenant, admS.dm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("preparing filters failed: %w", err)
|
||||
}
|
||||
if err := admS.storDB.RemoveCDRs(ctx, fltrs); err != nil {
|
||||
return fmt.Errorf("removing CDRs failed: %w", err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return
|
||||
}
|
||||
169
admins/chargers.go
Normal file
169
admins/chargers.go
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetChargerProfile returns a Charger Profile
|
||||
func (adms *AdminS) V1GetChargerProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.ChargerProfile) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if cpp, err := adms.dm.GetChargerProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
} else {
|
||||
*reply = *cpp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetChargerProfileIDs returns list of chargerProfile IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetChargerProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, chPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ChargerProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*chPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetChargerProfiles returns a list of charger profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetChargerProfiles(ctx *context.Context, args *utils.ArgsItemIDs, chrgPrfs *[]*engine.ChargerProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var chrgPrfIDs []string
|
||||
if err = admS.V1GetChargerProfileIDs(ctx, args, &chrgPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*chrgPrfs = make([]*engine.ChargerProfile, 0, len(chrgPrfIDs))
|
||||
for _, chrgPrfID := range chrgPrfIDs {
|
||||
var chgrPrf *engine.ChargerProfile
|
||||
chgrPrf, err = admS.dm.GetChargerProfile(ctx, tnt, chrgPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*chrgPrfs = append(*chrgPrfs, chgrPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetChargerProfilesCount returns the total number of ChargerProfiles registered for a tenant
|
||||
// returns ErrNotFound in case of 0 ChargerProfiles
|
||||
func (admS *AdminS) V1GetChargerProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ChargerProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
type ChargerWithAPIOpts struct {
|
||||
*engine.ChargerProfile
|
||||
APIOpts map[string]any
|
||||
}
|
||||
|
||||
// SetChargerProfile add/update a new Charger Profile
|
||||
func (adms *AdminS) V1SetChargerProfile(ctx *context.Context, arg *ChargerWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg.ChargerProfile, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if arg.Tenant == utils.EmptyString {
|
||||
arg.Tenant = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.SetChargerProfile(ctx, arg.ChargerProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheChargerProfiles and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheChargerProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ChargerProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), arg.Tenant, utils.CacheChargerProfiles,
|
||||
arg.TenantID(), utils.EmptyString, &arg.FilterIDs, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveChargerProfile remove a specific Charger Profile
|
||||
func (adms *AdminS) V1RemoveChargerProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveChargerProfile(ctx, tnt,
|
||||
arg.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheChargerProfiles and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheChargerProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ChargerProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheChargerProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
316
admins/dispatchers.go
Normal file
316
admins/dispatchers.go
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetDispatcherProfile returns a Dispatcher Profile
|
||||
func (admS *AdminS) V1GetDispatcherProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.DispatcherProfile) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
dpp, err := admS.dm.GetDispatcherProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = *dpp
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDispatcherProfileIDs returns list of dispatcherProfile IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetDispatcherProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, dPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.DispatcherProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*dPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDispatcherProfiles returns a list of dispatcher profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetDispatcherProfiles(ctx *context.Context, args *utils.ArgsItemIDs, dspPrfs *[]*engine.DispatcherProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var dspPrfIDs []string
|
||||
if err = admS.V1GetDispatcherProfileIDs(ctx, args, &dspPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*dspPrfs = make([]*engine.DispatcherProfile, 0, len(dspPrfIDs))
|
||||
for _, dspPrfID := range dspPrfIDs {
|
||||
var dspPrf *engine.DispatcherProfile
|
||||
dspPrf, err = admS.dm.GetDispatcherProfile(ctx, tnt, dspPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*dspPrfs = append(*dspPrfs, dspPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDispatcherProfilesCount returns the total number of DispatcherProfiles registered for a tenant
|
||||
// returns ErrNotFound in case of 0 DispatcherProfiles
|
||||
func (admS *AdminS) V1GetDispatcherProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.DispatcherProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
type DispatcherWithAPIOpts struct {
|
||||
*engine.DispatcherProfile
|
||||
APIOpts map[string]any
|
||||
}
|
||||
|
||||
// SetDispatcherProfile add/update a new Dispatcher Profile
|
||||
func (admS *AdminS) V1SetDispatcherProfile(ctx *context.Context, args *DispatcherWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args.DispatcherProfile, []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.SetDispatcherProfile(ctx, args.DispatcherProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheDispatcherProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheDispatcherProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatcherProfile
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheDispatcherProfiles,
|
||||
args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatchersInstance
|
||||
cacheAct := utils.MetaRemove
|
||||
if err := admS.CallCache(ctx, utils.FirstNonEmpty(utils.IfaceAsString(args.APIOpts[utils.MetaCache]), cacheAct),
|
||||
args.Tenant, utils.CacheDispatchers, args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatcherRoutes
|
||||
if err := admS.CallCache(ctx, utils.FirstNonEmpty(utils.IfaceAsString(args.APIOpts[utils.MetaCache]), cacheAct),
|
||||
args.Tenant, utils.CacheDispatcherRoutes, args.TenantID(),
|
||||
utils.ConcatenatedKey(utils.CacheDispatcherProfiles, args.Tenant, args.ID),
|
||||
&args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDispatcherProfile remove a specific Dispatcher Profile
|
||||
func (admS *AdminS) V1RemoveDispatcherProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveDispatcherProfile(ctx, tnt,
|
||||
arg.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheDispatcherProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheDispatcherProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatcherProfile
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheDispatcherProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDispatcherHost returns a Dispatcher Host
|
||||
func (admS *AdminS) V1GetDispatcherHost(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.DispatcherHost) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
dpp, err := admS.dm.GetDispatcherHost(ctx, tnt, arg.ID, true, false, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = *dpp
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDispatcherHostIDs returns list of dispatcherHost IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetDispatcherHostIDs(ctx *context.Context, args *utils.ArgsItemIDs, dspHostIDs *[]string) (err error) {
|
||||
tenant := args.Tenant
|
||||
if tenant == utils.EmptyString {
|
||||
tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.DispatcherHostPrefix + tenant + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*dspHostIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDispatcherHosts returns a list of dispatcher hosts registered for a tenant
|
||||
func (admS *AdminS) V1GetDispatcherHosts(ctx *context.Context, args *utils.ArgsItemIDs, dspHosts *[]*engine.DispatcherHost) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var dspHostIDs []string
|
||||
if err = admS.V1GetDispatcherHostIDs(ctx, args, &dspHostIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*dspHosts = make([]*engine.DispatcherHost, 0, len(dspHostIDs))
|
||||
for _, dspHostID := range dspHostIDs {
|
||||
var dspHost *engine.DispatcherHost
|
||||
dspHost, err = admS.dm.GetDispatcherHost(ctx, tnt, dspHostID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*dspHosts = append(*dspHosts, dspHost)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDispatcherHostsCount returns the total number of DispatcherHosts registered for a tenant
|
||||
// returns ErrNotFound in case of 0 DispatcherHosts
|
||||
func (admS *AdminS) V1GetDispatcherHostsCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.DispatcherHostPrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetDispatcherHost add/update a new Dispatcher Host
|
||||
func (admS *AdminS) V1SetDispatcherHost(ctx *context.Context, args *engine.DispatcherHostWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args.DispatcherHost, []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.SetDispatcherHost(ctx, args.DispatcherHost); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheDispatcherHosts and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheDispatcherHosts: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatcherProfile
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheDispatcherHosts,
|
||||
args.TenantID(), utils.EmptyString, nil, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveDispatcherHost remove a specific Dispatcher Host
|
||||
func (admS *AdminS) V1RemoveDispatcherHost(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveDispatcherHost(ctx, tnt, arg.ID); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheDispatcherHosts and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheDispatcherHosts: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for DispatcherProfile
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheDispatcherHosts,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
842
admins/filter_indexes.go
Normal file
842
admins/filter_indexes.go
Normal file
@@ -0,0 +1,842 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/ltcache"
|
||||
)
|
||||
|
||||
type AttrGetFilterIndexes struct {
|
||||
Tenant string
|
||||
Context string
|
||||
ItemType string
|
||||
FilterType string
|
||||
FilterField string
|
||||
FilterValue string
|
||||
APIOpts map[string]any
|
||||
}
|
||||
|
||||
type AttrRemFilterIndexes struct {
|
||||
Tenant string
|
||||
Context string
|
||||
ItemType string
|
||||
APIOpts map[string]any
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1RemoveFilterIndexes(ctx *context.Context, arg *AttrRemFilterIndexes, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(arg, []string{"ItemType"}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
tntCtx := tnt
|
||||
switch arg.ItemType {
|
||||
case utils.MetaThresholds:
|
||||
arg.ItemType = utils.CacheThresholdFilterIndexes
|
||||
case utils.MetaRoutes:
|
||||
arg.ItemType = utils.CacheRouteFilterIndexes
|
||||
case utils.MetaStats:
|
||||
arg.ItemType = utils.CacheStatFilterIndexes
|
||||
case utils.MetaResources:
|
||||
arg.ItemType = utils.CacheResourceFilterIndexes
|
||||
case utils.MetaChargers:
|
||||
arg.ItemType = utils.CacheChargerFilterIndexes
|
||||
case utils.MetaAccounts:
|
||||
arg.ItemType = utils.CacheAccountsFilterIndexes
|
||||
case utils.MetaActions:
|
||||
arg.ItemType = utils.CacheActionProfilesFilterIndexes
|
||||
case utils.MetaRateProfiles:
|
||||
arg.ItemType = utils.CacheRateProfilesFilterIndexes
|
||||
case utils.MetaRateProfileRates:
|
||||
if missing := utils.MissingStructFields(arg, []string{"Context"}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
arg.ItemType = utils.CacheRateFilterIndexes
|
||||
tntCtx = utils.ConcatenatedKey(tnt, arg.Context)
|
||||
case utils.MetaDispatchers:
|
||||
arg.ItemType = utils.CacheDispatcherFilterIndexes
|
||||
case utils.MetaAttributes:
|
||||
arg.ItemType = utils.CacheAttributeFilterIndexes
|
||||
}
|
||||
if err = adms.dm.RemoveIndexes(ctx, arg.ItemType, tntCtx, utils.EmptyString); err != nil {
|
||||
return
|
||||
}
|
||||
//generate a loadID for CacheFilterIndexes and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx,
|
||||
map[string]int64{arg.ItemType: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := adms.callCacheForRemoveIndexes(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), arg.Tenant,
|
||||
arg.ItemType, []string{utils.MetaAny}, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetFilterIndexes(ctx *context.Context, arg *AttrGetFilterIndexes, reply *[]string) (err error) {
|
||||
var indexes map[string]utils.StringSet
|
||||
var indexedSlice []string
|
||||
indexesFilter := make(map[string]utils.StringSet)
|
||||
if missing := utils.MissingStructFields(arg, []string{"ItemType"}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
tntCtx := tnt
|
||||
switch arg.ItemType {
|
||||
case utils.MetaThresholds:
|
||||
arg.ItemType = utils.CacheThresholdFilterIndexes
|
||||
case utils.MetaRoutes:
|
||||
arg.ItemType = utils.CacheRouteFilterIndexes
|
||||
case utils.MetaStats:
|
||||
arg.ItemType = utils.CacheStatFilterIndexes
|
||||
case utils.MetaResources:
|
||||
arg.ItemType = utils.CacheResourceFilterIndexes
|
||||
case utils.MetaChargers:
|
||||
arg.ItemType = utils.CacheChargerFilterIndexes
|
||||
case utils.MetaAccounts:
|
||||
arg.ItemType = utils.CacheAccountsFilterIndexes
|
||||
case utils.MetaActions:
|
||||
arg.ItemType = utils.CacheActionProfilesFilterIndexes
|
||||
case utils.MetaRateProfiles:
|
||||
arg.ItemType = utils.CacheRateProfilesFilterIndexes
|
||||
case utils.MetaRateProfileRates:
|
||||
if missing := utils.MissingStructFields(arg, []string{"Context"}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
arg.ItemType = utils.CacheRateFilterIndexes
|
||||
tntCtx = utils.ConcatenatedKey(tnt, arg.Context)
|
||||
case utils.MetaDispatchers:
|
||||
arg.ItemType = utils.CacheDispatcherFilterIndexes
|
||||
case utils.MetaAttributes:
|
||||
arg.ItemType = utils.CacheAttributeFilterIndexes
|
||||
}
|
||||
if indexes, err = adms.dm.GetIndexes(ctx,
|
||||
arg.ItemType, tntCtx, utils.EmptyString, utils.EmptyString, true, true); err != nil {
|
||||
return
|
||||
}
|
||||
if arg.FilterType != utils.EmptyString {
|
||||
for val, strmap := range indexes {
|
||||
if strings.HasPrefix(val, arg.FilterType) {
|
||||
indexesFilter[val] = strmap
|
||||
for _, value := range strmap.AsSlice() {
|
||||
indexedSlice = append(indexedSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(indexedSlice) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
}
|
||||
if arg.FilterField != utils.EmptyString {
|
||||
if len(indexedSlice) == 0 {
|
||||
indexesFilter = make(map[string]utils.StringSet)
|
||||
for val, strmap := range indexes {
|
||||
if strings.Contains(val, arg.FilterField) {
|
||||
indexesFilter[val] = strmap
|
||||
for _, value := range strmap.AsSlice() {
|
||||
indexedSlice = append(indexedSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(indexedSlice) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
} else {
|
||||
var cloneIndexSlice []string
|
||||
for val, strmap := range indexesFilter {
|
||||
if strings.Contains(val, arg.FilterField) {
|
||||
for _, value := range strmap.AsSlice() {
|
||||
cloneIndexSlice = append(cloneIndexSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(cloneIndexSlice) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
indexedSlice = cloneIndexSlice
|
||||
}
|
||||
}
|
||||
if arg.FilterValue != utils.EmptyString {
|
||||
if len(indexedSlice) == 0 {
|
||||
for val, strmap := range indexes {
|
||||
if strings.Contains(val, arg.FilterValue) {
|
||||
for _, value := range strmap.AsSlice() {
|
||||
indexedSlice = append(indexedSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(indexedSlice) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
} else {
|
||||
var cloneIndexSlice []string
|
||||
for val, strmap := range indexesFilter {
|
||||
if strings.Contains(val, arg.FilterValue) {
|
||||
for _, value := range strmap.AsSlice() {
|
||||
cloneIndexSlice = append(cloneIndexSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(cloneIndexSlice) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
indexedSlice = cloneIndexSlice
|
||||
}
|
||||
}
|
||||
if len(indexedSlice) == 0 {
|
||||
for val, strmap := range indexes {
|
||||
for _, value := range strmap.AsSlice() {
|
||||
indexedSlice = append(indexedSlice, utils.ConcatenatedKey(val, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(arg.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*reply, err = utils.Paginate(indexedSlice, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// ComputeFilterIndexes selects which index filters to recompute
|
||||
func (adms *AdminS) V1ComputeFilterIndexes(ctx *context.Context, args *utils.ArgsComputeFilterIndexes, reply *string) (err error) {
|
||||
transactionID := utils.GenUUID()
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
cacheIDs := make(map[string][]string)
|
||||
|
||||
var indexes utils.StringSet
|
||||
//ThresholdProfile Indexes
|
||||
if args.ThresholdS {
|
||||
cacheIDs[utils.CacheThresholdFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheThresholdFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
th, e := adms.dm.GetThresholdProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(th.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.ThresholdS = indexes.Size() != 0
|
||||
}
|
||||
//StatQueueProfile Indexes
|
||||
if args.StatS {
|
||||
cacheIDs[utils.CacheStatFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheStatFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
sq, e := adms.dm.GetStatQueueProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(sq.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.StatS = indexes.Size() != 0
|
||||
}
|
||||
//ResourceProfile Indexes
|
||||
if args.ResourceS {
|
||||
cacheIDs[utils.CacheResourceFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheResourceFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rp, e := adms.dm.GetResourceProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(rp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.ResourceS = indexes.Size() != 0
|
||||
}
|
||||
//RouteSProfile Indexes
|
||||
if args.RouteS {
|
||||
cacheIDs[utils.CacheRouteFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheRouteFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rp, e := adms.dm.GetRouteProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(rp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.RouteS = indexes.Size() != 0
|
||||
}
|
||||
//AttributeProfile Indexes
|
||||
if args.AttributeS {
|
||||
cacheIDs[utils.CacheAttributeFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheAttributeFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
attr, e := adms.dm.GetAttributeProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(attr.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.AttributeS = indexes.Size() != 0
|
||||
}
|
||||
//ChargerProfile Indexes
|
||||
if args.ChargerS {
|
||||
cacheIDs[utils.CacheChargerFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheChargerFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
ch, e := adms.dm.GetChargerProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(ch.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.ChargerS = indexes.Size() != 0
|
||||
}
|
||||
//AccountFilter Indexes
|
||||
if args.AccountS {
|
||||
cacheIDs[utils.CacheAccountsFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheAccountsFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
acnts, e := adms.dm.GetAccount(ctx, tnt, id)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(acnts.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.AccountS = indexes.Size() != 0
|
||||
}
|
||||
//ActionFilter Indexes
|
||||
if args.ActionS {
|
||||
cacheIDs[utils.CacheActionProfilesFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheActionProfilesFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
act, e := adms.dm.GetActionProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(act.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.ActionS = indexes.Size() != 0
|
||||
}
|
||||
// RateFilter Indexes
|
||||
var ratePrf []string
|
||||
if args.RateS {
|
||||
cacheIDs[utils.CacheRateProfilesFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheRateProfilesFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rtPrf, e := adms.dm.GetRateProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
ratePrf = append(ratePrf, utils.ConcatenatedKey(tnt, id))
|
||||
rtIds := make([]string, 0, len(rtPrf.Rates))
|
||||
for key := range rtPrf.Rates {
|
||||
rtIds = append(rtIds, key)
|
||||
}
|
||||
cacheIDs[utils.CacheRateFilterIndexes] = rtIds
|
||||
_, e = engine.ComputeIndexes(ctx, adms.dm, tnt, id, utils.CacheRateFilterIndexes,
|
||||
&rtIds, transactionID, func(_, id, _ string) (*[]string, error) {
|
||||
return utils.SliceStringPointer(slices.Clone(rtPrf.Rates[id].FilterIDs)), nil
|
||||
}, nil)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(rtPrf.FilterIDs)), nil
|
||||
}, nil); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.RateS = indexes.Size() != 0
|
||||
}
|
||||
//DispatcherProfile Indexes
|
||||
if args.DispatcherS {
|
||||
cacheIDs[utils.CacheDispatcherFilterIndexes] = []string{utils.MetaAny}
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheDispatcherFilterIndexes,
|
||||
nil, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
dsp, e := adms.dm.GetDispatcherProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(dsp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrDSPProfileNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
args.DispatcherS = indexes.Size() != 0
|
||||
}
|
||||
|
||||
//Now we move from tmpKey to the right key for each type
|
||||
//ThresholdProfile Indexes
|
||||
if args.ThresholdS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheThresholdFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//StatQueueProfile Indexes
|
||||
if args.StatS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheStatFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//ResourceProfile Indexes
|
||||
if args.ResourceS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheResourceFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//RouteProfile Indexes
|
||||
if args.RouteS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheRouteFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//AttributeProfile Indexes
|
||||
if args.AttributeS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheAttributeFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//ChargerProfile Indexes
|
||||
if args.ChargerS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheChargerFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//AccountProfile Indexes
|
||||
if args.AccountS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheAccountsFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
//ActionProfile Indexes
|
||||
if args.ActionS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheActionProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
//RateProfile Indexes
|
||||
if args.RateS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheRateProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tntId := range ratePrf {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheRateFilterIndexes, tntId, nil, true, transactionID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//DispatcherProfile Indexes
|
||||
if args.DispatcherS {
|
||||
if err = adms.dm.SetIndexes(ctx, utils.CacheDispatcherFilterIndexes, tnt, nil, true, transactionID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
//generate a load
|
||||
//ID for CacheFilterIndexes and store it in database
|
||||
loadIDs := make(map[string]int64)
|
||||
timeNow := time.Now().UnixNano()
|
||||
for idx := range cacheIDs {
|
||||
loadIDs[idx] = timeNow
|
||||
}
|
||||
if err := adms.dm.SetLoadIDs(ctx, loadIDs); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := adms.callCacheForComputeIndexes(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]),
|
||||
args.Tenant, cacheIDs, args.APIOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComputeFilterIndexIDs computes specific filter indexes
|
||||
func (adms *AdminS) V1ComputeFilterIndexIDs(ctx *context.Context, args *utils.ArgsComputeFilterIndexIDs, reply *string) (err error) {
|
||||
transactionID := utils.NonTransactional
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var indexes utils.StringSet
|
||||
cacheIDs := make(map[string][]string)
|
||||
//ThresholdProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheThresholdFilterIndexes,
|
||||
&args.ThresholdIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
th, e := adms.dm.GetThresholdProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(th.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheThresholdFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//StatQueueProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheStatFilterIndexes,
|
||||
&args.StatIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
sq, e := adms.dm.GetStatQueueProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
cacheIDs[utils.CacheStatFilterIndexes] = []string{sq.ID}
|
||||
return utils.SliceStringPointer(slices.Clone(sq.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheStatFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//ResourceProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheResourceFilterIndexes,
|
||||
&args.ResourceIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rp, e := adms.dm.GetResourceProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
cacheIDs[utils.CacheResourceFilterIndexes] = []string{rp.ID}
|
||||
return utils.SliceStringPointer(slices.Clone(rp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheResourceFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//RouteProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheRouteFilterIndexes,
|
||||
&args.RouteIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rp, e := adms.dm.GetRouteProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
cacheIDs[utils.CacheRouteFilterIndexes] = []string{rp.ID}
|
||||
return utils.SliceStringPointer(slices.Clone(rp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheRouteFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//AttributeProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheAttributeFilterIndexes,
|
||||
&args.AttributeIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
attr, e := adms.dm.GetAttributeProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(attr.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheAttributeFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//ChargerProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheChargerFilterIndexes,
|
||||
&args.ChargerIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
ch, e := adms.dm.GetChargerProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(ch.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheChargerFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//AccountIndexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheAccountsFilterIndexes,
|
||||
&args.AccountIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
acc, e := adms.dm.GetAccount(ctx, tnt, id)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(acc.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheAccountsFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//ActionProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheActionProfilesFilterIndexes,
|
||||
&args.ActionProfileIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
act, e := adms.dm.GetActionProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(act.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheActionProfilesFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//RateProfile Indexes
|
||||
var ratePrf []string
|
||||
if _, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheRateProfilesFilterIndexes,
|
||||
&args.RateProfileIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
rpr, e := adms.dm.GetRateProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
ratePrf = append(ratePrf, utils.ConcatenatedKey(tnt, id))
|
||||
rtIds := make([]string, 0, len(rpr.Rates))
|
||||
for key := range rpr.Rates {
|
||||
rtIds = append(rtIds, key)
|
||||
}
|
||||
indexesRate, e := engine.ComputeIndexes(ctx, adms.dm, tnt, id, utils.CacheRateFilterIndexes,
|
||||
&rtIds, transactionID, func(_, id, _ string) (*[]string, error) {
|
||||
return utils.SliceStringPointer(slices.Clone(rpr.Rates[id].FilterIDs)), nil
|
||||
}, nil)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if indexesRate.Size() != 0 {
|
||||
cacheIDs[utils.CacheRateFilterIndexes] = indexesRate.AsSlice()
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(rpr.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheRateProfilesFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//DispatcherProfile Indexes
|
||||
if indexes, err = engine.ComputeIndexes(ctx, adms.dm, tnt, utils.EmptyString, utils.CacheDispatcherFilterIndexes,
|
||||
&args.DispatcherIDs, transactionID, func(tnt, id, grp string) (*[]string, error) {
|
||||
dsp, e := adms.dm.GetDispatcherProfile(ctx, tnt, id, true, false, utils.NonTransactional)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return utils.SliceStringPointer(slices.Clone(dsp.FilterIDs)), nil
|
||||
}, nil); err != nil && err != utils.ErrDSPProfileNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if indexes.Size() != 0 {
|
||||
cacheIDs[utils.CacheDispatcherFilterIndexes] = indexes.AsSlice()
|
||||
}
|
||||
//generate a load
|
||||
//ID for CacheFilterIndexes and store it in database
|
||||
|
||||
loadIDs := make(map[string]int64)
|
||||
timeNow := time.Now().UnixNano()
|
||||
for idx := range cacheIDs {
|
||||
loadIDs[idx] = timeNow
|
||||
}
|
||||
if err := adms.dm.SetLoadIDs(ctx, loadIDs); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := adms.callCacheForComputeIndexes(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]),
|
||||
args.Tenant, cacheIDs, args.APIOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetReverseFilterHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *map[string]*engine.ReverseFilterIHReply) (err error) {
|
||||
objCaches := map[string]*ltcache.Cache{utils.CacheRateFilterIndexes: ltcache.NewCache(-1, 0, false, nil)}
|
||||
for indxType := range utils.CacheIndexesToPrefix {
|
||||
objCaches[indxType] = ltcache.NewCache(-1, 0, false, nil)
|
||||
}
|
||||
|
||||
*reply, err = engine.GetRevFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
objCaches,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetThresholdsIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheThresholdFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetResourcesIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheResourceFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetStatsIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheStatFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetRoutesIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheRouteFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetAttributesIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheAttributeFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetChargersIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheChargerFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetDispatchersIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheDispatcherFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetRateProfilesIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheRateProfilesFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetActionsIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheActionProfilesFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetAccountsIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealth(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
utils.CacheAccountsFilterIndexes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adms *AdminS) V1GetRateRatesIndexesHealth(ctx *context.Context, args *engine.IndexHealthArgs, reply *engine.FilterIHReply) error {
|
||||
rp, err := engine.GetFltrIdxHealthForRateRates(ctx, adms.dm,
|
||||
ltcache.NewCache(args.FilterCacheLimit, args.FilterCacheTTL, args.FilterCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.IndexCacheLimit, args.IndexCacheTTL, args.IndexCacheStaticTTL, nil),
|
||||
ltcache.NewCache(args.ObjectCacheLimit, args.ObjectCacheTTL, args.ObjectCacheStaticTTL, nil),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = *rp
|
||||
return nil
|
||||
}
|
||||
210
admins/filters.go
Normal file
210
admins/filters.go
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func validateFilterRules(rules []*engine.FilterRule) error {
|
||||
for _, rule := range rules {
|
||||
if !rule.IsValid() {
|
||||
return fmt.Errorf("there exists at least one filter rule that is not valid")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFilter add a new Filter
|
||||
func (adms *AdminS) V1SetFilter(ctx *context.Context, arg *engine.FilterWithAPIOpts, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(arg.Filter, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if len(arg.Rules) == 0 {
|
||||
return utils.NewErrMandatoryIeMissing("Filter Rules")
|
||||
}
|
||||
if err = validateFilterRules(arg.Rules); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if arg.Tenant == utils.EmptyString {
|
||||
arg.Tenant = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
tntID := arg.TenantID()
|
||||
argC := map[string][]string{utils.CacheFilters: {tntID}}
|
||||
if fltr, err := adms.dm.GetFilter(ctx, arg.Filter.Tenant, arg.Filter.ID, true, false, utils.NonTransactional); err != nil {
|
||||
if err != utils.ErrNotFound {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
} else if argC, err = composeCacheArgsForFilter(adms.dm, ctx, fltr, fltr.Tenant, tntID, argC); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := adms.dm.SetFilter(ctx, arg.Filter, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if argC, err = composeCacheArgsForFilter(adms.dm, ctx, arg.Filter, arg.Filter.Tenant, tntID, argC); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheFilters and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx,
|
||||
map[string]int64{utils.CacheFilters: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for Filter
|
||||
if err := callCacheForFilter(adms.connMgr, adms.cfg.AdminSCfg().CachesConns, ctx,
|
||||
utils.IfaceAsString(arg.APIOpts[utils.MetaCache]),
|
||||
adms.cfg.GeneralCfg().DefaultCaching,
|
||||
arg.Tenant, argC, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return
|
||||
}
|
||||
|
||||
// GetFilter returns a Filter
|
||||
func (adms *AdminS) V1GetFilter(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.Filter) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if fltr, err := adms.dm.GetFilter(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
} else {
|
||||
*reply = *fltr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFilters returns a list of filters for a tenant
|
||||
func (adms *AdminS) V1GetFilters(ctx *context.Context, args *utils.ArgsItemIDs, fltrs *[]*engine.Filter) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var fltrIDs []string
|
||||
if err = adms.V1GetFilterIDs(ctx, args, &fltrIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*fltrs = make([]*engine.Filter, 0, len(fltrIDs))
|
||||
for _, fltrID := range fltrIDs {
|
||||
var fltr *engine.Filter
|
||||
if fltr, err = adms.dm.GetFilter(ctx, tnt, fltrID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*fltrs = append(*fltrs, fltr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetFilterIDs returns list of Filter IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetFilterIDs(ctx *context.Context, args *utils.ArgsItemIDs, fltrIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.FilterPrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*fltrIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveFilter remove a specific filter
|
||||
func (adms *AdminS) V1RemoveFilter(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveFilter(ctx, tnt, arg.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheFilters and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheFilters: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for Filter
|
||||
if err := callCacheForFilter(adms.connMgr, adms.cfg.AdminSCfg().CachesConns, ctx,
|
||||
utils.IfaceAsString(arg.APIOpts[utils.MetaCache]),
|
||||
adms.cfg.GeneralCfg().DefaultCaching,
|
||||
arg.Tenant, map[string][]string{utils.CacheFilters: {utils.ConcatenatedKey(tnt, arg.ID)}}, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFiltersCount returns the total number of FilterIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 FilterIDs
|
||||
func (admS *AdminS) V1GetFiltersCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.FilterPrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// FiltersMatch checks whether a set of filter IDs passes for the provided CGREvent
|
||||
func (admS *AdminS) V1FiltersMatch(ctx *context.Context, args *engine.ArgsFiltersMatch, reply *bool) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
evDP := args.CGREvent.AsDataProvider()
|
||||
var pass bool
|
||||
if pass, err = admS.fltrS.Pass(ctx, tnt, args.FilterIDs, evDP); err != nil {
|
||||
return
|
||||
} else if pass {
|
||||
*reply = true
|
||||
}
|
||||
return
|
||||
}
|
||||
307
admins/libadmin.go
Normal file
307
admins/libadmin.go
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// CallCache caching the item based on CacheOpt
|
||||
func (admS *AdminS) CallCache(ctx *context.Context, cacheopt string, tnt, cacheID, itemID, groupID string,
|
||||
filters *[]string, opts map[string]any) (err error) {
|
||||
var reply, method string
|
||||
var args any
|
||||
switch utils.FirstNonEmpty(cacheopt, admS.cfg.GeneralCfg().DefaultCaching) {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaReload:
|
||||
method = utils.CacheSv1ReloadCache
|
||||
var argCache map[string][]string
|
||||
if argCache, err = admS.composeArgsReload(ctx, tnt, cacheID, itemID, filters); err != nil {
|
||||
return
|
||||
}
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(argCache, tnt, opts)
|
||||
case utils.MetaLoad:
|
||||
method = utils.CacheSv1LoadCache
|
||||
var argCache map[string][]string
|
||||
if argCache, err = admS.composeArgsReload(ctx, tnt, cacheID, itemID, filters); err != nil {
|
||||
return
|
||||
}
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(argCache, tnt, opts)
|
||||
case utils.MetaRemove:
|
||||
if groupID != utils.EmptyString {
|
||||
method = utils.CacheSv1RemoveGroup
|
||||
args = &utils.ArgsGetGroupWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
APIOpts: opts,
|
||||
ArgsGetGroup: utils.ArgsGetGroup{
|
||||
CacheID: cacheID,
|
||||
GroupID: groupID,
|
||||
},
|
||||
}
|
||||
break
|
||||
}
|
||||
method = utils.CacheSv1RemoveItems
|
||||
var argCache map[string][]string
|
||||
if argCache, err = admS.composeArgsReload(ctx, tnt, cacheID, itemID, filters); err != nil {
|
||||
return
|
||||
}
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(argCache, tnt, opts)
|
||||
case utils.MetaClear:
|
||||
cacheIDs := make([]string, 1, 3)
|
||||
cacheIDs[0] = cacheID
|
||||
// do not send a EmptyString if the item doesn't have indexes
|
||||
if cIdx, has := utils.CacheInstanceToCacheIndex[cacheID]; has {
|
||||
cacheIDs = append(cacheIDs, cIdx)
|
||||
}
|
||||
switch cacheID { // add the items to the cache reload
|
||||
case utils.CacheThresholdProfiles:
|
||||
cacheIDs = append(cacheIDs, utils.CacheThresholds)
|
||||
case utils.CacheResourceProfiles:
|
||||
cacheIDs = append(cacheIDs, utils.CacheResources)
|
||||
case utils.CacheStatQueueProfiles:
|
||||
cacheIDs = append(cacheIDs, utils.CacheStatQueues)
|
||||
}
|
||||
method = utils.CacheSv1Clear
|
||||
args = &utils.AttrCacheIDsWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
CacheIDs: cacheIDs,
|
||||
APIOpts: opts,
|
||||
}
|
||||
|
||||
}
|
||||
return admS.connMgr.Call(ctx, admS.cfg.AdminSCfg().CachesConns,
|
||||
method, args, &reply)
|
||||
}
|
||||
|
||||
// composeArgsReload add the ItemID to AttrReloadCache
|
||||
// for a specific CacheID
|
||||
func (admS *AdminS) composeArgsReload(ctx *context.Context, tnt, cacheID, itemID string, filterIDs *[]string) (argCache map[string][]string, err error) {
|
||||
argCache = map[string][]string{cacheID: {itemID}}
|
||||
switch cacheID { // add the items to the cache reload
|
||||
case utils.CacheThresholdProfiles:
|
||||
argCache[utils.CacheThresholds] = []string{itemID}
|
||||
case utils.CacheResourceProfiles:
|
||||
argCache[utils.CacheResources] = []string{itemID}
|
||||
case utils.CacheStatQueueProfiles:
|
||||
argCache[utils.CacheStatQueues] = []string{itemID}
|
||||
}
|
||||
if filterIDs == nil { // in case we remove a profile we do not need to reload the indexes
|
||||
return
|
||||
}
|
||||
// populate the indexes
|
||||
idxCacheID := utils.CacheInstanceToCacheIndex[cacheID]
|
||||
if len(*filterIDs) == 0 { // in case we do not have any filters reload the *none filter indexes
|
||||
indxID := utils.ConcatenatedKey(utils.MetaNone, utils.MetaAny, utils.MetaAny)
|
||||
argCache[idxCacheID] = []string{utils.ConcatenatedKey(tnt, indxID)}
|
||||
return
|
||||
}
|
||||
indxIDs := make([]string, 0, len(*filterIDs))
|
||||
for _, id := range *filterIDs {
|
||||
var fltr *engine.Filter
|
||||
if fltr, err = admS.dm.GetFilter(ctx, tnt, id, true, true, utils.NonTransactional); err != nil {
|
||||
return
|
||||
}
|
||||
for _, flt := range fltr.Rules {
|
||||
if !engine.FilterIndexTypes.Has(flt.Type) ||
|
||||
engine.IsDynamicDPPath(flt.Element) {
|
||||
continue
|
||||
}
|
||||
isDyn := strings.HasPrefix(flt.Element, utils.DynamicDataPrefix)
|
||||
for _, fldVal := range flt.Values {
|
||||
if engine.IsDynamicDPPath(fldVal) {
|
||||
continue
|
||||
}
|
||||
if isDyn {
|
||||
if !strings.HasPrefix(fldVal, utils.DynamicDataPrefix) {
|
||||
indxIDs = append(indxIDs, utils.ConcatenatedKey(flt.Type, flt.Element[1:], fldVal))
|
||||
}
|
||||
} else if strings.HasPrefix(fldVal, utils.DynamicDataPrefix) {
|
||||
indxIDs = append(indxIDs, utils.ConcatenatedKey(flt.Type, fldVal[1:], flt.Element))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
argCache[idxCacheID] = make([]string, len(indxIDs))
|
||||
for i, indxID := range indxIDs {
|
||||
argCache[idxCacheID][i] = utils.ConcatenatedKey(tnt, indxID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// callCacheForIndexes will only call CacheClear because don't have access at ItemID
|
||||
func (admS *AdminS) callCacheForRemoveIndexes(ctx *context.Context, cacheopt string, tnt, cacheID string,
|
||||
itemIDs []string, opts map[string]any) (err error) {
|
||||
var reply, method string
|
||||
var args any = utils.NewAttrReloadCacheWithOptsFromMap(map[string][]string{cacheID: itemIDs}, tnt, opts)
|
||||
switch utils.FirstNonEmpty(cacheopt, admS.cfg.GeneralCfg().DefaultCaching) {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaReload:
|
||||
method = utils.CacheSv1ReloadCache
|
||||
case utils.MetaLoad:
|
||||
method = utils.CacheSv1LoadCache
|
||||
case utils.MetaRemove:
|
||||
method = utils.CacheSv1RemoveItems
|
||||
case utils.MetaClear:
|
||||
method = utils.CacheSv1Clear
|
||||
args = &utils.AttrCacheIDsWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
CacheIDs: []string{cacheID},
|
||||
APIOpts: opts,
|
||||
}
|
||||
}
|
||||
return admS.connMgr.Call(ctx, admS.cfg.AdminSCfg().CachesConns,
|
||||
method, args, &reply)
|
||||
}
|
||||
|
||||
func (admS *AdminS) callCacheForComputeIndexes(ctx *context.Context, cacheopt, tnt string,
|
||||
cacheItems map[string][]string, opts map[string]any) (err error) {
|
||||
var reply, method string
|
||||
var args any = utils.NewAttrReloadCacheWithOptsFromMap(cacheItems, tnt, opts)
|
||||
switch utils.FirstNonEmpty(cacheopt, admS.cfg.GeneralCfg().DefaultCaching) {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaReload:
|
||||
method = utils.CacheSv1ReloadCache
|
||||
case utils.MetaLoad:
|
||||
method = utils.CacheSv1LoadCache
|
||||
case utils.MetaRemove:
|
||||
method = utils.CacheSv1RemoveItems
|
||||
case utils.MetaClear:
|
||||
method = utils.CacheSv1Clear
|
||||
cacheIDs := make([]string, 0, len(cacheItems))
|
||||
for idx := range cacheItems {
|
||||
cacheIDs = append(cacheIDs, idx)
|
||||
}
|
||||
args = &utils.AttrCacheIDsWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
CacheIDs: cacheIDs,
|
||||
APIOpts: opts,
|
||||
}
|
||||
}
|
||||
return admS.connMgr.Call(ctx, admS.cfg.AdminSCfg().CachesConns,
|
||||
method, args, &reply)
|
||||
}
|
||||
|
||||
// callCacheRevDestinations used for reverse destination, loadIDs and indexes replication
|
||||
func (admS *AdminS) callCacheMultiple(ctx *context.Context, cacheopt, tnt, cacheID string, itemIDs []string, opts map[string]any) (err error) {
|
||||
if len(itemIDs) == 0 {
|
||||
return
|
||||
}
|
||||
var reply, method string
|
||||
var args any
|
||||
switch utils.FirstNonEmpty(cacheopt, admS.cfg.GeneralCfg().DefaultCaching) {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaReload:
|
||||
method = utils.CacheSv1ReloadCache
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(map[string][]string{cacheID: itemIDs}, tnt, opts)
|
||||
case utils.MetaLoad:
|
||||
method = utils.CacheSv1LoadCache
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(map[string][]string{cacheID: itemIDs}, tnt, opts)
|
||||
case utils.MetaRemove:
|
||||
method = utils.CacheSv1RemoveItems
|
||||
args = utils.NewAttrReloadCacheWithOptsFromMap(map[string][]string{cacheID: itemIDs}, tnt, opts)
|
||||
case utils.MetaClear:
|
||||
method = utils.CacheSv1Clear
|
||||
args = &utils.AttrCacheIDsWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
CacheIDs: []string{cacheID},
|
||||
APIOpts: opts,
|
||||
}
|
||||
}
|
||||
return admS.connMgr.Call(ctx, admS.cfg.AdminSCfg().CachesConns,
|
||||
method, args, &reply)
|
||||
}
|
||||
|
||||
func composeCacheArgsForFilter(dm *engine.DataManager, ctx *context.Context, fltr *engine.Filter, tnt, tntID string, args map[string][]string) (_ map[string][]string, err error) {
|
||||
indxIDs := make([]string, 0, len(fltr.Rules))
|
||||
for _, flt := range fltr.Rules {
|
||||
if !engine.FilterIndexTypes.Has(flt.Type) ||
|
||||
engine.IsDynamicDPPath(flt.Element) {
|
||||
continue
|
||||
}
|
||||
isDyn := strings.HasPrefix(flt.Element, utils.DynamicDataPrefix)
|
||||
for _, fldVal := range flt.Values {
|
||||
if engine.IsDynamicDPPath(fldVal) {
|
||||
continue
|
||||
}
|
||||
if isDyn {
|
||||
if !strings.HasPrefix(fldVal, utils.DynamicDataPrefix) {
|
||||
indxIDs = append(indxIDs, utils.ConcatenatedKey(flt.Type, flt.Element[1:], fldVal))
|
||||
}
|
||||
} else if strings.HasPrefix(fldVal, utils.DynamicDataPrefix) {
|
||||
indxIDs = append(indxIDs, utils.ConcatenatedKey(flt.Type, fldVal[1:], flt.Element))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(indxIDs) == 0 { // no index
|
||||
return args, nil
|
||||
}
|
||||
|
||||
var rcvIndx map[string]utils.StringSet
|
||||
if rcvIndx, err = dm.GetIndexes(ctx, utils.CacheReverseFilterIndexes, tntID,
|
||||
utils.EmptyString, utils.EmptyString, true, true); err != nil && err != utils.ErrNotFound { // error when geting the revers
|
||||
return
|
||||
}
|
||||
if err == utils.ErrNotFound || len(rcvIndx) == 0 { // no reverse index for this filter
|
||||
return args, nil
|
||||
}
|
||||
|
||||
for k := range rcvIndx {
|
||||
for _, indx := range indxIDs {
|
||||
args[k] = append(args[k], utils.ConcatenatedKey(tnt, indx))
|
||||
}
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// callCacheForFilter will call the cache for filter
|
||||
func callCacheForFilter(connMgr *engine.ConnManager, cacheConns []string, ctx *context.Context, cacheopt, dftCache, tnt string,
|
||||
argC map[string][]string, opts map[string]any) (err error) {
|
||||
var reply, method string
|
||||
var args any = utils.NewAttrReloadCacheWithOptsFromMap(argC, tnt, opts)
|
||||
switch utils.FirstNonEmpty(cacheopt, dftCache) {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaReload:
|
||||
method = utils.CacheSv1ReloadCache
|
||||
case utils.MetaLoad:
|
||||
method = utils.CacheSv1LoadCache
|
||||
case utils.MetaRemove:
|
||||
method = utils.CacheSv1RemoveItems
|
||||
case utils.MetaClear:
|
||||
cacheIDs := make([]string, 0, len(argC))
|
||||
for k := range argC {
|
||||
cacheIDs = append(cacheIDs, k)
|
||||
}
|
||||
method = utils.CacheSv1Clear
|
||||
args = &utils.AttrCacheIDsWithAPIOpts{
|
||||
Tenant: tnt,
|
||||
CacheIDs: cacheIDs,
|
||||
APIOpts: opts,
|
||||
}
|
||||
}
|
||||
return connMgr.Call(ctx, cacheConns, method, args, &reply)
|
||||
}
|
||||
292
admins/rates.go
Normal file
292
admins/rates.go
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetRateProfile returns a Rate Profile based on tenant and id
|
||||
func (admS *AdminS) V1GetRateProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *utils.RateProfile) (err error) {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var rPrf *utils.RateProfile
|
||||
rPrf, err = admS.dm.GetRateProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
if err.Error() != utils.ErrNotFound.Error() {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
rateIDs := make([]string, 0, len(rPrf.Rates))
|
||||
prefix := utils.IfaceAsString(arg.APIOpts[utils.ItemsPrefixOpt])
|
||||
for rateID := range rPrf.Rates {
|
||||
if strings.HasPrefix(rateID, prefix) {
|
||||
rateIDs = append(rateIDs, rateID)
|
||||
}
|
||||
}
|
||||
sort.Strings(rateIDs)
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(arg.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
rateIDs, err = utils.Paginate(rateIDs, limit, offset, maxItems)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
paginatedRatePrf := &utils.RateProfile{
|
||||
Tenant: rPrf.Tenant,
|
||||
ID: rPrf.ID,
|
||||
FilterIDs: rPrf.FilterIDs,
|
||||
Weights: rPrf.Weights,
|
||||
MinCost: rPrf.MinCost,
|
||||
MaxCost: rPrf.MaxCost,
|
||||
MaxCostStrategy: rPrf.MaxCostStrategy,
|
||||
}
|
||||
paginatedRatePrf.Rates = make(map[string]*utils.Rate)
|
||||
for _, rateID := range rateIDs {
|
||||
paginatedRatePrf.Rates[rateID] = rPrf.Rates[rateID].Clone()
|
||||
}
|
||||
*reply = *paginatedRatePrf
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfile returns the rates of a profile based on their profile. Those rates will be returned back by matching a prefix.
|
||||
func (admS *AdminS) V1GetRateProfileRates(ctx *context.Context, args *utils.ArgsSubItemIDs, reply *[]*utils.Rate) (err error) {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ProfileID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
_, rates, err := admS.dm.GetRateProfileRates(ctx, args, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(rates) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = rates
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfileIDs returns a list of rate profile IDs registered for a tenant
|
||||
func (admS *AdminS) V1GetRateProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, ratePrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.RateProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*ratePrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfileRateIDs returns a list of rates from a specific RateProfile registered for a tenant. RateIDs are returned back by matching a pattern given by ItemPrefix. If the ItemPrefix is not there, it will be returned all RateIDs.
|
||||
func (admS *AdminS) V1GetRateProfileRateIDs(ctx *context.Context, args *utils.ArgsSubItemIDs, rateIDs *[]string) (err error) {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ProfileID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var ids []string
|
||||
ids, _, err = admS.dm.GetRateProfileRates(ctx, args, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*rateIDs, err = utils.Paginate(ids, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfiles returns a list of rate profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetRateProfiles(ctx *context.Context, args *utils.ArgsItemIDs, ratePrfs *[]*utils.RateProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var ratePrfIDs []string
|
||||
if err = admS.V1GetRateProfileIDs(ctx, args, &ratePrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*ratePrfs = make([]*utils.RateProfile, 0, len(ratePrfIDs))
|
||||
for _, ratePrfID := range ratePrfIDs {
|
||||
var ratePrf *utils.RateProfile
|
||||
ratePrf, err = admS.dm.GetRateProfile(ctx, tnt, ratePrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*ratePrfs = append(*ratePrfs, ratePrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfilesCount returns the total number of RateProfileIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 RateProfileIDs
|
||||
func (admS *AdminS) V1GetRateProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.RateProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// GetRateProfileRatesCount count the rates from a specific RateProfile registered for a tenant. The number of rates is returned back by matching a pattern given by ItemPrefix. If the ItemPrefix is not there, it will be counted all the rates.
|
||||
func (admS *AdminS) V1GetRateProfileRatesCount(ctx *context.Context, args *utils.ArgsSubItemIDs, countIDs *int) (err error) {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ProfileID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
|
||||
var ids []string
|
||||
ids, _, err = admS.dm.GetRateProfileRates(ctx, args, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*countIDs = len(ids)
|
||||
return
|
||||
}
|
||||
|
||||
// SetRateProfile add/update a new Rate Profile
|
||||
func (admS *AdminS) V1SetRateProfile(ctx *context.Context, args *utils.APIRateProfile, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ID, utils.Rates}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
// check if we want to overwrite our profile already existing in database
|
||||
var optOverwrite bool
|
||||
if _, has := args.APIOpts[utils.MetaRateSOverwrite]; has {
|
||||
optOverwrite, err = utils.IfaceAsBool(args.APIOpts[utils.MetaRateSOverwrite])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := admS.dm.SetRateProfile(ctx, args.RateProfile, optOverwrite, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheRateProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheRateProfiles,
|
||||
args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRateProfileRates removes the rates from the Rate Profile
|
||||
func (admS *AdminS) V1RemoveRateProfileRates(ctx *context.Context, args *utils.RemoveRPrfRates, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveRateProfileRates(ctx, tnt, args.ID, &args.RateIDs, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheRateProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), tnt, utils.CacheRateProfiles,
|
||||
utils.ConcatenatedKey(tnt, args.ID), utils.EmptyString, nil, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRateProfile remove a specific Rate Profile specified by tenant and id
|
||||
func (admS *AdminS) V1RemoveRateProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := admS.dm.RemoveRateProfile(ctx, tnt, arg.ID,
|
||||
true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheAttributeProfiles and store it in database
|
||||
if err := admS.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
if err := admS.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheRateProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
168
admins/resources.go
Normal file
168
admins/resources.go
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetResourceProfile returns a resource configuration
|
||||
func (adms *AdminS) V1GetResourceProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.ResourceProfile) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if rcfg, err := adms.dm.GetResourceProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
} else {
|
||||
*reply = *rcfg
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetResourceProfileIDs returns list of resourceProfile IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetResourceProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, rsPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ResourceProfilesPrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*rsPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetResourceProfiles returns a list of resource profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetResourceProfiles(ctx *context.Context, args *utils.ArgsItemIDs, rsPrfs *[]*engine.ResourceProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var rsPrfIDs []string
|
||||
if err = admS.V1GetResourceProfileIDs(ctx, args, &rsPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*rsPrfs = make([]*engine.ResourceProfile, 0, len(rsPrfIDs))
|
||||
for _, rsPrfID := range rsPrfIDs {
|
||||
var rsPrf *engine.ResourceProfile
|
||||
rsPrf, err = admS.dm.GetResourceProfile(ctx, tnt, rsPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*rsPrfs = append(*rsPrfs, rsPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetResourceProfilesCount returns the total number of ResourceProfileIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 ResourceProfileIDs
|
||||
func (admS *AdminS) V1GetResourceProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ResourceProfilesPrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetResourceProfile adds a new resource configuration
|
||||
func (adms *AdminS) V1SetResourceProfile(ctx *context.Context, arg *engine.ResourceProfileWithAPIOpts, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(arg.ResourceProfile, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if arg.Tenant == utils.EmptyString {
|
||||
arg.Tenant = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err = adms.dm.SetResourceProfile(ctx, arg.ResourceProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheResourceProfiles and CacheResources and store it in database
|
||||
//make 1 insert for both ResourceProfile and Resources instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err = adms.dm.SetLoadIDs(ctx,
|
||||
map[string]int64{utils.CacheResourceProfiles: loadID,
|
||||
utils.CacheResources: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ResourceProfile
|
||||
if err = adms.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), arg.Tenant, utils.CacheResourceProfiles,
|
||||
arg.TenantID(), utils.EmptyString, &arg.FilterIDs, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveResourceProfile remove a specific resource configuration
|
||||
func (adms *AdminS) V1RemoveResourceProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveResourceProfile(ctx, tnt, arg.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ResourceProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), tnt, utils.CacheResourceProfiles,
|
||||
utils.ConcatenatedKey(tnt, arg.ID), utils.EmptyString, nil, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheResourceProfiles and CacheResources and store it in database
|
||||
//make 1 insert for both ResourceProfile and Resources instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheResourceProfiles: loadID, utils.CacheResources: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
165
admins/routes.go
Normal file
165
admins/routes.go
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetRouteProfile returns a Route configuration
|
||||
func (adms *AdminS) V1GetRouteProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.RouteProfile) error {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if rp, err := adms.dm.GetRouteProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
} else {
|
||||
*reply = *rp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRouteProfileIDs returns list of routeProfile IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetRouteProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, routeProfileIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.RouteProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*routeProfileIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetRouteProfiles returns a list of route profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetRouteProfiles(ctx *context.Context, args *utils.ArgsItemIDs, rouPrfs *[]*engine.RouteProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var rouPrfIDs []string
|
||||
if err = admS.V1GetRouteProfileIDs(ctx, args, &rouPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*rouPrfs = make([]*engine.RouteProfile, 0, len(rouPrfIDs))
|
||||
for _, rouPrfID := range rouPrfIDs {
|
||||
var rouPrf *engine.RouteProfile
|
||||
rouPrf, err = admS.dm.GetRouteProfile(ctx, tnt, rouPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*rouPrfs = append(*rouPrfs, rouPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetRouteProfilesCount sets in reply var the total number of RouteProfileIDs registered for the received tenant
|
||||
// returns ErrNotFound in case of 0 RouteProfileIDs
|
||||
func (adms *AdminS) V1GetRouteProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.RouteProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetRouteProfile add a new Route configuration
|
||||
func (adms *AdminS) V1SetRouteProfile(ctx *context.Context, args *engine.RouteProfileWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args.RouteProfile, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if args.Tenant == utils.EmptyString {
|
||||
args.Tenant = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if len(args.Routes) == 0 {
|
||||
return utils.NewErrMandatoryIeMissing("Routes")
|
||||
}
|
||||
if err := adms.dm.SetRouteProfile(ctx, args.RouteProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheRouteProfiles and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheRouteProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for SupplierProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheRouteProfiles,
|
||||
args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRouteProfile remove a specific Route configuration
|
||||
func (adms *AdminS) V1RemoveRouteProfile(ctx *context.Context, args *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveRouteProfile(ctx, tnt, args.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheRouteProfiles and store it in database
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheRouteProfiles: time.Now().UnixNano()}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for SupplierProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), tnt, utils.CacheRouteProfiles,
|
||||
utils.ConcatenatedKey(tnt, args.ID), utils.EmptyString, nil, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
166
admins/stats.go
Normal file
166
admins/stats.go
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetStatQueueProfile returns a StatQueue profile
|
||||
func (adms *AdminS) V1GetStatQueueProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.StatQueueProfile) (err error) {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
sCfg, err := adms.dm.GetStatQueueProfile(ctx, tnt, arg.ID,
|
||||
true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = *sCfg
|
||||
return
|
||||
}
|
||||
|
||||
// GetStatQueueProfileIDs returns list of statQueueProfile IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetStatQueueProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, stsPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.StatQueueProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*stsPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetStatQueueProfiles returns a list of stats profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetStatQueueProfiles(ctx *context.Context, args *utils.ArgsItemIDs, sqPrfs *[]*engine.StatQueueProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var sqPrfIDs []string
|
||||
if err = admS.V1GetStatQueueProfileIDs(ctx, args, &sqPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*sqPrfs = make([]*engine.StatQueueProfile, 0, len(sqPrfIDs))
|
||||
for _, sqPrfID := range sqPrfIDs {
|
||||
var sqPrf *engine.StatQueueProfile
|
||||
sqPrf, err = admS.dm.GetStatQueueProfile(ctx, tnt, sqPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*sqPrfs = append(*sqPrfs, sqPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetStatQueueProfilesCount returns the total number of StatQueueProfileIDs registered for a tenant
|
||||
// returns ErrNotFound in case of 0 StatQueueProfileIDs
|
||||
func (admS *AdminS) V1GetStatQueueProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.StatQueueProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = admS.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetStatQueueProfile alters/creates a StatQueueProfile
|
||||
func (adms *AdminS) V1SetStatQueueProfile(ctx *context.Context, arg *engine.StatQueueProfileWithAPIOpts, reply *string) (err error) {
|
||||
if missing := utils.MissingStructFields(arg.StatQueueProfile, []string{utils.ID}); len(missing) != 0 {
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
if arg.Tenant == utils.EmptyString {
|
||||
arg.Tenant = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err = adms.dm.SetStatQueueProfile(ctx, arg.StatQueueProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheStatQueueProfiles and CacheStatQueues and store it in database
|
||||
//make 1 insert for both StatQueueProfile and StatQueue instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err = adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheStatQueueProfiles: loadID, utils.CacheStatQueues: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for StatQueueProfile
|
||||
if err = adms.CallCache(ctx, utils.IfaceAsString(arg.APIOpts[utils.MetaCache]), arg.Tenant, utils.CacheStatQueueProfiles,
|
||||
arg.TenantID(), utils.EmptyString, &arg.FilterIDs, arg.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveStatQueueProfile remove a specific stat configuration
|
||||
func (adms *AdminS) V1RemoveStatQueueProfile(ctx *context.Context, args *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveStatQueueProfile(ctx, tnt, args.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for StatQueueProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), tnt, utils.CacheStatQueueProfiles,
|
||||
utils.ConcatenatedKey(tnt, args.ID), utils.EmptyString, nil, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheStatQueueProfiles and CacheStatQueues and store it in database
|
||||
//make 1 insert for both StatQueueProfile and StatQueue instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheStatQueueProfiles: loadID, utils.CacheStatQueues: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
166
admins/thresholds.go
Normal file
166
admins/thresholds.go
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
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 admins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// GetThresholdProfile returns a Threshold Profile
|
||||
func (adms *AdminS) V1GetThresholdProfile(ctx *context.Context, arg *utils.TenantIDWithAPIOpts, reply *engine.ThresholdProfile) (err error) {
|
||||
if missing := utils.MissingStructFields(arg, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := arg.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
th, err := adms.dm.GetThresholdProfile(ctx, tnt, arg.ID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = *th
|
||||
return
|
||||
}
|
||||
|
||||
// GetThresholdProfileIDs returns list of thresholdProfile IDs registered for a tenant
|
||||
func (adms *AdminS) V1GetThresholdProfileIDs(ctx *context.Context, args *utils.ArgsItemIDs, thPrfIDs *[]string) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ThresholdProfilePrefix + tnt + utils.ConcatenatedKeySep
|
||||
lenPrfx := len(prfx)
|
||||
prfx += args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
retIDs := make([]string, len(keys))
|
||||
for i, key := range keys {
|
||||
retIDs[i] = key[lenPrfx:]
|
||||
}
|
||||
var limit, offset, maxItems int
|
||||
if limit, offset, maxItems, err = utils.GetPaginateOpts(args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
*thPrfIDs, err = utils.Paginate(retIDs, limit, offset, maxItems)
|
||||
return
|
||||
}
|
||||
|
||||
// GetThresholdProfiles returns a list of threshold profiles registered for a tenant
|
||||
func (admS *AdminS) V1GetThresholdProfiles(ctx *context.Context, args *utils.ArgsItemIDs, thdPrfs *[]*engine.ThresholdProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = admS.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
var thdPrfIDs []string
|
||||
if err = admS.V1GetThresholdProfileIDs(ctx, args, &thdPrfIDs); err != nil {
|
||||
return
|
||||
}
|
||||
*thdPrfs = make([]*engine.ThresholdProfile, 0, len(thdPrfIDs))
|
||||
for _, thdPrfID := range thdPrfIDs {
|
||||
var thdPrf *engine.ThresholdProfile
|
||||
thdPrf, err = admS.dm.GetThresholdProfile(ctx, tnt, thdPrfID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*thdPrfs = append(*thdPrfs, thdPrf)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetThresholdProfilesCount sets in reply var the total number of ThresholdProfileIDs registered for the received tenant
|
||||
// returns ErrNotFound in case of 0 ThresholdProfileIDs
|
||||
func (adms *AdminS) V1GetThresholdProfilesCount(ctx *context.Context, args *utils.ArgsItemIDs, reply *int) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
prfx := utils.ThresholdProfilePrefix + tnt + utils.ConcatenatedKeySep + args.ItemsPrefix
|
||||
var keys []string
|
||||
if keys, err = adms.dm.DataDB().GetKeysForPrefix(ctx, prfx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return utils.ErrNotFound
|
||||
}
|
||||
*reply = len(keys)
|
||||
return
|
||||
}
|
||||
|
||||
// SetThresholdProfile alters/creates a ThresholdProfile
|
||||
func (adms *AdminS) V1SetThresholdProfile(ctx *context.Context, args *engine.ThresholdProfileWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args.ThresholdProfile, []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.SetThresholdProfile(ctx, args.ThresholdProfile, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheThresholdProfiles and CacheThresholds and store it in database
|
||||
//make 1 insert for both ThresholdProfile and Threshold instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheThresholdProfiles: loadID, utils.CacheThresholds: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ThresholdProfile and Threshold
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), args.Tenant, utils.CacheThresholdProfiles,
|
||||
args.TenantID(), utils.EmptyString, &args.FilterIDs, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveThresholdProfile removes a specific Threshold Profile
|
||||
func (adms *AdminS) V1RemoveThresholdProfile(ctx *context.Context, args *utils.TenantIDWithAPIOpts, reply *string) error {
|
||||
if missing := utils.MissingStructFields(args, []string{utils.ID}); len(missing) != 0 { //Params missing
|
||||
return utils.NewErrMandatoryIeMissing(missing...)
|
||||
}
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = adms.cfg.GeneralCfg().DefaultTenant
|
||||
}
|
||||
if err := adms.dm.RemoveThresholdProfile(ctx, tnt, args.ID, true); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//handle caching for ThresholdProfile
|
||||
if err := adms.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]), tnt, utils.CacheThresholdProfiles,
|
||||
utils.ConcatenatedKey(tnt, args.ID), utils.EmptyString, nil, args.APIOpts); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
//generate a loadID for CacheThresholdProfiles and CacheThresholds and store it in database
|
||||
//make 1 insert for both ThresholdProfile and Threshold instead of 2
|
||||
loadID := time.Now().UnixNano()
|
||||
if err := adms.dm.SetLoadIDs(ctx, map[string]int64{utils.CacheThresholdProfiles: loadID, utils.CacheThresholds: loadID}); err != nil {
|
||||
return utils.APIErrorHandler(err)
|
||||
}
|
||||
*reply = utils.OK
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user