Aliases now with multi-tenant support, ApierV1.GetRatingSubjectAliases, ApierV1.GetAccountAliases RPC commands implementation

This commit is contained in:
DanB
2014-05-11 21:48:51 +02:00
parent 6ffdb1633f
commit 79d654c2a0
12 changed files with 187 additions and 13 deletions

View File

@@ -1458,6 +1458,32 @@ func TestLocalRemDC(t *testing.T) {
}
}
func TestLocalGetRatingSubjectAliases(t *testing.T) {
if !*testLocal {
return
}
attrs := utils.AttrGetRatingSubjectAliases{Tenant: "cgrates.org", Subject: "1001"}
var subjAliases []string
if err := rater.Call("ApierV1.GetRatingSubjectAliases", attrs, &subjAliases); err != nil {
t.Error("Unexpected error", err.Error())
} else if len(subjAliases) != 0 {
t.Error("Unexpected subject aliases returned", subjAliases)
}
}
func TestLocalAccountAliases(t *testing.T) {
if !*testLocal {
return
}
attrs := utils.AttrGetAccountAliases{Tenant: "cgrates.org", Account: "1001"}
var acntAliases []string
if err := rater.Call("ApierV1.GetAccountAliases", attrs, &acntAliases); err != nil {
t.Error("Unexpected error", err.Error())
} else if len(acntAliases) != 0 {
t.Error("Unexpected subject aliases returned", acntAliases)
}
}
// Simply kill the engine after we are done with tests within this file
func TestStopEngine(t *testing.T) {
if !*testLocal {

View File

@@ -277,7 +277,7 @@ func (cd *CallDescriptor) addRatingInfos(ris RatingInfos) bool {
// The prefixLen is limiting the length of the destination prefix.
func (cd *CallDescriptor) GetKey(subject string) string {
// check if subject is alias
if rs, err := cache2go.GetCached(RP_ALIAS_PREFIX + subject); err == nil {
if rs, err := cache2go.GetCached(RP_ALIAS_PREFIX + utils.RatingProfileAliasKey(cd.Tenant,subject)); err == nil {
realSubject := rs.(string)
subject = realSubject
cd.Subject = realSubject
@@ -290,7 +290,7 @@ func (cd *CallDescriptor) GetAccountKey() string {
subj := cd.Subject
if cd.Account != "" {
// check if subject is alias
if realSubject, err := cache2go.GetCached(ACC_ALIAS_PREFIX + subj); err == nil {
if realSubject, err := cache2go.GetCached(ACC_ALIAS_PREFIX + utils.AccountAliasKey(cd.Tenant,subj)); err == nil {
cd.Account = realSubject.(string)
}
subj = cd.Account

View File

@@ -518,7 +518,7 @@ func (csvr *CSVReader) LoadRatingProfiles() (err error) {
if len(aliases) > 1 {
subject = aliases[0]
for _, alias := range aliases[1:] {
csvr.rpAliases[alias] = subject
csvr.rpAliases[utils.RatingProfileAliasKey(tenant, alias)] = subject
}
}
key := fmt.Sprintf("%s:%s:%s:%s", direction, tenant, tor, subject)
@@ -796,7 +796,7 @@ func (csvr *CSVReader) LoadAccountActions() (err error) {
if len(aliases) > 1 {
account = aliases[0]
for _, alias := range aliases[1:] {
csvr.accAliases[alias] = account
csvr.accAliases[utils.AccountAliasKey(tenant, alias)] = account
}
}
tag := fmt.Sprintf("%s:%s:%s", direction, tenant, account)

View File

@@ -911,9 +911,9 @@ func TestLoadRpAliases(t *testing.T) {
if len(csvr.rpAliases) != 3 {
t.Error("Failed to load rp aliases: ", csvr.rpAliases)
}
if csvr.rpAliases["a1"] != "minu" ||
csvr.rpAliases["a2"] != "minu" ||
csvr.rpAliases["a3"] != "minu" {
if csvr.rpAliases[utils.RatingProfileAliasKey("vdf", "a1")] != "minu" ||
csvr.rpAliases[utils.RatingProfileAliasKey("vdf", "a2")] != "minu" ||
csvr.rpAliases[utils.RatingProfileAliasKey("vdf", "a3")] != "minu" {
t.Error("Error loading rp aliases: ", csvr.rpAliases)
}
}
@@ -922,8 +922,8 @@ func TestLoadAccAliases(t *testing.T) {
if len(csvr.accAliases) != 2 {
t.Error("Failed to load acc aliases: ", csvr.accAliases)
}
if csvr.accAliases["a1"] != "minitsboy" ||
csvr.accAliases["a2"] != "minitsboy" {
if csvr.accAliases[utils.AccountAliasKey("vdf", "a1")] != "minitsboy" ||
csvr.accAliases[utils.AccountAliasKey("vdf", "a2")] != "minitsboy" {
t.Error("Error loading acc aliases: ", csvr.accAliases)
}
}

View File

@@ -348,7 +348,7 @@ func (dbr *DbReader) LoadRatingProfiles() error {
if len(aliases) > 1 {
tpRpf.Subject = aliases[0]
for _, alias := range aliases[1:] {
dbr.rpAliases[alias] = tpRpf.Subject
dbr.rpAliases[utils.RatingProfileAliasKey(tpRpf.Tenant, alias)] = tpRpf.Subject
}
}
rpf := &RatingProfile{Id: tpRpf.KeyId()}
@@ -584,7 +584,7 @@ func (dbr *DbReader) LoadAccountActions() (err error) {
if len(aliases) > 1 {
aa.Account = aliases[0]
for _, alias := range aliases[1:] {
dbr.accAliases[alias] = aa.Account
dbr.accAliases[utils.AccountAliasKey(aa.Tenant, alias)] = aa.Account
}
}
aTriggers, exists := dbr.actionsTriggers[aa.ActionTriggersId]

View File

@@ -80,6 +80,7 @@ type RatingStorage interface {
GetRpAlias(string, bool) (string, error)
SetRpAlias(string, string) error
RemoveRpAliases([]string) error
GetRPAliases(string, string) ([]string, error)
GetDestination(string) (*Destination, error)
SetDestination(*Destination) error
GetLCR(string, bool) (*LCR, error)
@@ -99,6 +100,7 @@ type AccountingStorage interface {
GetAccAlias(string, bool) (string, error)
SetAccAlias(string, string) error
RemoveAccAliases([]string) error
GetAccountAliases(string, string) ([]string, error)
GetActionTimings(string) (ActionPlan, error)
SetActionTimings(string, ActionPlan) error
GetAllActionTimings() (map[string]ActionPlan, error)

View File

@@ -288,6 +288,16 @@ func (ms *MapStorage) RemoveRpAliases(accounts []string) (err error) {
return
}
func (ms *MapStorage) GetRPAliases(tenant, subject string) (aliases []string, err error) {
for key, value := range ms.dict {
tenantPrfx := RP_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP
if strings.HasPrefix(key, RP_ALIAS_PREFIX) && len(key) >= len(tenantPrfx) && key[:len(tenantPrfx)] == tenantPrfx && subject == string(value) {
aliases = append(aliases, key[len(tenantPrfx):])
}
}
return aliases, nil
}
func (ms *MapStorage) GetAccAlias(key string, checkDb bool) (alias string, err error) {
key = ACC_ALIAS_PREFIX + key
if x, err := cache2go.GetCached(key); err == nil {
@@ -320,6 +330,16 @@ func (ms *MapStorage) RemoveAccAliases(accounts []string) (err error) {
return
}
func (ms *MapStorage) GetAccountAliases(tenant, account string) (aliases []string, err error) {
for key, value := range ms.dict {
tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP
if strings.HasPrefix(key, ACC_ALIAS_PREFIX) && len(key) >= len(tenantPrfx) && key[:len(tenantPrfx)] == tenantPrfx && account == string(value) {
aliases = append(aliases, key[len(tenantPrfx):])
}
}
return aliases, nil
}
func (ms *MapStorage) GetDestination(key string) (dest *Destination, err error) {
key = DESTINATION_PREFIX + key
if values, ok := ms.dict[key]; ok {

View File

@@ -343,6 +343,7 @@ func (rs *RedisStorage) SetRpAlias(key, alias string) (err error) {
return
}
// Returns the aliases of one specific rating profile subject on a tenant
func (rs *RedisStorage) RemoveRpAliases(accounts []string) (err error) {
if alsKeys, err := rs.db.Keys(RP_ALIAS_PREFIX + "*"); err != nil {
return err
@@ -363,6 +364,26 @@ func (rs *RedisStorage) RemoveRpAliases(accounts []string) (err error) {
return
}
func (rs *RedisStorage) GetRPAliases(tenant, subject string) (aliases []string, err error) {
alsKeys, err := rs.db.Keys(RP_ALIAS_PREFIX + "*")
if err != nil {
return nil, err
}
for _, key := range alsKeys {
tenantPrfx := RP_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP
if len(key) < len(tenantPrfx) || tenantPrfx != key[:len(tenantPrfx)] { // filter out the tenant for accounts
continue
}
if alsSubj, err := rs.GetRpAlias(key[len(ACC_ALIAS_PREFIX):], true); err != nil {
return nil, err
} else if alsSubj == subject {
alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant
aliases = append(aliases, alsFromKey)
}
}
return aliases, nil
}
func (rs *RedisStorage) GetLCR(key string, checkDb bool) (lcr *LCR, err error) {
key = LCR_PREFIX + key
if x, err := cache2go.GetCached(key); err == nil {
@@ -402,6 +423,7 @@ func (rs *RedisStorage) GetAccAlias(key string, checkDb bool) (alias string, err
return
}
// Adds one alias for one account
func (rs *RedisStorage) SetAccAlias(key, alias string) (err error) {
err = rs.db.Set(ACC_ALIAS_PREFIX+key, []byte(alias))
//cache2go.Cache(ALIAS_PREFIX+key, alias)
@@ -428,6 +450,27 @@ func (rs *RedisStorage) RemoveAccAliases(accounts []string) (err error) {
return
}
// Returns the aliases of one specific account on a tenant
func (rs *RedisStorage) GetAccountAliases(tenant, account string) (aliases []string, err error) {
alsKeys, err := rs.db.Keys(ACC_ALIAS_PREFIX + "*")
if err != nil {
return nil, err
}
for _, key := range alsKeys {
tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP
if len(key) < len(tenantPrfx) || tenantPrfx != key[:len(tenantPrfx)] { // filter out the tenant for accounts
continue
}
if alsAcnt, err := rs.GetAccAlias(key[len(ACC_ALIAS_PREFIX):], true); err != nil {
return nil, err
} else if alsAcnt == account {
alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant
aliases = append(aliases, alsFromKey)
}
}
return aliases, nil
}
func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error) {
key = DESTINATION_PREFIX + key
var values []byte

View File

@@ -19,10 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"reflect"
"sort"
"testing"
"time"
"github.com/cgrates/cgrates/cache2go"
"github.com/cgrates/cgrates/utils"
)
func TestMsgpackStructsAdded(t *testing.T) {
@@ -110,7 +113,7 @@ func TestCacheRefresh(t *testing.T) {
}
func TestCacheAliases(t *testing.T) {
if subj, err := cache2go.GetCached(RP_ALIAS_PREFIX + "a3"); err != nil || subj != "minu" {
if subj, err := cache2go.GetCached(RP_ALIAS_PREFIX + utils.RatingProfileAliasKey("vdf", "a3")); err != nil || subj != "minu" {
t.Error("Error caching alias: ", subj, err)
}
}
@@ -125,6 +128,52 @@ func TestStoreInterfaces(t *testing.T) {
var _ LogStorage = sql
}
func TestGetRPAliases(t *testing.T) {
if err := dataStorage.SetRpAlias(utils.RatingProfileAliasKey("cgrates.org", "2001"), "1001"); err != nil {
t.Error(err)
}
if err := dataStorage.SetRpAlias(utils.RatingProfileAliasKey("cgrates.org", "2002"), "1001"); err != nil {
t.Error(err)
}
if err := dataStorage.SetRpAlias(utils.RatingProfileAliasKey("itsyscom.com", "2003"), "1001"); err != nil {
t.Error(err)
}
expectAliases := sort.StringSlice([]string{"2001", "2002"})
expectAliases.Sort()
if aliases, err := dataStorage.GetRPAliases("cgrates.org", "1001"); err != nil {
t.Error(err)
} else {
aliases := sort.StringSlice(aliases)
aliases.Sort()
if !reflect.DeepEqual(aliases, expectAliases) {
t.Errorf("Expecting: %v, received: %v", expectAliases, aliases)
}
}
}
func TestGetAccountAliases(t *testing.T) {
if err := accountingStorage.SetAccAlias(utils.AccountAliasKey("cgrates.org", "2001"), "1001"); err != nil {
t.Error(err)
}
if err := accountingStorage.SetAccAlias(utils.AccountAliasKey("cgrates.org", "2002"), "1001"); err != nil {
t.Error(err)
}
if err := accountingStorage.SetAccAlias(utils.AccountAliasKey("itsyscom.com", "2003"), "1001"); err != nil {
t.Error(err)
}
expectAliases := sort.StringSlice([]string{"2001", "2002"})
expectAliases.Sort()
if aliases, err := accountingStorage.GetAccountAliases("cgrates.org", "1001"); err != nil {
t.Error(err)
} else {
aliases := sort.StringSlice(aliases)
aliases.Sort()
if !reflect.DeepEqual(aliases, expectAliases) {
t.Errorf("Expecting: %v, received: %v", expectAliases, aliases)
}
}
}
/************************** Benchmarks *****************************/
func GetUB() *Account {

View File

@@ -8,5 +8,5 @@ The Debian packaging is:
Copyright (C) 2011 Canonical Ltd.
Further development:
Copyright (C) 2014 ITsysCOM
Copyright (C) 2014 ITsysCOM GmbH

View File

@@ -384,3 +384,29 @@ type AttrGetDestination struct {
type AttrDerivedChargers struct {
Direction, Tenant, Category, Account, Subject string
}
type AttrGetRatingSubjectAliases struct {
Tenant, Subject string
}
type AttrRemRatingSubjectAliases struct {
Tenant, Subject string
}
type AttrAddRatingSubjectAliases struct {
Tenant, Subject string
Aliases []string
}
type AttrGetAccountAliases struct {
Tenant, Account string
}
type AttrRemAccountAliases struct {
Tenant, Account string
}
type AttrAddAccountAliases struct {
Tenant, Account string
Aliases []string
}

View File

@@ -234,3 +234,11 @@ func ConcatenatedKey(keyVals ...string) string {
}
return resKey
}
func RatingProfileAliasKey(tenant, subject string) string {
return ConcatenatedKey(tenant, subject)
}
func AccountAliasKey(tenant, account string) string {
return ConcatenatedKey(tenant, account)
}