From b2f11e7f4208294caa0cba46ea6f3c08d76dfccc Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Tue, 1 Mar 2022 18:44:20 +0200 Subject: [PATCH] Implement config drv funcs for redis, mongo and internal dbs --- engine/storage_internal_datadb.go | 33 ++- engine/storage_it_test.go | 391 ++++++++++++++++++++++++++++++ engine/storage_mongo_datadb.go | 68 +++++- engine/storage_redis.go | 14 +- engine/storage_redis_it_test.go | 150 ------------ utils/consts.go | 1 + 6 files changed, 489 insertions(+), 168 deletions(-) create mode 100644 engine/storage_it_test.go delete mode 100644 engine/storage_redis_it_test.go 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"