diff --git a/engine/storage_internal_datadb.go b/engine/storage_internal_datadb.go
index 81d25efb3..452d9b05f 100644
--- a/engine/storage_internal_datadb.go
+++ b/engine/storage_internal_datadb.go
@@ -652,14 +652,35 @@ func (iDB *InternalDB) RemoveAccountDrv(_ *context.Context, tenant, id string) (
return
}
-func (iDB *InternalDB) GetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (map[string][]byte, error) {
- return nil, utils.ErrNotImplemented
+func (iDB *InternalDB) GetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (sectionMap map[string][]byte, err error) {
+ sectionMap = make(map[string][]byte)
+ for _, sectionID := range sectionIDs {
+ x, ok := iDB.db.Get(utils.CacheConfig, utils.ConcatenatedKey(tenant, nodeID, sectionID))
+ if !ok || x == nil {
+ utils.Logger.Warning(fmt.Sprintf("<%+v> Could not find any data for section <%+v>",
+ utils.ConcatenatedKey(tenant, nodeID), sectionID))
+ continue
+ }
+ sectionMap[sectionID] = x.([]byte)
+ }
+ if len(sectionMap) == 0 {
+ err = utils.ErrNotFound
+ return
+ }
+ return
}
-func (iDB *InternalDB) SetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionsData map[string][]byte) error {
- return utils.ErrNotImplemented
+func (iDB *InternalDB) SetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionsData map[string][]byte) (err error) {
+ for sectionID, sectionData := range sectionsData {
+ iDB.db.Set(utils.CacheConfig, utils.ConcatenatedKey(tenant, nodeID, sectionID),
+ sectionData, nil, true, utils.NonTransactional)
+ }
+ return
}
-func (iDB *InternalDB) RemoveConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) error {
- return utils.ErrNotImplemented
+func (iDB *InternalDB) RemoveConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (err error) {
+ for _, sectionID := range sectionIDs {
+ iDB.db.Remove(utils.CacheConfig, utils.ConcatenatedKey(tenant, nodeID, sectionID), true, utils.NonTransactional)
+ }
+ return
}
diff --git a/engine/storage_it_test.go b/engine/storage_it_test.go
new file mode 100644
index 000000000..d1e2bad2f
--- /dev/null
+++ b/engine/storage_it_test.go
@@ -0,0 +1,391 @@
+//go:build integration
+// +build integration
+
+/*
+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
+*/
+
+package engine
+
+import (
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/cgrates/birpc/context"
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestSetGetRemoveConfigSectionsDrvRedis(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ db, err := NewRedisStorage(cfg.DataDbCfg().Host+":"+cfg.DataDbCfg().Port, 10, cfg.DataDbCfg().User,
+ cfg.DataDbCfg().Password, cfg.GeneralCfg().DBDataEncoding, utils.RedisMaxConns, utils.RedisMaxAttempts,
+ utils.EmptyString, false, 0, 0, false, utils.EmptyString, utils.EmptyString, utils.EmptyString)
+ if err != nil {
+ t.Error(err)
+ }
+ defer db.Close()
+ sectionIDs := []string{"thresholds", "resources"}
+ expected := make(map[string][]byte)
+
+ // Try to retrieve the values before setting them (should receive an empty map)
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+
+ ms, err := utils.NewMarshaler(utils.JSON)
+ if err != nil {
+ t.Error(err)
+ }
+ thCfg := &config.ThresholdSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"req.index11"},
+ Prefix_indexed_fields: &[]string{"req.index22"},
+ Suffix_indexed_fields: &[]string{"req.index33"},
+ Actions_conns: &[]string{"*internal"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ThresholdsOptsJson{
+ ProfileIDs: []*utils.DynamicStringSliceOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: []string{"value1"},
+ },
+ },
+ ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: true,
+ },
+ },
+ },
+ }
+ thJsnCfg, err := ms.Marshal(thCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ rsCfg := &config.ResourceSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Thresholds_conns: &[]string{"*birpc"},
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"*req.index11"},
+ Prefix_indexed_fields: &[]string{"*req.index22"},
+ Suffix_indexed_fields: &[]string{"*req.index33"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ResourcesOptsJson{
+ UsageID: []*utils.DynamicStringOpt{
+ {
+ Value: "usg2",
+ },
+ },
+ UsageTTL: []*utils.DynamicStringOpt{
+ {
+ Value: "1m0s",
+ },
+ },
+ Units: []*utils.DynamicFloat64Opt{
+ {
+ Value: 2,
+ },
+ },
+ },
+ }
+ rsJsnCfg, err := ms.Marshal(rsCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ sectData := map[string][]byte{
+ "thresholds": thJsnCfg,
+ "resources": rsJsnCfg,
+ }
+
+ if err := db.SetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectData); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(rcv, sectData) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(sectData), utils.ToJSON(rcv))
+ } else {
+ rcvThCfg := &config.ThresholdSJsonCfg{}
+ ms.Unmarshal(rcv["thresholds"], &rcvThCfg)
+ if !reflect.DeepEqual(rcvThCfg, thCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(thCfg), utils.ToJSON(rcvThCfg))
+ }
+ rcvRsCfg := &config.ResourceSJsonCfg{}
+ ms.Unmarshal(rcv["resources"], &rcvRsCfg)
+ if !reflect.DeepEqual(rcvRsCfg, rsCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(rsCfg), utils.ToJSON(rcvRsCfg))
+ }
+ }
+
+ if err := db.RemoveConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+}
+
+func TestSetGetRemoveConfigSectionsDrvMongo(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ db, err := NewMongoStorage(cfg.DataDbCfg().Host, "27017", "10", cfg.DataDbCfg().User,
+ cfg.DataDbCfg().Password, cfg.GeneralCfg().DBDataEncoding, utils.DataDB, nil, 10*time.Second)
+ if err != nil {
+ t.Error(err)
+ }
+ defer db.Close()
+ sectionIDs := []string{"thresholds", "resources"}
+ expected := make(map[string][]byte)
+
+ // Try to retrieve the values before setting them (should receive an empty map)
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+
+ ms, err := utils.NewMarshaler(utils.JSON)
+ if err != nil {
+ t.Error(err)
+ }
+ thCfg := &config.ThresholdSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"req.index11"},
+ Prefix_indexed_fields: &[]string{"req.index22"},
+ Suffix_indexed_fields: &[]string{"req.index33"},
+ Actions_conns: &[]string{"*internal"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ThresholdsOptsJson{
+ ProfileIDs: []*utils.DynamicStringSliceOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: []string{"value1"},
+ },
+ },
+ ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: true,
+ },
+ },
+ },
+ }
+ thJsnCfg, err := ms.Marshal(thCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ rsCfg := &config.ResourceSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Thresholds_conns: &[]string{"*birpc"},
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"*req.index11"},
+ Prefix_indexed_fields: &[]string{"*req.index22"},
+ Suffix_indexed_fields: &[]string{"*req.index33"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ResourcesOptsJson{
+ UsageID: []*utils.DynamicStringOpt{
+ {
+ Value: "usg2",
+ },
+ },
+ UsageTTL: []*utils.DynamicStringOpt{
+ {
+ Value: "1m0s",
+ },
+ },
+ Units: []*utils.DynamicFloat64Opt{
+ {
+ Value: 2,
+ },
+ },
+ },
+ }
+ rsJsnCfg, err := ms.Marshal(rsCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ sectData := map[string][]byte{
+ "thresholds": thJsnCfg,
+ "resources": rsJsnCfg,
+ }
+
+ if err := db.SetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectData); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(rcv, sectData) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(sectData), utils.ToJSON(rcv))
+ } else {
+ rcvThCfg := &config.ThresholdSJsonCfg{}
+ ms.Unmarshal(rcv["thresholds"], &rcvThCfg)
+ if !reflect.DeepEqual(rcvThCfg, thCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(thCfg), utils.ToJSON(rcvThCfg))
+ }
+ rcvRsCfg := &config.ResourceSJsonCfg{}
+ ms.Unmarshal(rcv["resources"], &rcvRsCfg)
+ if !reflect.DeepEqual(rcvRsCfg, rsCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(rsCfg), utils.ToJSON(rcvRsCfg))
+ }
+ }
+
+ if err := db.RemoveConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+}
+
+func TestSetGetRemoveConfigSectionsDrvInternal(t *testing.T) {
+ db := NewInternalDB(nil, nil, nil)
+ if err != nil {
+ t.Error(err)
+ }
+ defer db.Close()
+ sectionIDs := []string{"thresholds", "resources"}
+ expected := make(map[string][]byte)
+
+ // Try to retrieve the values before setting them (should receive an empty map)
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+
+ ms, err := utils.NewMarshaler(utils.JSON)
+ if err != nil {
+ t.Error(err)
+ }
+ thCfg := &config.ThresholdSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"req.index11"},
+ Prefix_indexed_fields: &[]string{"req.index22"},
+ Suffix_indexed_fields: &[]string{"req.index33"},
+ Actions_conns: &[]string{"*internal"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ThresholdsOptsJson{
+ ProfileIDs: []*utils.DynamicStringSliceOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: []string{"value1"},
+ },
+ },
+ ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
+ {
+ Tenant: "cgrates.org",
+ Value: true,
+ },
+ },
+ },
+ }
+ thJsnCfg, err := ms.Marshal(thCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ rsCfg := &config.ResourceSJsonCfg{
+ Enabled: utils.BoolPointer(true),
+ Indexed_selects: utils.BoolPointer(true),
+ Thresholds_conns: &[]string{"*birpc"},
+ Store_interval: utils.StringPointer("2s"),
+ String_indexed_fields: &[]string{"*req.index11"},
+ Prefix_indexed_fields: &[]string{"*req.index22"},
+ Suffix_indexed_fields: &[]string{"*req.index33"},
+ Nested_fields: utils.BoolPointer(true),
+ Opts: &config.ResourcesOptsJson{
+ UsageID: []*utils.DynamicStringOpt{
+ {
+ Value: "usg2",
+ },
+ },
+ UsageTTL: []*utils.DynamicStringOpt{
+ {
+ Value: "1m0s",
+ },
+ },
+ Units: []*utils.DynamicFloat64Opt{
+ {
+ Value: 2,
+ },
+ },
+ },
+ }
+ rsJsnCfg, err := ms.Marshal(rsCfg)
+ if err != nil {
+ t.Error(err)
+ }
+ sectData := map[string][]byte{
+ "thresholds": thJsnCfg,
+ "resources": rsJsnCfg,
+ }
+
+ if err := db.SetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectData); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(rcv, sectData) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(sectData), utils.ToJSON(rcv))
+ } else {
+ rcvThCfg := &config.ThresholdSJsonCfg{}
+ ms.Unmarshal(rcv["thresholds"], &rcvThCfg)
+ if !reflect.DeepEqual(rcvThCfg, thCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(thCfg), utils.ToJSON(rcvThCfg))
+ }
+ rcvRsCfg := &config.ResourceSJsonCfg{}
+ ms.Unmarshal(rcv["resources"], &rcvRsCfg)
+ if !reflect.DeepEqual(rcvRsCfg, rsCfg) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(rsCfg), utils.ToJSON(rcvRsCfg))
+ }
+ }
+
+ if err := db.RemoveConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
+ t.Error(err)
+ }
+
+ if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err == nil ||
+ err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
+ } else if !reflect.DeepEqual(rcv, expected) {
+ t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+}
diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go
index bef5e1d12..df19a4bfb 100644
--- a/engine/storage_mongo_datadb.go
+++ b/engine/storage_mongo_datadb.go
@@ -1497,16 +1497,72 @@ func (ms *MongoStorage) RemoveAccountDrv(ctx *context.Context, tenant, id string
})
}
-func (ms *MongoStorage) GetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (map[string][]byte, error) {
- return nil, utils.ErrNotImplemented
+func (ms *MongoStorage) GetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (sectionMap map[string][]byte, err error) {
+ sectionMap = make(map[string][]byte)
+ for _, sectionID := range sectionIDs {
+ if err = ms.query(context.TODO(), func(sctx mongo.SessionContext) (err error) {
+ cur := ms.getCol(ColCfg).FindOne(sctx, bson.M{
+ "tenant": tenant,
+ "nodeID": nodeID,
+ "section": sectionID,
+ }, options.FindOne().SetProjection(bson.M{"cfgData": 1, "_id": 0}))
+ cfgMap := make(map[string][]byte)
+ if err = cur.Decode(&cfgMap); err != nil {
+ if err == mongo.ErrNoDocuments {
+ err = nil
+ return
+ }
+ return
+ }
+ sectionMap[sectionID] = cfgMap["cfgData"]
+ return
+ }); err != nil {
+ return
+ }
+ }
+ if len(sectionMap) == 0 {
+ err = utils.ErrNotFound
+ return
+ }
+ return
}
-func (ms *MongoStorage) SetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionsData map[string][]byte) error {
- return utils.ErrNotImplemented
+func (ms *MongoStorage) SetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionsData map[string][]byte) (err error) {
+ for sectionID, sectionData := range sectionsData {
+ if err = ms.query(ctx, func(sctx mongo.SessionContext) (err error) {
+ _, err = ms.getCol(ColCfg).UpdateOne(sctx, bson.M{
+ "tenant": tenant,
+ "nodeID": nodeID,
+ "section": sectionID,
+ }, bson.M{"$set": bson.M{
+ "tenant": tenant,
+ "nodeID": nodeID,
+ "section": sectionID,
+ "cfgData": sectionData}},
+ options.Update().SetUpsert(true),
+ )
+ return err
+ }); err != nil {
+ return
+ }
+ }
+ return
}
-func (ms *MongoStorage) RemoveConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) error {
- return utils.ErrNotImplemented
+func (ms *MongoStorage) RemoveConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (err error) {
+ for _, sectionID := range sectionIDs {
+ if err = ms.query(ctx, func(sctx mongo.SessionContext) (err error) {
+ _, err = ms.getCol(ColCfg).DeleteOne(sctx, bson.M{
+ "tenant": tenant,
+ "nodeID": nodeID,
+ "section": sectionID,
+ })
+ return err
+ }); err != nil {
+ return
+ }
+ }
+ return
}
func newAggregateStages(profileID, tenant, prefix string) (match, query bson.D) {
diff --git a/engine/storage_redis.go b/engine/storage_redis.go
index 2321a0b99..ca06c129b 100644
--- a/engine/storage_redis.go
+++ b/engine/storage_redis.go
@@ -939,28 +939,30 @@ func (rs *RedisStorage) GetConfigSectionsDrv(ctx *context.Context, tenant, nodeI
sectionMap = make(map[string][]byte)
for _, sectionID := range sectionIDs {
var value []byte
- if err = rs.Cmd(&value, redisGET, utils.ConfigPrefix+sectionID); err != nil {
+ if err = rs.Cmd(&value, redisHGET, utils.ConfigPrefix+utils.ConcatenatedKey(tenant, nodeID), sectionID); err != nil {
return
}
if value != nil {
sectionMap[sectionID] = value
}
}
+ if len(sectionMap) == 0 {
+ err = utils.ErrNotFound
+ return
+ }
return
}
func (rs *RedisStorage) SetConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionsData map[string][]byte) (err error) {
- for sectionID, sectionData := range sectionsData {
- if err = rs.Cmd(nil, redisSET, utils.ConfigPrefix+sectionID, string(sectionData)); err != nil {
- return
- }
+ if err = rs.FlatCmd(nil, redisHSET, utils.ConfigPrefix+utils.ConcatenatedKey(tenant, nodeID), sectionsData); err != nil {
+ return
}
return
}
func (rs *RedisStorage) RemoveConfigSectionsDrv(ctx *context.Context, tenant, nodeID string, sectionIDs []string) (err error) {
for _, sectionID := range sectionIDs {
- if err = rs.Cmd(nil, redisDEL, utils.ConfigPrefix+sectionID); err != nil {
+ if err = rs.Cmd(nil, redisHDEL, utils.ConfigPrefix+utils.ConcatenatedKey(tenant, nodeID), sectionID); err != nil {
return
}
}
diff --git a/engine/storage_redis_it_test.go b/engine/storage_redis_it_test.go
deleted file mode 100644
index 13dc2b4dc..000000000
--- a/engine/storage_redis_it_test.go
+++ /dev/null
@@ -1,150 +0,0 @@
-//go:build integration
-// +build integration
-
-/*
-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
-*/
-
-package engine
-
-import (
- "reflect"
- "testing"
-
- "github.com/cgrates/birpc/context"
- "github.com/cgrates/cgrates/config"
- "github.com/cgrates/cgrates/utils"
-)
-
-func TestSetGetRemoveConfigSectionsDrv(t *testing.T) {
- cfg := config.NewDefaultCGRConfig()
- db, err := NewRedisStorage(cfg.DataDbCfg().Host+":"+cfg.DataDbCfg().Port, 10, cfg.DataDbCfg().User,
- cfg.DataDbCfg().Password, cfg.GeneralCfg().DBDataEncoding, utils.RedisMaxConns, utils.RedisMaxAttempts,
- utils.EmptyString, false, 0, 0, false, utils.EmptyString, utils.EmptyString, utils.EmptyString)
- if err != nil {
- t.Fatal(err)
- }
- defer db.Close()
- sectionIDs := []string{"thresholds", "resources"}
- expected := make(map[string][]byte)
-
- // Try to retrieve the values before setting them (should receive an empty map)
- if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
- t.Fatal(err)
- } else if !reflect.DeepEqual(rcv, expected) {
- t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
- }
-
- ms, err := utils.NewMarshaler(utils.JSON)
- if err != nil {
- t.Fatal(err)
- }
- thCfg := &config.ThresholdSJsonCfg{
- Enabled: utils.BoolPointer(true),
- Indexed_selects: utils.BoolPointer(true),
- Store_interval: utils.StringPointer("2s"),
- String_indexed_fields: &[]string{"req.index11"},
- Prefix_indexed_fields: &[]string{"req.index22"},
- Suffix_indexed_fields: &[]string{"req.index33"},
- Actions_conns: &[]string{"*internal"},
- Nested_fields: utils.BoolPointer(true),
- Opts: &config.ThresholdsOptsJson{
- ProfileIDs: []*utils.DynamicStringSliceOpt{
- {
- Tenant: "cgrates.org",
- Value: []string{"value1"},
- },
- },
- ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
- {
- Tenant: "cgrates.org",
- Value: true,
- },
- },
- },
- }
- thJsnCfg, err := ms.Marshal(thCfg)
- if err != nil {
- t.Fatal(err)
- }
- rsCfg := &config.ResourceSJsonCfg{
- Enabled: utils.BoolPointer(true),
- Indexed_selects: utils.BoolPointer(true),
- Thresholds_conns: &[]string{"*birpc"},
- Store_interval: utils.StringPointer("2s"),
- String_indexed_fields: &[]string{"*req.index11"},
- Prefix_indexed_fields: &[]string{"*req.index22"},
- Suffix_indexed_fields: &[]string{"*req.index33"},
- Nested_fields: utils.BoolPointer(true),
- Opts: &config.ResourcesOptsJson{
- UsageID: []*utils.DynamicStringOpt{
- {
- Value: "usg2",
- },
- },
- UsageTTL: []*utils.DynamicStringOpt{
- {
- Value: "1m0s",
- },
- },
- Units: []*utils.DynamicFloat64Opt{
- {
- Value: 2,
- },
- },
- },
- }
- rsJsnCfg, err := ms.Marshal(rsCfg)
- if err != nil {
- t.Fatal(err)
- }
- sectData := map[string][]byte{
- "thresholds": thJsnCfg,
- "resources": rsJsnCfg,
- }
-
- if err := db.SetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectData); err != nil {
- t.Fatal(err)
- }
-
- if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
- t.Fatal(err)
- } else if !reflect.DeepEqual(rcv, sectData) {
- t.Fatalf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(sectData), utils.ToJSON(rcv))
- } else {
- rcvThCfg := &config.ThresholdSJsonCfg{}
- ms.Unmarshal(rcv["thresholds"], &rcvThCfg)
- if !reflect.DeepEqual(rcvThCfg, thCfg) {
- t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(thCfg), utils.ToJSON(rcvThCfg))
- }
- rcvRsCfg := &config.ResourceSJsonCfg{}
- ms.Unmarshal(rcv["resources"], &rcvRsCfg)
- if !reflect.DeepEqual(rcvRsCfg, rsCfg) {
- t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(rsCfg), utils.ToJSON(rcvRsCfg))
- }
- }
-
- if err := db.RemoveConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
- t.Fatal(err)
- }
-
- if rcv, err := db.GetConfigSectionsDrv(context.Background(), "cgrates.org", "1234", sectionIDs); err != nil {
- t.Fatal(err)
- } else if !reflect.DeepEqual(rcv, expected) {
- t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expected), utils.ToJSON(rcv))
- }
-}
diff --git a/utils/consts.go b/utils/consts.go
index 9cbe232e0..ff30a5074 100644
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -1629,6 +1629,7 @@ const (
// Cache Name
const (
+ CacheConfig = "*config"
CacheResources = "*resources"
CacheResourceProfiles = "*resource_profiles"
CacheEventResources = "*event_resources"