mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Make Attribute Profiles storable in MySQL and Postgres
This commit is contained in:
committed by
Dan Christian Bogos
parent
eda80242eb
commit
38a02535f0
@@ -109,11 +109,11 @@ func TestAttributesIT(t *testing.T) {
|
||||
case utils.MetaMongo:
|
||||
attrConfigDIR = "attributes_mongo"
|
||||
case utils.MetaRedis:
|
||||
t.SkipNow()
|
||||
attrConfigDIR = "attributes_redis"
|
||||
case utils.MetaMySQL:
|
||||
attrConfigDIR = "attributes_mysql"
|
||||
case utils.MetaPostgres:
|
||||
t.SkipNow()
|
||||
attrConfigDIR = "attributes_postgres"
|
||||
default:
|
||||
t.Fatal("Unknown Database type")
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ const CGRATES_CFG_JSON = `
|
||||
"*action_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*versions": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*charger_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
|
||||
// compatible db types: <*internal|*redis|*mongo>
|
||||
"*actions": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
@@ -143,7 +144,6 @@ const CGRATES_CFG_JSON = `
|
||||
"*thresholds": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*filters": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*route_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*rate_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*load_ids": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "*default"},
|
||||
"*resource_filter_indexes" : {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate": false, "dbConn": "*default"},
|
||||
|
||||
@@ -1026,6 +1026,14 @@ func (cfg *CGRConfig) checkConfigSanity() error {
|
||||
|
||||
// DataDB sanity checks
|
||||
hasOneInternalDB := false // used to reutrn error in case more then 1 internaldb is found
|
||||
allDBsItems := []string{
|
||||
utils.MetaAccounts,
|
||||
utils.MetaIPProfiles,
|
||||
utils.MetaIPAllocations,
|
||||
utils.MetaActionProfiles,
|
||||
utils.MetaChargerProfiles,
|
||||
utils.MetaAttributeProfiles,
|
||||
}
|
||||
for _, dbcfg := range cfg.dbCfg.DBConns {
|
||||
if dbcfg.Type == utils.MetaInternal {
|
||||
if hasOneInternalDB {
|
||||
@@ -1060,9 +1068,7 @@ func (cfg *CGRConfig) checkConfigSanity() error {
|
||||
dataDBTypes := []string{utils.MetaInternal, utils.MetaRedis, utils.MetaMongo,
|
||||
utils.Internal, utils.Redis, utils.Mongo}
|
||||
|
||||
if item != utils.MetaAccounts && item != utils.MetaIPProfiles &&
|
||||
item != utils.MetaIPAllocations && item != utils.MetaActionProfiles &&
|
||||
item != utils.MetaChargerProfiles {
|
||||
if !slices.Contains(allDBsItems, item) {
|
||||
if item == utils.MetaCDRs {
|
||||
if !slices.Contains(storDBTypes, cfg.dbCfg.DBConns[val.DBConn].Type) {
|
||||
return fmt.Errorf("<%s> db item can only be of types <%v>, got <%s>", item,
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
"loaders": [
|
||||
|
||||
148
data/conf/samples/attr_test_postgres/cgrates.json
Normal file
148
data/conf/samples/attr_test_postgres/cgrates.json
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
//
|
||||
|
||||
|
||||
"general": {
|
||||
"reply_timeout": "50s",
|
||||
},
|
||||
|
||||
"logger": {
|
||||
"level": 7
|
||||
},
|
||||
|
||||
"listen": {
|
||||
"rpc_json": ":2012",
|
||||
"rpc_gob": ":2013",
|
||||
"http": ":2080",
|
||||
},
|
||||
|
||||
"db": {
|
||||
"db_conns": {
|
||||
"*default": {
|
||||
"db_type": "redis",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 6379,
|
||||
"db_name": "10",
|
||||
"db_user": "cgrates"
|
||||
},
|
||||
"StorDB": {
|
||||
"db_type": "postgres",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 5432,
|
||||
"db_name": "cgrates",
|
||||
"db_user": "cgrates",
|
||||
"db_password": "CGRateS.org"
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
"loaders": [
|
||||
{
|
||||
"id": "*default",
|
||||
"enabled": true,
|
||||
"tenant": "cgrates.org",
|
||||
"lockfile_path": ".cgr.lck",
|
||||
"tp_in_dir": "/usr/share/cgrates/tariffplans/testit",
|
||||
"tp_out_dir": "",
|
||||
},
|
||||
],
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true,
|
||||
"chargers_conns":["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"stats_conns": ["*localhost"],
|
||||
"resources_conns": ["*localhost"],
|
||||
"accounts_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
|
||||
"chargers": {
|
||||
"enabled": true,
|
||||
"attributes_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"resources": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
"thresholds_conns": ["*internal"]
|
||||
},
|
||||
|
||||
|
||||
"stats": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
"thresholds_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"thresholds": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
},
|
||||
|
||||
|
||||
"routes": {
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields":["*req.Destination"],
|
||||
"stats_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"rates_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"sessions": {
|
||||
"enabled": true,
|
||||
"routes_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"attributes_conns": ["*internal"],
|
||||
"rates_conns": ["*internal"],
|
||||
"cdrs_conns": ["*internal"],
|
||||
"chargers_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"migrator":{
|
||||
"users_filters":["Account"],
|
||||
},
|
||||
|
||||
|
||||
"admins": {
|
||||
"enabled": true,
|
||||
},
|
||||
|
||||
|
||||
"rates": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
|
||||
"actions": {
|
||||
"enabled": true,
|
||||
"accounts_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
|
||||
"accounts": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
|
||||
"filters": {
|
||||
"stats_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"accounts_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
|
||||
147
data/conf/samples/attr_test_redis/cgrates.json
Normal file
147
data/conf/samples/attr_test_redis/cgrates.json
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
//
|
||||
|
||||
|
||||
"general": {
|
||||
"reply_timeout": "50s",
|
||||
},
|
||||
|
||||
"logger": {
|
||||
"level": 7
|
||||
},
|
||||
|
||||
"listen": {
|
||||
"rpc_json": ":2012",
|
||||
"rpc_gob": ":2013",
|
||||
"http": ":2080",
|
||||
},
|
||||
|
||||
"db": {
|
||||
"db_conns": {
|
||||
"*default": {
|
||||
"db_type": "redis",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 6379,
|
||||
"db_name": "10",
|
||||
"db_user": "cgrates"
|
||||
},
|
||||
"StorDB": {
|
||||
"db_type": "mysql",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 3306,
|
||||
"db_name": "cgrates",
|
||||
"db_user": "cgrates",
|
||||
"db_password": "CGRateS.org"
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
"loaders": [
|
||||
{
|
||||
"id": "*default",
|
||||
"enabled": true,
|
||||
"tenant": "cgrates.org",
|
||||
"lockfile_path": ".cgr.lck",
|
||||
"tp_in_dir": "/usr/share/cgrates/tariffplans/testit",
|
||||
"tp_out_dir": "",
|
||||
},
|
||||
],
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true,
|
||||
"chargers_conns":["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"stats_conns": ["*localhost"],
|
||||
"resources_conns": ["*localhost"],
|
||||
"accounts_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
|
||||
"chargers": {
|
||||
"enabled": true,
|
||||
"attributes_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"resources": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
"thresholds_conns": ["*internal"]
|
||||
},
|
||||
|
||||
|
||||
"stats": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
"thresholds_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"thresholds": {
|
||||
"enabled": true,
|
||||
"store_interval": "1s",
|
||||
},
|
||||
|
||||
|
||||
"routes": {
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields":["*req.Destination"],
|
||||
"stats_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"rates_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"sessions": {
|
||||
"enabled": true,
|
||||
"routes_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"attributes_conns": ["*internal"],
|
||||
"rates_conns": ["*internal"],
|
||||
"cdrs_conns": ["*internal"],
|
||||
"chargers_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
"migrator":{
|
||||
"users_filters":["Account"],
|
||||
},
|
||||
|
||||
|
||||
"admins": {
|
||||
"enabled": true,
|
||||
},
|
||||
|
||||
|
||||
"rates": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
|
||||
"actions": {
|
||||
"enabled": true,
|
||||
"accounts_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
|
||||
"accounts": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
|
||||
"filters": {
|
||||
"stats_conns": ["*internal"],
|
||||
"resources_conns": ["*internal"],
|
||||
"accounts_conns": ["*internal"],
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false,
|
||||
"replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields": ["*req.Destination"],
|
||||
"exists_indexed_fields": ["*opts.*usage"],
|
||||
"notexists_indexed_fields": ["*req.ToR"],
|
||||
|
||||
45
data/conf/samples/attributes_postgres/cgrates.json
Normal file
45
data/conf/samples/attributes_postgres/cgrates.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
// will be used in apis/attributes_it_test.go
|
||||
|
||||
"logger": {
|
||||
"level": 7
|
||||
},
|
||||
|
||||
"db": {
|
||||
"db_conns": {
|
||||
"*default": {
|
||||
"db_type": "redis",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 6379,
|
||||
"db_name": "10",
|
||||
"db_user": "cgrates"
|
||||
},
|
||||
"StorDB": { // The id of the DB connection
|
||||
"db_type": "postgres", // db type: <internal|redis|mysql|mongo|postgres>
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 5432, // db port to reach the database
|
||||
"db_name": "cgrates", // the host to connect to
|
||||
"db_user": "cgrates",
|
||||
"db_password": "CGRateS.org" // password to use when connecting to the database
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"},
|
||||
"*attribute_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false,
|
||||
"replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields": ["*req.Destination"],
|
||||
"exists_indexed_fields": ["*opts.*usage"],
|
||||
"notexists_indexed_fields": ["*req.ToR"],
|
||||
},
|
||||
|
||||
"admins": {
|
||||
"enabled": true,
|
||||
}
|
||||
|
||||
}
|
||||
43
data/conf/samples/attributes_redis/cgrates.json
Normal file
43
data/conf/samples/attributes_redis/cgrates.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
// will be used in apis/attributes_it_test.go
|
||||
|
||||
"logger": {
|
||||
"level": 7
|
||||
},
|
||||
|
||||
"db": {
|
||||
"db_conns": {
|
||||
"*default": {
|
||||
"db_type": "redis",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 6379,
|
||||
"db_name": "10",
|
||||
"db_user": "cgrates"
|
||||
},
|
||||
"StorDB": {
|
||||
"db_type": "mysql",
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 3306,
|
||||
"db_name": "cgrates",
|
||||
"db_user": "cgrates",
|
||||
"db_password": "CGRateS.org"
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"*cdrs": {"limit": -1, "ttl": "", "static_ttl": false, "remote":false, "replicate":false, "dbConn": "StorDB"}
|
||||
}
|
||||
},
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"prefix_indexed_fields": ["*req.Destination"],
|
||||
"exists_indexed_fields": ["*opts.*usage"],
|
||||
"notexists_indexed_fields": ["*req.ToR"],
|
||||
},
|
||||
|
||||
"admins": {
|
||||
"enabled": true,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,4 +55,15 @@ CREATE TABLE charger_profiles (
|
||||
PRIMARY KEY (`pk`),
|
||||
UNIQUE KEY unique_tenant_id (`tenant`, `id`)
|
||||
);
|
||||
CREATE UNIQUE INDEX charger_profiles_idx ON charger_profiles (`id`);
|
||||
CREATE UNIQUE INDEX charger_profiles_idx ON charger_profiles (`id`);
|
||||
|
||||
DROP TABLE IF EXISTS attribute_profiles;
|
||||
CREATE TABLE attribute_profiles (
|
||||
`pk` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tenant` VARCHAR(40) NOT NULL,
|
||||
`id` VARCHAR(64) NOT NULL,
|
||||
`attribute_profile` JSON NOT NULL,
|
||||
PRIMARY KEY (`pk`),
|
||||
UNIQUE KEY unique_tenant_id (`tenant`, `id`)
|
||||
);
|
||||
CREATE UNIQUE INDEX attribute_profiles_idx ON attribute_profiles (`id`);
|
||||
@@ -54,3 +54,14 @@ CREATE TABLE charger_profiles (
|
||||
UNIQUE (tenant, id)
|
||||
);
|
||||
CREATE UNIQUE INDEX charger_profiles_idx ON charger_profiles ("id");
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS attribute_profiles;
|
||||
CREATE TABLE attribute_profiles (
|
||||
pk SERIAL PRIMARY KEY,
|
||||
tenant VARCHAR(40) NOT NULL,
|
||||
id VARCHAR(64) NOT NULL,
|
||||
attribute_profile JSONB NOT NULL,
|
||||
UNIQUE (tenant, id)
|
||||
);
|
||||
CREATE UNIQUE INDEX attribute_profiles_idx ON attribute_profiles ("id");
|
||||
|
||||
@@ -424,7 +424,7 @@ type ActionProfileJSONMdl struct {
|
||||
}
|
||||
|
||||
func (ActionProfileJSONMdl) TableName() string {
|
||||
return utils.TBLActionProfilesJSON
|
||||
return utils.TBLActionProfiles
|
||||
}
|
||||
|
||||
type ChargerProfileMdl struct {
|
||||
@@ -435,5 +435,16 @@ type ChargerProfileMdl struct {
|
||||
}
|
||||
|
||||
func (ChargerProfileMdl) TableName() string {
|
||||
return utils.TBLChargerProfilesJSON
|
||||
return utils.TBLChargerProfiles
|
||||
}
|
||||
|
||||
type AttributeProfileMdl struct {
|
||||
PK uint `gorm:"primary_key"`
|
||||
Tenant string `index:"0" re:".*"`
|
||||
ID string `index:"1" re:".*"`
|
||||
AttributeProfile utils.JSONB `gorm:"type:jsonb" index:"2" re:".*"`
|
||||
}
|
||||
|
||||
func (AttributeProfileMdl) TableName() string {
|
||||
return utils.TBLAttributeProfiles
|
||||
}
|
||||
|
||||
@@ -105,9 +105,11 @@ func (sqls *SQLStorage) GetKeysForPrefix(ctx *context.Context, prefix string) (k
|
||||
case utils.IPAllocationsPrefix:
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLIPAllocations, tntID)
|
||||
case utils.ActionProfilePrefix:
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLActionProfilesJSON, tntID)
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLActionProfiles, tntID)
|
||||
case utils.ChargerProfilePrefix:
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLChargerProfilesJSON, tntID)
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLChargerProfiles, tntID)
|
||||
case utils.AttributeProfilePrefix:
|
||||
keys, err = sqls.getAllKeysMatchingTenantID(ctx, utils.TBLAttributeProfiles, tntID)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported prefix in GetKeysForPrefix: %q", prefix)
|
||||
}
|
||||
@@ -616,6 +618,51 @@ func (sqls *SQLStorage) RemoveChargerProfileDrv(_ *context.Context, tenant, id s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sqls *SQLStorage) GetAttributeProfileDrv(ctx *context.Context, tenant, id string) (ap *utils.AttributeProfile, err error) {
|
||||
var result []*AttributeProfileMdl
|
||||
if err := sqls.db.Model(&AttributeProfileMdl{}).Where(&AttributeProfileMdl{Tenant: tenant,
|
||||
ID: id}).Find(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(result) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
|
||||
return utils.MapStringInterfaceToAttributeProfile(result[0].AttributeProfile)
|
||||
}
|
||||
|
||||
func (sqls *SQLStorage) SetAttributeProfileDrv(ctx *context.Context, ap *utils.AttributeProfile) (err error) {
|
||||
tx := sqls.db.Begin()
|
||||
mdl := &AttributeProfileMdl{
|
||||
Tenant: ap.Tenant,
|
||||
ID: ap.ID,
|
||||
AttributeProfile: ap.AsMapStringInterface(),
|
||||
}
|
||||
if err = tx.Model(&AttributeProfileMdl{}).Where(
|
||||
AttributeProfileMdl{Tenant: mdl.Tenant, ID: mdl.ID}).Delete(
|
||||
AttributeProfileMdl{}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
if err = tx.Save(mdl).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
func (sqls *SQLStorage) RemoveAttributeProfileDrv(ctx *context.Context, tenant, id string) (err error) {
|
||||
tx := sqls.db.Begin()
|
||||
if err = tx.Model(&AttributeProfileMdl{}).Where(&AttributeProfileMdl{Tenant: tenant, ID: id}).
|
||||
Delete(&AttributeProfileMdl{}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
// AddLoadHistory DataDB method not implemented yet
|
||||
func (sqls *SQLStorage) AddLoadHistory(ldInst *utils.LoadInstance,
|
||||
loadHistSize int, transactionID string) error {
|
||||
@@ -838,21 +885,6 @@ func (sqls *SQLStorage) RemoveRouteProfileDrv(ctx *context.Context, tenant, id s
|
||||
return utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// DataDB method not implemented yet
|
||||
func (sqls *SQLStorage) GetAttributeProfileDrv(ctx *context.Context, tenant, id string) (r *utils.AttributeProfile, err error) {
|
||||
return nil, utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// DataDB method not implemented yet
|
||||
func (sqls *SQLStorage) SetAttributeProfileDrv(ctx *context.Context, r *utils.AttributeProfile) (err error) {
|
||||
return utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// DataDB method not implemented yet
|
||||
func (sqls *SQLStorage) RemoveAttributeProfileDrv(ctx *context.Context, tenant, id string) (err error) {
|
||||
return utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// GetStorageType returns the storage type that is being used
|
||||
func (sqls *SQLStorage) GetStorageType() string {
|
||||
return utils.MetaMySQL
|
||||
|
||||
@@ -67,13 +67,13 @@ func TestAttributeSIT(t *testing.T) {
|
||||
case utils.MetaInternal:
|
||||
alsPrfConfigDIR = "attr_test_internal"
|
||||
case utils.MetaRedis:
|
||||
t.SkipNow()
|
||||
alsPrfConfigDIR = "attr_test_redis"
|
||||
case utils.MetaMySQL:
|
||||
alsPrfConfigDIR = "attr_test_mysql"
|
||||
case utils.MetaMongo:
|
||||
alsPrfConfigDIR = "attr_test_mongo"
|
||||
case utils.MetaPostgres:
|
||||
t.SkipNow()
|
||||
alsPrfConfigDIR = "attr_test_postgres"
|
||||
default:
|
||||
t.Fatal("Unknown Database type")
|
||||
}
|
||||
|
||||
@@ -415,3 +415,66 @@ func (ext *APIAttributeProfile) AsAttributeProfile() (attr *AttributeProfile, er
|
||||
attr.Weights = ext.Weights
|
||||
return
|
||||
}
|
||||
|
||||
// AsMapStringInterface converts AttributeProfile struct to map[string]any
|
||||
func (ap *AttributeProfile) AsMapStringInterface() map[string]any {
|
||||
if ap == nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]any{
|
||||
Tenant: ap.Tenant,
|
||||
ID: ap.ID,
|
||||
FilterIDs: ap.FilterIDs,
|
||||
Weights: ap.Weights,
|
||||
Blockers: ap.Blockers,
|
||||
Attributes: ap.Attributes,
|
||||
}
|
||||
}
|
||||
|
||||
// MapStringInterfaceToAttributeProfile converts map[string]any to AttributeProfile struct
|
||||
func MapStringInterfaceToAttributeProfile(m map[string]any) (ap *AttributeProfile, err error) {
|
||||
ap = &AttributeProfile{}
|
||||
if v, ok := m[Tenant].(string); ok {
|
||||
ap.Tenant = v
|
||||
}
|
||||
if v, ok := m[ID].(string); ok {
|
||||
ap.ID = v
|
||||
}
|
||||
ap.FilterIDs = InterfaceToStringSlice(m[FilterIDs])
|
||||
ap.Weights = InterfaceToDynamicWeights(m[Weights])
|
||||
ap.Blockers = InterfaceToDynamicBlockers(m[Blockers])
|
||||
ap.Attributes = InterfaceToAttributes(m[Attributes])
|
||||
return
|
||||
}
|
||||
|
||||
// InterfaceToAttributes converts interface{} to []*Attribute
|
||||
func InterfaceToAttributes(v any) []*Attribute {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
attrs, ok := v.([]any)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
attributes := make([]*Attribute, 0, len(attrs))
|
||||
for _, attrIface := range attrs {
|
||||
attrMap, ok := attrIface.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
attr := &Attribute{}
|
||||
attr.FilterIDs = InterfaceToStringSlice(attrMap[FilterIDs])
|
||||
attr.Blockers = InterfaceToDynamicBlockers(attrMap[Blockers])
|
||||
if path, ok := attrMap[Path].(string); ok {
|
||||
attr.Path = path
|
||||
}
|
||||
if typ, ok := attrMap[Type].(string); ok {
|
||||
attr.Type = typ
|
||||
}
|
||||
if valueIface, ok := attrMap[Value]; ok {
|
||||
attr.Value = InterfaceToRSRParsers(valueIface)
|
||||
}
|
||||
attributes = append(attributes, attr)
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
|
||||
@@ -1897,29 +1897,30 @@ const (
|
||||
|
||||
// Table Name
|
||||
const (
|
||||
TBLTPResources = "tp_resources"
|
||||
TBLTPStats = "tp_stats"
|
||||
TBLTPRankings = "tp_rankings"
|
||||
TBLTPTrends = "tp_trends"
|
||||
TBLTPThresholds = "tp_thresholds"
|
||||
TBLTPFilters = "tp_filters"
|
||||
SessionCostsTBL = "session_costs"
|
||||
CDRsTBL = "cdrs"
|
||||
TBLTPRoutes = "tp_routes"
|
||||
TBLTPAttributes = "tp_attributes"
|
||||
TBLTPChargers = "tp_chargers"
|
||||
TBLVersions = "versions"
|
||||
TBLAccounts = "accounts"
|
||||
TBLIPProfiles = "ip_profiles"
|
||||
TBLIPAllocations = "ip_allocations"
|
||||
TBLActionProfilesJSON = "action_profiles"
|
||||
TBLChargerProfilesJSON = "charger_profiles"
|
||||
OldSMCosts = "sm_costs"
|
||||
TBLTPDispatchers = "tp_dispatcher_profiles"
|
||||
TBLTPDispatcherHosts = "tp_dispatcher_hosts"
|
||||
TBLTPRateProfiles = "tp_rate_profiles"
|
||||
TBLTPActionProfiles = "tp_action_profiles"
|
||||
TBLTPAccounts = "tp_accounts"
|
||||
TBLTPResources = "tp_resources"
|
||||
TBLTPStats = "tp_stats"
|
||||
TBLTPRankings = "tp_rankings"
|
||||
TBLTPTrends = "tp_trends"
|
||||
TBLTPThresholds = "tp_thresholds"
|
||||
TBLTPFilters = "tp_filters"
|
||||
SessionCostsTBL = "session_costs"
|
||||
CDRsTBL = "cdrs"
|
||||
TBLTPRoutes = "tp_routes"
|
||||
TBLTPAttributes = "tp_attributes"
|
||||
TBLTPChargers = "tp_chargers"
|
||||
TBLVersions = "versions"
|
||||
TBLAccounts = "accounts"
|
||||
TBLIPProfiles = "ip_profiles"
|
||||
TBLIPAllocations = "ip_allocations"
|
||||
TBLActionProfiles = "action_profiles"
|
||||
TBLChargerProfiles = "charger_profiles"
|
||||
TBLAttributeProfiles = "attribute_profiles"
|
||||
OldSMCosts = "sm_costs"
|
||||
TBLTPDispatchers = "tp_dispatcher_profiles"
|
||||
TBLTPDispatcherHosts = "tp_dispatcher_hosts"
|
||||
TBLTPRateProfiles = "tp_rate_profiles"
|
||||
TBLTPActionProfiles = "tp_action_profiles"
|
||||
TBLTPAccounts = "tp_accounts"
|
||||
)
|
||||
|
||||
// Cache Name
|
||||
|
||||
@@ -214,6 +214,31 @@ func (prsrs RSRParsers) AsStringSlice() (v []string) {
|
||||
return
|
||||
}
|
||||
|
||||
// InterfaceToRSRParsers converts interface to RSRParsers (unexported fields not included)
|
||||
func InterfaceToRSRParsers(v any) RSRParsers {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
parsers := make(RSRParsers, 0)
|
||||
switch val := v.(type) {
|
||||
case []any:
|
||||
for _, item := range val {
|
||||
if parserMap, ok := item.(map[string]any); ok {
|
||||
parser := &RSRParser{}
|
||||
if rules, ok := parserMap[Rules].(string); ok {
|
||||
parser.Rules = rules
|
||||
}
|
||||
if path, ok := parserMap[Path].(string); ok {
|
||||
parser.Path = path
|
||||
}
|
||||
parsers = append(parsers, parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parsers
|
||||
}
|
||||
|
||||
// NewRSRParser builds one RSRParser
|
||||
func NewRSRParser(parserRules string) (rsrParser *RSRParser, err error) {
|
||||
if len(parserRules) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user