From 89cebf4e0e4ed664f91f5095653cebed803ce630 Mon Sep 17 00:00:00 2001 From: andronache Date: Fri, 4 Jun 2021 15:47:18 +0300 Subject: [PATCH] Started integration tests for config in apis --- apis/account_it_test.go | 6 +- apis/config_it_test.go | 357 ++++++++++++++++++ .../samples/apis_config_internal/cgrates.json | 138 +++++++ .../samples/apis_config_mongo/cgrates.json | 154 ++++++++ .../samples/apis_config_mysql/cgrates.json | 146 +++++++ 5 files changed, 798 insertions(+), 3 deletions(-) create mode 100644 apis/config_it_test.go create mode 100644 data/conf/samples/apis_config_internal/cgrates.json create mode 100644 data/conf/samples/apis_config_mongo/cgrates.json create mode 100644 data/conf/samples/apis_config_mysql/cgrates.json diff --git a/apis/account_it_test.go b/apis/account_it_test.go index 363e4e9d2..d5774e3b6 100644 --- a/apis/account_it_test.go +++ b/apis/account_it_test.go @@ -67,11 +67,11 @@ var ( func TestAccSIT(t *testing.T) { switch *dbType { case utils.MetaInternal: - accPrfConfigDIR = "tutinternal" + accPrfConfigDIR = "apis_config_internal" case utils.MetaMongo: - accPrfConfigDIR = "tutmongo" + accPrfConfigDIR = "apis_config_mongo" case utils.MetaMySQL: - accPrfConfigDIR = "tutmysql" + accPrfConfigDIR = "apis_config_mysql" case utils.MetaPostgres: t.SkipNow() default: diff --git a/apis/config_it_test.go b/apis/config_it_test.go new file mode 100644 index 000000000..c192e7845 --- /dev/null +++ b/apis/config_it_test.go @@ -0,0 +1,357 @@ +// +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 apis + +import ( + "path" + "reflect" + "testing" + + "github.com/cgrates/birpc" + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + cfgPath string + cfgCfg *config.CGRConfig + cfgRPC *birpc.Client + cfgDIR string //run tests for specific configuration + + sTestsCfg = []func(t *testing.T){ + testCfgInitCfg, + testCfgInitDataDb, + testCfgResetStorDb, + testCfgStartEngine, + testCfgRPCConn, + testCfgGetConfigInvalidSection, + testCfgGetConfig, + testCfgSetGetConfig, + testCfgSetEmptyReload, + testCfgSetJSONGetJSONConfig, + testCfgEngine, + //Store Cfg in Database Test + testCfgInitCfgStore, + testCfgInitCfgStore, + testCfgInitDataDbStore, + testCfgResetStorDbStore, + testCfgStartEngineStore, + testCfgRPCConnStore, + testCfgEngineStore, + } +) + +func TestCfgSIT(t *testing.T) { + switch *dbType { + case utils.MetaInternal: + cfgDIR = "tutinternal" + case utils.MetaMongo: + cfgDIR = "tutmongo" + case utils.MetaMySQL: + cfgDIR = "tutmysql" + case utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("Unknown Database type") + } + for _, stest := range sTestsCfg { + t.Run(cfgDIR, stest) + } +} + +func testCfgInitCfg(t *testing.T) { + var err error + cfgPath = path.Join(*dataDir, "conf", "samples", cfgDIR) + cfgCfg, err = config.NewCGRConfigFromPath(cfgPath) + if err != nil { + t.Error(err) + } +} + +func testCfgInitDataDb(t *testing.T) { + if err := engine.InitDataDB(cfgCfg); err != nil { + t.Fatal(err) + } +} + +func testCfgResetStorDb(t *testing.T) { + if err := engine.InitStorDB(cfgCfg); err != nil { + t.Fatal(err) + } +} + +// Start CGR Engine +func testCfgStartEngine(t *testing.T) { + if _, err := engine.StopStartEngine(cfgPath, *waitRater); err != nil { + t.Fatal(err) + } +} + +func testCfgRPCConn(t *testing.T) { + var err error + cfgRPC, err = newRPCClient(cfgCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal(err) + } +} + +func testCfgGetConfigInvalidSection(t *testing.T) { + var reply map[string]interface{} + expected := "Invalid section " + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfig, + &config.SectionWithAPIOpts{ + APIOpts: nil, + Tenant: utils.CGRateSorg, + Sections: []string{"fakeSection"}, + }, + &reply); err == nil || err.Error() != expected { + t.Error(err) + } +} + +func testCfgGetConfig(t *testing.T) { + var reply map[string]interface{} + expected := map[string]interface{}{ + "attributes": map[string]interface{}{ + "admins_conns": []string{"*localhost"}, + "enabled": true, + "indexed_selects": true, + "nested_fields": false, + "prefix_indexed_fields": []string{}, + "process_runs": 1, + "resources_conns": []string{"*localhost"}, + "stats_conns": []string{"*localhost"}, + "suffix_indexed_fields": []string{}, + }, + } + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfig, + &config.SectionWithAPIOpts{ + APIOpts: nil, + Tenant: utils.CGRateSorg, + Sections: []string{"attributes"}, + }, + &reply); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(utils.ToJSON(expected), utils.ToJSON(reply)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", utils.ToJSON(expected), utils.ToJSON(reply)) + } +} + +func testCfgSetGetConfig(t *testing.T) { + var reply string + + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1SetConfig, + &config.SetConfigArgs{ + APIOpts: nil, + Tenant: "", + Config: map[string]interface{}{ + "attributes": map[string]interface{}{ + "admins_conns": []string{"*internal"}, + "enabled": true, + "indexed_selects": false, + "nested_fields": false, + "prefix_indexed_fields": []string{}, + "process_runs": 2, + "resources_conns": []string{"*internal"}, + "stats_conns": []string{"*internal"}, + "suffix_indexed_fields": []string{}, + }, + }, + DryRun: false, + }, + &reply); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(`"OK"`, utils.ToJSON(reply)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", "OK", utils.ToJSON(reply)) + } + expectedGet := map[string]interface{}{ + "attributes": map[string]interface{}{ + "admins_conns": []string{"*internal"}, + "enabled": true, + "indexed_selects": false, + "nested_fields": false, + "prefix_indexed_fields": []string{}, + "process_runs": 2, + "resources_conns": []string{"*internal"}, + "stats_conns": []string{"*internal"}, + "suffix_indexed_fields": []string{}, + }, + } + var replyGet map[string]interface{} + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfig, + &config.SectionWithAPIOpts{ + APIOpts: nil, + Tenant: utils.CGRateSorg, + Sections: []string{"attributes"}, + }, + &replyGet); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) + } +} + +func testCfgSetEmptyReload(t *testing.T) { + var reply string + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1SetConfig, + &config.SetConfigArgs{ + APIOpts: nil, + Tenant: "", + Config: map[string]interface{}{ + "rates": map[string]interface{}{ + "enabled": true, + }, + }, + DryRun: false, + }, + &reply); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(`"OK"`, utils.ToJSON(reply)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", "OK", utils.ToJSON(reply)) + } + var rldArgs string + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1ReloadConfig, + &config.ReloadArgs{ + APIOpts: nil, + Tenant: "", + Section: "rates", + DryRun: false, + }, + &rldArgs); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(`"OK"`, utils.ToJSON(rldArgs)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", "OK", utils.ToJSON(rldArgs)) + } + expectedGet := map[string]interface{}{ + "rates": map[string]interface{}{ + "enabled": true, + "indexed_selects": true, + "nested_fields": false, + "prefix_indexed_fields": []string{}, + "rate_indexed_selects": true, + "rate_nested_fields": false, + "rate_prefix_indexed_fields": []string{}, + "rate_suffix_indexed_fields": []string{}, + "suffix_indexed_fields": []string{}, + "verbosity": 1000, + }, + } + var replyGet map[string]interface{} + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfig, + &config.SectionWithAPIOpts{ + APIOpts: nil, + Tenant: utils.CGRateSorg, + Sections: []string{"rates"}, + }, + &replyGet); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) + } +} + +func testCfgSetJSONGetJSONConfig(t *testing.T) { + var reply string + + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1SetConfigFromJSON, + &config.SetConfigFromJSONArgs{ + APIOpts: nil, + Tenant: "", + Config: "{\"attributes\":{\"admins_conns\":[\"*internal\"],\"enabled\":true,\"indexed_selects\":false,\"nested_fields\":false,\"prefix_indexed_fields\":[],\"process_runs\":2,\"resources_conns\":[\"*internal\"],\"stats_conns\":[\"*localhost\"],\"suffix_indexed_fields\":[]}}", + DryRun: false, + }, + &reply); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(`"OK"`, utils.ToJSON(reply)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", "OK", utils.ToJSON(reply)) + } + expectedGet := "{\"attributes\":{\"admins_conns\":[\"*internal\"],\"enabled\":true,\"indexed_selects\":false,\"nested_fields\":false,\"prefix_indexed_fields\":[],\"process_runs\":2,\"resources_conns\":[\"*internal\"],\"stats_conns\":[\"*localhost\"],\"suffix_indexed_fields\":[]}}" + var replyGet string + if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfigAsJSON, + &config.SectionWithAPIOpts{ + APIOpts: nil, + Tenant: utils.CGRateSorg, + Sections: []string{"attributes"}, + }, + &replyGet); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", utils.ToJSON(expectedGet), utils.ToJSON(replyGet)) + } +} + +func testCfgInitCfgStore(t *testing.T) { + var err error + cfgPath = path.Join(*dataDir, "conf", "samples", cfgDIR) + cfgCfg, err = config.NewCGRConfigFromPath(cfgPath) + if err != nil { + t.Error(err) + } +} + +func testCfgEngine(t *testing.T) { + if err := engine.KillEngine(100); err != nil { + t.Error(err) + } +} + +func testCfgInitDataDbStore(t *testing.T) { + if err := engine.InitDataDB(cfgCfg); err != nil { + t.Fatal(err) + } +} + +func testCfgResetStorDbStore(t *testing.T) { + if err := engine.InitStorDB(cfgCfg); err != nil { + t.Fatal(err) + } +} + +// Start CGR Engine +func testCfgStartEngineStore(t *testing.T) { + if _, err := engine.StopStartEngine(cfgPath, *waitRater); err != nil { + t.Fatal(err) + } +} + +func testCfgRPCConnStore(t *testing.T) { + var err error + cfgRPC, err = newRPCClient(cfgCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal(err) + } +} + +func testCfgEngineStore(t *testing.T) { + if err := engine.KillEngine(100); err != nil { + t.Error(err) + } +} diff --git a/data/conf/samples/apis_config_internal/cgrates.json b/data/conf/samples/apis_config_internal/cgrates.json new file mode 100644 index 000000000..020d6e2a6 --- /dev/null +++ b/data/conf/samples/apis_config_internal/cgrates.json @@ -0,0 +1,138 @@ +{ + // CGRateS Configuration file + // + + + "general": { + "log_level": 7, + "reply_timeout": "50s" + }, + + + "listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080" + }, + + + "data_db": { + "db_type": "*internal" + }, + + + "stor_db": { + "db_type": "*internal" + }, + + + "rals": { + "enabled": true, + "thresholds_conns": ["*internal"], + "max_increments":3000000 + }, + + + "schedulers": { + "enabled": true, + "cdrs_conns": ["*internal"], + "stats_conns": ["*localhost"] + }, + + + "cdrs": { + "enabled": true, + "chargers_conns":["*internal"] + }, + + + "attributes": { + "enabled": true, + "stats_conns": ["*localhost"], + "resources_conns": ["*localhost"], + "admins_conns": ["*localhost"] + }, + + + "chargers": { + "enabled": true, + "attributes_conns": ["*internal"] + }, + + + "resources": { + "enabled": true, + "store_interval": "-1", + "thresholds_conns": ["*internal"] + }, + + + "stats": { + "enabled": true, + "store_interval": "-1", + "thresholds_conns": ["*internal"] + }, + + "thresholds": { + "enabled": true, + "store_interval": "-1" + }, + + + "routes": { + "enabled": true, + "prefix_indexed_fields":["*req.Destination"], + "stats_conns": ["*internal"], + "resources_conns": ["*internal"], + "rals_conns": ["*internal"] + }, + + + "sessions": { + "enabled": true, + "routes_conns": ["*internal"], + "resources_conns": ["*internal"], + "attributes_conns": ["*internal"], + "rals_conns": ["*internal"], + "cdrs_conns": ["*internal"], + "chargers_conns": ["*internal"] + }, + + + "admins": { + "enabled": true, + "scheduler_conns": ["*internal"] + }, + + + "rates": { + "enabled": false + }, + + + "actions": { + "enabled": true, + "accounts_conns": ["*localhost"] + }, + + + "accounts": { + "enabled": true + }, + + + "filters": { + "stats_conns": ["*internal"], + "resources_conns": ["*internal"], + "admins_conns": ["*internal"] + }, + + "config_db": { + "db_type": "redis", + "db_host": "", + "db_port": 6379, + "db_name": "10", + "db_user": "", + "db_password": "" + } +} diff --git a/data/conf/samples/apis_config_mongo/cgrates.json b/data/conf/samples/apis_config_mongo/cgrates.json new file mode 100644 index 000000000..7b1757883 --- /dev/null +++ b/data/conf/samples/apis_config_mongo/cgrates.json @@ -0,0 +1,154 @@ +{ + // CGRateS Configuration file + + + "general": { + "log_level": 7, + "reply_timeout": "30s", + }, + + + "listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", + }, + + + "data_db": { + "db_type": "mongo", + "db_name": "10", + "db_port": 27017, + }, + + + "stor_db": { + "db_type": "mongo", + "db_name": "cgrates", + "db_port": 27017, + }, + + + "rals": { + "enabled": true, + "thresholds_conns": ["*internal"], + "max_increments":3000000, + }, + + + "schedulers": { + "enabled": true, + "cdrs_conns": ["*internal"], + "stats_conns": ["*localhost"], + }, + + + "cdrs": { + "enabled": true, + "chargers_conns":["*internal"], + }, + + + "attributes": { + "enabled": true, + "stats_conns": ["*localhost"], + "resources_conns": ["*localhost"], + "admins_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"], + "rals_conns": ["*internal"], + }, + + + "sessions": { + "enabled": true, + "routes_conns": ["*internal"], + "resources_conns": ["*internal"], + "attributes_conns": ["*internal"], + "rals_conns": ["*internal"], + "cdrs_conns": ["*internal"], + "chargers_conns": ["*internal"], + }, + + + "migrator": { + "out_datadb_type": "mongo", + "out_datadb_port": "27017", + "out_datadb_name": "10", + "out_stordb_type": "mongo", + "out_stordb_port": "27017", + "out_stordb_name": "cgrates", + "users_filters":["Account"], + }, + + + "admins": { + "enabled": true, + "scheduler_conns": ["*internal"], + }, + + + "rates": { + "enabled": false + }, + + + + "actions": { + "enabled": true, + "accounts_conns": ["*localhost"] + }, + + + "accounts": { + "enabled": true + }, + + + "filters": { + "stats_conns": ["*internal"], + "resources_conns": ["*internal"], + "admins_conns": ["*internal"], + }, + + "config_db": { + "db_type": "redis", + "db_host": "", + "db_port": 6379, + "db_name": "10", + "db_user": "", + "db_password": "" + } +} diff --git a/data/conf/samples/apis_config_mysql/cgrates.json b/data/conf/samples/apis_config_mysql/cgrates.json new file mode 100644 index 000000000..5d5d342f1 --- /dev/null +++ b/data/conf/samples/apis_config_mysql/cgrates.json @@ -0,0 +1,146 @@ +{ + // CGRateS Configuration file + // + + + "general": { + "log_level": 7, + "reply_timeout": "50s", + }, + + + "listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", + }, + + "data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "redis", // data_db type: + "db_port": 6379, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + }, + + "stor_db": { + "db_password": "CGRateS.org", + }, + + + "rals": { + "enabled": true, + "thresholds_conns": ["*internal"], + "max_increments":3000000, + }, + + + "schedulers": { + "enabled": true, + "cdrs_conns": ["*internal"], + "stats_conns": ["*localhost"], + }, + + + "cdrs": { + "enabled": true, + "chargers_conns":["*internal"], + }, + + + "attributes": { + "enabled": true, + "stats_conns": ["*localhost"], + "resources_conns": ["*localhost"], + "admins_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"], + "rals_conns": ["*internal"], + }, + + + "sessions": { + "enabled": true, + "routes_conns": ["*internal"], + "resources_conns": ["*internal"], + "attributes_conns": ["*internal"], + "rals_conns": ["*internal"], + "cdrs_conns": ["*internal"], + "chargers_conns": ["*internal"], + }, + + + "migrator":{ + "out_stordb_password": "CGRateS.org", + "users_filters":["Account"], + }, + + + "admins": { + "enabled": true, + "scheduler_conns": ["*internal"], + }, + + + "rates": { + "enabled": false + }, + + + "actions": { + "enabled": true, + "accounts_conns": ["*localhost"] + }, + + + "accounts": { + "enabled": true + }, + + + "filters": { + "stats_conns": ["*internal"], + "resources_conns": ["*internal"], + "admins_conns": ["*internal"], + }, + + "config_db": { + "db_type": "redis", + "db_host": "", + "db_port": 6379, + "db_name": "10", + "db_user": "", + "db_password": "" + }, + +},