diff --git a/agents/fsevent.go b/agents/fsevent.go index c7dde5de9..7ada33b04 100644 --- a/agents/fsevent.go +++ b/agents/fsevent.go @@ -397,8 +397,8 @@ func (fsev FSEvent) V1AuthorizeArgs() (args *sessions.V1AuthorizeArgs) { if err != nil { return } - cgrEv.Event[utils.Usage] = config.CgrConfig().SessionSCfg().MaxCallDuration // no billsec available in auth - args = &sessions.V1AuthorizeArgs{ // defaults + cgrEv.Event[utils.Usage] = config.CgrConfig().GeneralCfg().MaxCallDuration // no billsec available in auth + args = &sessions.V1AuthorizeArgs{ // defaults CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: cgrEv, Opts: fsev.GetOptions(), diff --git a/agents/fsevent_test.go b/agents/fsevent_test.go index d2f0ae5b3..844fa0e40 100644 --- a/agents/fsevent_test.go +++ b/agents/fsevent_test.go @@ -988,7 +988,7 @@ func TestFsEvV1AuthorizeArgs(t *testing.T) { RoutesIgnoreErrors: true, RoutesMaxCost: utils.MetaEventCost, } - expected.Event[utils.Usage] = config.CgrConfig().SessionSCfg().MaxCallDuration + expected.Event[utils.Usage] = config.CgrConfig().GeneralCfg().MaxCallDuration rcv := ev.V1AuthorizeArgs() if !reflect.DeepEqual(expected.CGREvent.Tenant, rcv.CGREvent.Tenant) { t.Errorf("Expecting: %+v, received: %+v", expected.CGREvent.Tenant, rcv.CGREvent.Tenant) diff --git a/apier/v1/accounts_it_test.go b/apier/v1/accounts_it_test.go index fca9b9172..d41cc1f55 100644 --- a/apier/v1/accounts_it_test.go +++ b/apier/v1/accounts_it_test.go @@ -622,6 +622,21 @@ func testAccITGetDisabledAccountsWithoutTenant(t *testing.T) { func testAccITRemoveAccountWithoutTenant(t *testing.T) { var reply string + acnt1 := utils.AttrSetAccount{Account: "randomAccount"} + if err := accRPC.Call(utils.APIerSv1SetAccount, acnt1, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Errorf("Calling APIerSv1.SetAccount received: %s", reply) + } + var result *engine.Account + if err := accRPC.Call(utils.APIerSv2GetAccount, + &utils.AttrGetAccount{Account: "randomAccount"}, + &result); err != nil { + t.Fatal(err) + } else if result.ID != "cgrates.org:randomAccount" { + t.Errorf("Expected %+v, received %+v", "cgrates.org:randomAccount", result.ID) + } + if err := accRPC.Call(utils.APIerSv1RemoveAccount, &utils.AttrRemoveAccount{Account: "randomAccount"}, &reply); err != nil { @@ -629,9 +644,8 @@ func testAccITRemoveAccountWithoutTenant(t *testing.T) { } else if reply != utils.OK { t.Errorf("Calling APIerSv2.RemoveAccount received: %s", reply) } - var result *[]*engine.Account if err := accRPC.Call(utils.APIerSv2GetAccount, - &utils.AttrGetAccounts{}, + &utils.AttrGetAccount{Account: "randomAccount"}, &result); err == nil || utils.ErrNotFound.Error() != err.Error() { t.Error(err) } diff --git a/apier/v1/apier_it_test.go b/apier/v1/apier_it_test.go index bd54cbe1f..06632fd5c 100644 --- a/apier/v1/apier_it_test.go +++ b/apier/v1/apier_it_test.go @@ -88,6 +88,7 @@ var ( testApierReloadScheduler, testApierSetRatingProfile, testApierSetRatingProfileWithoutTenant, + testApierRemoveRatingProfilesWithoutTenant, testAPIerSv1GetRatingProfile, testAPIerSv1GetRatingProfileWithoutTenant, testAPIerSv1GetRatingProfileIDsWithoutTenant, @@ -140,7 +141,6 @@ var ( testApierGetCacheStats2, testApierLoadTariffPlanFromStorDb, testApierStartStopServiceStatus, - testApierRemoveRatingProfilesWithoutTenant, testApierReplayFldPosts, testApierGetDataDBVesions, testApierGetStorDBVesions, @@ -921,17 +921,6 @@ func testApierSetRatingProfile(t *testing.T) { } } -func testApierSetRatingProfileWithoutTenant(t *testing.T) { - var reply string - rpa := &utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1", FallbackSubjects: "dan2"} - rpf := &utils.AttrSetRatingProfile{Category: "call", Subject: "dan", RatingPlanActivations: []*utils.TPRatingActivation{rpa}} - if err := rater.Call(utils.APIerSv1SetRatingProfile, &rpf, &reply); err != nil { - t.Error("Got error on APIerSv1.SetRatingProfile: ", err.Error()) - } else if reply != utils.OK { - t.Error("Calling APIerSv1.SetRatingProfile got reply: ", reply) - } -} - func testAPIerSv1GetRatingProfile(t *testing.T) { var rpl engine.RatingProfile attrGetRatingPlan := &utils.AttrGetRatingProfile{ @@ -953,11 +942,6 @@ func testAPIerSv1GetRatingProfile(t *testing.T) { RatingPlanId: "RETAIL1", FallbackKeys: []string{"*out:cgrates.org:call:dan2"}, }, - { - ActivationTime: actTime, - RatingPlanId: "RETAIL1", - FallbackKeys: []string{"*out:cgrates.org:call:dan2"}, - }, }, } if err := rater.Call(utils.APIerSv1GetRatingProfile, attrGetRatingPlan, &rpl); err != nil { @@ -1019,11 +1003,6 @@ func testAPIerSv1GetRatingProfileWithoutTenant(t *testing.T) { RatingPlanId: "RETAIL1", FallbackKeys: []string{"*out:cgrates.org:call:dan2"}, }, - { - ActivationTime: actTime, - RatingPlanId: "RETAIL1", - FallbackKeys: []string{"*out:cgrates.org:call:dan2"}, - }, }, } if err := rater.Call(utils.APIerSv1GetRatingProfile, &attrGetRatingPlan, &rpl); err != nil { @@ -2037,16 +2016,42 @@ func testApierStartStopServiceStatus(t *testing.T) { } } +func testApierSetRatingProfileWithoutTenant(t *testing.T) { + var reply string + rpa := &utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1", FallbackSubjects: "dan4"} + rpf := &utils.AttrSetRatingProfile{Category: utils.CALL, Subject: "dan3", RatingPlanActivations: []*utils.TPRatingActivation{rpa}} + if err := rater.Call(utils.APIerSv1SetRatingProfile, &rpf, &reply); err != nil { + t.Error("Got error on APIerSv1.SetRatingProfile: ", err.Error()) + } else if reply != utils.OK { + t.Error("Calling APIerSv1.SetRatingProfile got reply: ", reply) + } + expectedID := utils.ConcatenatedKey(utils.META_OUT, "cgrates.org", utils.CALL, "dan3") + var result *engine.RatingProfile + if err := rater.Call(utils.APIerSv1GetRatingProfile, + &utils.AttrGetRatingProfile{Category: utils.CALL, Subject: "dan3"}, + &result); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedID, result.Id) { + t.Errorf("Expected %+v, received %+v", expectedID, result.Id) + } +} + func testApierRemoveRatingProfilesWithoutTenant(t *testing.T) { var reply string if err := rater.Call(utils.APIerSv1RemoveRatingProfile, &AttrRemoveRatingProfile{ Category: utils.CALL, - Subject: utils.ANY, + Subject: "dan3", }, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Errorf("Expected: %s, received: %s ", utils.OK, reply) } + var result *engine.RatingProfile + if err := rater.Call(utils.APIerSv1GetRatingProfile, + &utils.AttrGetRatingProfile{Category: utils.CALL, Subject: "dan3"}, + &result); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } } func testApierReplayFldPosts(t *testing.T) { diff --git a/apier/v1/auth.go b/apier/v1/auth.go index e6b1df351..60cad2ea6 100644 --- a/apier/v1/auth.go +++ b/apier/v1/auth.go @@ -51,7 +51,7 @@ func (apierSv1 *APIerSv1) GetMaxUsage(usageRecord *engine.UsageRecordWithOpts, m } if usageRecord.Usage == utils.EmptyString { usageRecord.Usage = strconv.FormatFloat( - apierSv1.Config.MaxCallDuration.Seconds(), 'f', -1, 64) + apierSv1.Config.GeneralCfg().MaxCallDuration.Seconds(), 'f', -1, 64) } cd, err := usageRecord.AsCallDescriptor(apierSv1.Config.GeneralCfg().DefaultTimezone, false) if err != nil { diff --git a/apier/v1/config_it_test.go b/apier/v1/config_it_test.go index 1700fc358..6b0a64906 100644 --- a/apier/v1/config_it_test.go +++ b/apier/v1/config_it_test.go @@ -146,14 +146,12 @@ func testConfigSReloadConfigFromJSONSessionS(t *testing.T) { "AttrSConns": []interface{}{utils.MetaLocalHost}, "CDRsConns": []interface{}{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}, "ReplicationConns": []interface{}{}, - "MaxCallDuration": float64(3 * time.Hour), "MinDurLowBalance": 0., "SessionIndexes": map[string]interface{}{"OriginID": true}, "ClientProtocol": 1., "TerminateAttempts": 5., "ChannelSyncInterval": 0., "DebitInterval": 0., - "MinCallDuration": 0., "SessionTTL": 0., "SessionTTLLastUsed": nil, "SessionTTLMaxDelay": nil, @@ -203,14 +201,12 @@ func testConfigSv1GetJSONSectionWithoutTenant(t *testing.T) { "AttrSConns": []interface{}{utils.MetaLocalHost}, "CDRsConns": []interface{}{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}, "ReplicationConns": []interface{}{}, - "MaxCallDuration": float64(3 * time.Hour), "MinDurLowBalance": 0., "SessionIndexes": map[string]interface{}{"OriginID": true}, "ClientProtocol": 1., "TerminateAttempts": 5., "ChannelSyncInterval": 0., "DebitInterval": 0., - "MinCallDuration": 0., "SessionTTL": 0., "SessionTTLLastUsed": nil, "SessionTTLMaxDelay": nil, diff --git a/config/config.go b/config/config.go index 889a6676b..9fe0b02a8 100755 --- a/config/config.go +++ b/config/config.go @@ -136,7 +136,6 @@ func NewDefaultCGRConfig() (cfg *CGRConfig, err error) { cfg = new(CGRConfig) cfg.initChanels() cfg.DataFolderPath = "/usr/share/cgrates/" - cfg.MaxCallDuration = time.Duration(3) * time.Hour // Hardcoded for now cfg.rpcConns = make(map[string]*RPCConn) cfg.templates = make(map[string][]*FCTemplate) @@ -275,10 +274,9 @@ func isHidden(fileName string) bool { // CGRConfig holds system configuration, defaults are overwritten with values from config file if found type CGRConfig struct { - lks map[string]*sync.RWMutex - MaxCallDuration time.Duration // The maximum call duration (used by responder when querying DerivedCharging) // ToDo: export it in configuration file - DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options - ConfigPath string // Path towards config + lks map[string]*sync.RWMutex + DataFolderPath string // Path towards data folder, for tests internal usage, not loading out of .json options + ConfigPath string // Path towards config // Cache defaults loaded from json and needing clones dfltEvRdr *EventReaderCfg // default event reader diff --git a/config/config_defaults.go b/config/config_defaults.go index a9ad4e174..a1f7db1c7 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -42,6 +42,8 @@ const CGRATES_CFG_JSON = ` "default_tenant": "cgrates.org", // default tenant to consider when missing from requests "default_timezone": "Local", // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> "default_caching":"*reload", // default actions to do when caching items + "min_call_duration": "0s", // only authorize calls with allowed duration higher than this + "max_call_duration": "3h", // maximum call duration a prepaid call can last "connect_attempts": 5, // initial server connect attempts "reconnects": -1, // number of retries in case of connection lost "connect_timeout": "1s", // consider connection unsuccessful on timeout, 0 to disable the feature @@ -440,8 +442,6 @@ const CGRATES_CFG_JSON = ` "replication_conns": [], // replicate sessions towards these session services "debit_interval": "0s", // interval to perform debits on. "store_session_costs": false, // enable storing of the session costs within CDRs - "min_call_duration": "0s", // only authorize calls with allowed duration higher than this - "max_call_duration": "3h", // maximum call duration a prepaid call can last "session_ttl": "0s", // time after a session with no updates is terminated, not defined by default //"session_ttl_max_delay": "", // activates session_ttl randomization and limits the maximum possible delay //"session_ttl_last_used": "", // tweak LastUsed for sessions timing-out, not defined by default diff --git a/config/config_it_test.go b/config/config_it_test.go index 6d567a33b..22d242c68 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -410,7 +410,6 @@ func testCGRConfigReloadSessionS(t *testing.T) { CDRsConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}, ReplicationConns: []string{}, - MaxCallDuration: 3 * time.Hour, SessionIndexes: utils.NewStringMap(), ClientProtocol: 1, TerminateAttempts: 5, @@ -959,7 +958,6 @@ func testCGRConfigReloadConfigFromJSONSessionS(t *testing.T) { CDRsConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}, ReplicationConns: []string{}, - MaxCallDuration: 3 * time.Hour, SessionIndexes: utils.NewStringMap(), ClientProtocol: 1, TerminateAttempts: 5, @@ -1006,7 +1004,6 @@ func testCGRConfigReloadAll(t *testing.T) { CDRsConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}, ReplicationConns: []string{}, - MaxCallDuration: 3 * time.Hour, SessionIndexes: utils.NewStringMap(), ClientProtocol: 1, TerminateAttempts: 5, diff --git a/config/config_json_test.go b/config/config_json_test.go index f2d0271ba..8810771ad 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -54,6 +54,8 @@ func TestDfGeneralJsonCfg(t *testing.T) { Default_timezone: utils.StringPointer("Local"), Connect_attempts: utils.IntPointer(5), Reconnects: utils.IntPointer(-1), + Min_call_duration: utils.StringPointer("0s"), + Max_call_duration: utils.StringPointer("3h"), Connect_timeout: utils.StringPointer("1s"), Reply_timeout: utils.StringPointer("2s"), Locking_timeout: utils.StringPointer("0"), @@ -656,8 +658,6 @@ func TestSmgJsonCfg(t *testing.T) { Replication_conns: &[]string{}, Debit_interval: utils.StringPointer("0s"), Store_session_costs: utils.BoolPointer(false), - Min_call_duration: utils.StringPointer("0s"), - Max_call_duration: utils.StringPointer("3h"), Session_ttl: utils.StringPointer("0s"), Session_indexes: &[]string{}, Client_protocol: utils.Float64Pointer(1.0), diff --git a/config/config_test.go b/config/config_test.go index ab7d020d4..8a84eee86 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -474,8 +474,6 @@ func TestCgrCfgJSONDefaultsSMGenericCfg(t *testing.T) { ReplicationConns: []string{}, DebitInterval: 0 * time.Second, StoreSCosts: false, - MinCallDuration: 0 * time.Second, - MaxCallDuration: 3 * time.Hour, SessionTTL: 0 * time.Second, SessionIndexes: utils.StringMap{}, ClientProtocol: 1.0, diff --git a/config/generalcfg.go b/config/generalcfg.go index 79c30e172..cf016af52 100644 --- a/config/generalcfg.go +++ b/config/generalcfg.go @@ -46,10 +46,12 @@ type GeneralCfg struct { ConnectTimeout time.Duration // timeout for RPC connection attempts ReplyTimeout time.Duration // timeout replies if not reaching back LockingTimeout time.Duration // locking mechanism timeout to avoid deadlocks - DigestSeparator string // - DigestEqual string // - RSRSep string // separator used to split RSRParser (by default is used ";") - MaxParallelConns int // the maximum number of connection used by the *parallel strategy + MinCallDuration time.Duration + MaxCallDuration time.Duration + DigestSeparator string // + DigestEqual string // + RSRSep string // separator used to split RSRParser (by default is used ";") + MaxParallelConns int // the maximum number of connection used by the *parallel strategy ConcurrentRequests int ConcurrentStrategy string } @@ -87,6 +89,16 @@ func (gencfg *GeneralCfg) loadFromJsonCfg(jsnGeneralCfg *GeneralJsonCfg) (err er if jsnGeneralCfg.Reconnects != nil { gencfg.Reconnects = *jsnGeneralCfg.Reconnects } + if jsnGeneralCfg.Min_call_duration != nil { + if gencfg.MinCallDuration, err = utils.ParseDurationWithNanosecs(*jsnGeneralCfg.Min_call_duration); err != nil { + return err + } + } + if jsnGeneralCfg.Max_call_duration != nil { + if gencfg.MaxCallDuration, err = utils.ParseDurationWithNanosecs(*jsnGeneralCfg.Max_call_duration); err != nil { + return err + } + } if jsnGeneralCfg.Connect_timeout != nil { if gencfg.ConnectTimeout, err = utils.ParseDurationWithNanosecs(*jsnGeneralCfg.Connect_timeout); err != nil { return err @@ -195,5 +207,16 @@ func (gencfg *GeneralCfg) AsMapInterface() (initialMP map[string]interface{}) { } else { initialMP[utils.ReplyTimeoutCfg] = "0" } + + if gencfg.MinCallDuration != 0 { + initialMP[utils.MinCallDurationCfg] = gencfg.MinCallDuration.String() + } else if gencfg.MinCallDuration == 0 { + initialMP[utils.MinCallDurationCfg] = "0" + } + if gencfg.MaxCallDuration != 0 { + initialMP[utils.MaxCallDurationCfg] = gencfg.MaxCallDuration.String() + } else if gencfg.MaxCallDuration == 0 { + initialMP[utils.MaxCallDurationCfg] = "0" + } return } diff --git a/config/generalcfg_test.go b/config/generalcfg_test.go index b448de628..d9e432038 100644 --- a/config/generalcfg_test.go +++ b/config/generalcfg_test.go @@ -27,13 +27,14 @@ import ( func TestGeneralCfgloadFromJsonCfg(t *testing.T) { cfgJSON := &GeneralJsonCfg{ - Node_id: utils.StringPointer("randomID"), - Logger: utils.StringPointer(utils.MetaSysLog), - Log_level: utils.IntPointer(6), - Rounding_decimals: utils.IntPointer(5), - Dbdata_encoding: utils.StringPointer("msgpack"), - Tpexport_dir: utils.StringPointer("/var/spool/cgrates/tpe"), - + Node_id: utils.StringPointer("randomID"), + Logger: utils.StringPointer(utils.MetaSysLog), + Log_level: utils.IntPointer(6), + Rounding_decimals: utils.IntPointer(5), + Dbdata_encoding: utils.StringPointer("msgpack"), + Tpexport_dir: utils.StringPointer("/var/spool/cgrates/tpe"), + Min_call_duration: utils.StringPointer("0s"), + Max_call_duration: utils.StringPointer("3h0m0s"), Default_request_type: utils.StringPointer(utils.META_RATED), Default_category: utils.StringPointer(utils.CALL), Default_tenant: utils.StringPointer("cgrates.org"), @@ -62,15 +63,17 @@ func TestGeneralCfgloadFromJsonCfg(t *testing.T) { DefaultTimezone: "Local", ConnectAttempts: 3, Reconnects: -1, - ConnectTimeout: time.Duration(1 * time.Second), - ReplyTimeout: time.Duration(2 * time.Second), + ConnectTimeout: time.Second, + ReplyTimeout: 2 * time.Second, + MinCallDuration: 0, + MaxCallDuration: 3 * time.Hour, DigestSeparator: ",", DigestEqual: ":", ConcurrentStrategy: utils.MetaBusy, MaxParallelConns: 100, RSRSep: ";", DefaultCaching: utils.MetaReload, - FailedPostsTTL: time.Duration(2), + FailedPostsTTL: 2, } if jsnCfg, err := NewDefaultCGRConfig(); err != nil { t.Error(err) @@ -119,6 +122,24 @@ func TestGeneralParseDurationCfgloadFromJsonCfg(t *testing.T) { t.Errorf("Expected %+v, received %v", expected, err) } + cfgJSON4 := &GeneralJsonCfg{ + Min_call_duration: utils.StringPointer("1ss"), + } + if jsonCfg, err := NewDefaultCGRConfig(); err != nil { + t.Error(err) + } else if err = jsonCfg.generalCfg.loadFromJsonCfg(cfgJSON4); err == nil || err.Error() != expected { + t.Errorf("Expected %+v, received %v", expected, err) + } + + cfgJSON5 := &GeneralJsonCfg{ + Max_call_duration: utils.StringPointer("1ss"), + } + if jsonCfg, err := NewDefaultCGRConfig(); err != nil { + t.Error(err) + } else if err = jsonCfg.generalCfg.loadFromJsonCfg(cfgJSON5); err == nil || err.Error() != expected { + t.Errorf("Expected %+v, received %v", expected, err) + } + } func TestGeneralCfgAsMapInterface(t *testing.T) { @@ -166,6 +187,8 @@ func TestGeneralCfgAsMapInterface(t *testing.T) { utils.DefaultCachingCfg: "*reload", utils.ConnectAttemptsCfg: 5, utils.ReconnectsCfg: -1, + utils.MinCallDurationCfg: "0", + utils.MaxCallDurationCfg: "3h0m0s", utils.ConnectTimeoutCfg: "1s", utils.ReplyTimeoutCfg: "2s", utils.LockingTimeoutCfg: "1s", @@ -191,6 +214,8 @@ func TestGeneralCfgAsMapInterface1(t *testing.T) { "failed_posts_ttl": "0s", "connect_timeout": "0s", "reply_timeout": "0s", + "min_call_duration": "1s", + "max_call_duration": "0" } }` eMap := map[string]interface{}{ @@ -213,6 +238,8 @@ func TestGeneralCfgAsMapInterface1(t *testing.T) { utils.ConnectTimeoutCfg: "0", utils.ReplyTimeoutCfg: "0", utils.LockingTimeoutCfg: "0", + utils.MinCallDurationCfg: "1s", + utils.MaxCallDurationCfg: "0", utils.DigestSeparatorCfg: ",", utils.DigestEqualCfg: ":", utils.RSRSepCfg: ";", diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 303866c20..4af79d9f0 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -41,6 +41,8 @@ type GeneralJsonCfg struct { Connect_attempts *int Reconnects *int Connect_timeout *string + Min_call_duration *string + Max_call_duration *string Reply_timeout *string Locking_timeout *string Digest_separator *string @@ -223,8 +225,6 @@ type SessionSJsonCfg struct { Attributes_conns *[]string Debit_interval *string Store_session_costs *bool - Min_call_duration *string - Max_call_duration *string Session_ttl *string Session_ttl_max_delay *string Session_ttl_last_used *string diff --git a/config/migratorcfg_test.go b/config/migratorcfg_test.go index f36f342da..b43a6aefe 100644 --- a/config/migratorcfg_test.go +++ b/config/migratorcfg_test.go @@ -43,6 +43,9 @@ func TestMigratorCgrCfgloadFromJsonCfg(t *testing.T) { utils.RedisClusterCfg: true, utils.RedisClusterSyncCfg: "10s", }, + Out_storDB_opts: map[string]interface{}{ + utils.RedisSentinelNameCfg: utils.EmptyString, + }, } expected := &MigratorCgrCfg{ OutDataDBType: utils.REDIS, @@ -68,7 +71,9 @@ func TestMigratorCgrCfgloadFromJsonCfg(t *testing.T) { utils.RedisClientKey: "", utils.RedisCACertificate: "", }, - OutStorDBOpts: map[string]interface{}{}, + OutStorDBOpts: map[string]interface{}{ + utils.RedisSentinelNameCfg: utils.EmptyString, + }, } if cfgJson, err := NewDefaultCGRConfig(); err != nil { t.Error(err) diff --git a/config/multifiles_it_test.go b/config/multifiles_it_test.go index bfbd87265..17472872a 100644 --- a/config/multifiles_it_test.go +++ b/config/multifiles_it_test.go @@ -68,6 +68,7 @@ func TestMfEnvReaderITRead(t *testing.T) { DefaultTimezone: "Local", ConnectAttempts: 3, Reconnects: -1, + MaxCallDuration: 3 * time.Hour, ConnectTimeout: time.Duration(1 * time.Second), ReplyTimeout: time.Duration(2 * time.Second), LockingTimeout: time.Duration(0), diff --git a/config/sessionscfg.go b/config/sessionscfg.go index 9bbf48ada..8b097779f 100644 --- a/config/sessionscfg.go +++ b/config/sessionscfg.go @@ -87,8 +87,6 @@ type SessionSCfg struct { ReplicationConns []string DebitInterval time.Duration StoreSCosts bool - MinCallDuration time.Duration - MaxCallDuration time.Duration SessionTTL time.Duration SessionTTLMaxDelay *time.Duration SessionTTLLastUsed *time.Duration @@ -220,16 +218,6 @@ func (scfg *SessionSCfg) loadFromJsonCfg(jsnCfg *SessionSJsonCfg) (err error) { if jsnCfg.Store_session_costs != nil { scfg.StoreSCosts = *jsnCfg.Store_session_costs } - if jsnCfg.Min_call_duration != nil { - if scfg.MinCallDuration, err = utils.ParseDurationWithNanosecs(*jsnCfg.Min_call_duration); err != nil { - return err - } - } - if jsnCfg.Max_call_duration != nil { - if scfg.MaxCallDuration, err = utils.ParseDurationWithNanosecs(*jsnCfg.Max_call_duration); err != nil { - return err - } - } if jsnCfg.Session_ttl != nil { if scfg.SessionTTL, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl); err != nil { return err @@ -316,16 +304,6 @@ func (scfg *SessionSCfg) AsMapInterface() (initialMP map[string]interface{}) { } else if scfg.DebitInterval == 0 { initialMP[utils.DebitIntervalCfg] = "0" } - if scfg.MinCallDuration != 0 { - initialMP[utils.MinCallDurationCfg] = scfg.MinCallDuration.String() - } else if scfg.MinCallDuration == 0 { - initialMP[utils.MinCallDurationCfg] = "0" - } - if scfg.MaxCallDuration != 0 { - initialMP[utils.MaxCallDurationCfg] = scfg.MaxCallDuration.String() - } else if scfg.MaxCallDuration == 0 { - initialMP[utils.MaxCallDurationCfg] = "0" - } if scfg.SessionTTL != 0 { initialMP[utils.SessionTTLCfg] = scfg.SessionTTL.String() } else if scfg.SessionTTL == 0 { diff --git a/config/sessionscfg_test.go b/config/sessionscfg_test.go index 82399e6ff..e5fcf12bc 100644 --- a/config/sessionscfg_test.go +++ b/config/sessionscfg_test.go @@ -76,8 +76,6 @@ func TestSessionSCfgloadFromJsonCfgCase1(t *testing.T) { Replication_conns: &[]string{"*conn1"}, Debit_interval: utils.StringPointer("2"), Store_session_costs: utils.BoolPointer(true), - Min_call_duration: utils.StringPointer("1"), - Max_call_duration: utils.StringPointer("100"), Session_ttl: utils.StringPointer("0"), Session_indexes: &[]string{}, Client_protocol: utils.Float64Pointer(2.5), @@ -108,8 +106,6 @@ func TestSessionSCfgloadFromJsonCfgCase1(t *testing.T) { ReplicationConns: []string{"*conn1"}, DebitInterval: time.Duration(2), StoreSCosts: true, - MinCallDuration: time.Duration(1), - MaxCallDuration: time.Duration(100), SessionTTL: time.Duration(0), SessionIndexes: utils.StringMap{}, ClientProtocol: 2.5, @@ -159,18 +155,6 @@ func TestSessionSCfgloadFromJsonCfgCase3(t *testing.T) { } } -func TestSessionSCfgloadFromJsonCfgCase4(t *testing.T) { - cfgJSON := &SessionSJsonCfg{ - Max_call_duration: utils.StringPointer("1ss"), - } - expected := "time: unknown unit \"ss\" in duration \"1ss\"" - if jsonCfg, err := NewDefaultCGRConfig(); err != nil { - t.Error(err) - } else if err = jsonCfg.sessionSCfg.loadFromJsonCfg(cfgJSON); err == nil || err.Error() != expected { - t.Errorf("Expected %+v, received %+v", expected, err) - } -} - func TestSessionSCfgloadFromJsonCfgCase5(t *testing.T) { cfgJSON := &SessionSJsonCfg{ Session_ttl: utils.StringPointer("1ss"), @@ -183,18 +167,6 @@ func TestSessionSCfgloadFromJsonCfgCase5(t *testing.T) { } } -func TestSessionSCfgloadFromJsonCfgCase6(t *testing.T) { - cfgJSON := &SessionSJsonCfg{ - Min_call_duration: utils.StringPointer("1ss"), - } - expected := "time: unknown unit \"ss\" in duration \"1ss\"" - if jsonCfg, err := NewDefaultCGRConfig(); err != nil { - t.Error(err) - } else if err = jsonCfg.sessionSCfg.loadFromJsonCfg(cfgJSON); err == nil || err.Error() != expected { - t.Errorf("Expected %+v, received %+v", expected, err) - } -} - func TestSessionSCfgloadFromJsonCfgCase7(t *testing.T) { cfgJSON := &SessionSJsonCfg{ Channel_sync_interval: utils.StringPointer("1ss"), @@ -276,8 +248,6 @@ func TestSessionSCfgloadFromJsonCfgCase10(t *testing.T) { ReplicationConns: []string{}, DebitInterval: time.Duration(0), StoreSCosts: false, - MinCallDuration: time.Duration(0), - MaxCallDuration: time.Duration(10800000000000), SessionTTL: time.Duration(0), SessionIndexes: utils.StringMap{}, ClientProtocol: 1.0, @@ -324,7 +294,6 @@ func TestSessionSCfgloadFromJsonCfgCase11(t *testing.T) { func TestSessionSCfgAsMapInterfaceCase1(t *testing.T) { cfgJSONStr := `{ "sessions": { - "max_call_duration": "0", "channel_sync_interval": "1s", "session_ttl_max_delay": "3h0m0s", "session_ttl_last_used": "0s", @@ -351,8 +320,6 @@ func TestSessionSCfgAsMapInterfaceCase1(t *testing.T) { utils.ReplicationConnsCfg: []string{}, utils.DebitIntervalCfg: "0", utils.StoreSCostsCfg: false, - utils.MinCallDurationCfg: "0", - utils.MaxCallDurationCfg: "0", utils.SessionTTLCfg: "0", utils.SessionTTLMaxDelayCfg: "3h0m0s", utils.SessionTTLLastUsedCfg: "0s", @@ -395,8 +362,6 @@ func TestSessionSCfgAsMapInterfaceCase2(t *testing.T) { "replication_conns": ["*localhost"], "debit_interval": "8s", "store_session_costs": true, - "min_call_duration": "1s", - "max_call_duration": "1h", "session_ttl": "1s", "min_dur_low_balance": "1s", "client_protocol": 2.0, @@ -425,9 +390,7 @@ func TestSessionSCfgAsMapInterfaceCase2(t *testing.T) { utils.ReplicationConnsCfg: []string{utils.MetaLocalHost}, utils.DebitIntervalCfg: "8s", utils.StoreSCostsCfg: true, - utils.MinCallDurationCfg: "1s", utils.MinDurLowBalanceCfg: "1s", - utils.MaxCallDurationCfg: "1h0m0s", utils.SessionTTLCfg: "1s", utils.SessionIndexesCfg: []string{}, utils.ClientProtocolCfg: 2.0, diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index f646b609c..29504a222 100755 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -21,6 +21,8 @@ // "default_tenant": "cgrates.org", // default tenant to consider when missing from requests // "default_timezone": "Local", // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> // "default_caching":"*reload", // default actions to do when caching items +// "min_call_duration": "0s", // only authorize calls with allowed duration higher than this +// "max_call_duration": "3h", // maximum call duration a prepaid call can last // "connect_attempts": 5, // initial server connect attempts // "reconnects": -1, // number of retries in case of connection lost // "connect_timeout": "1s", // consider connection unsuccessful on timeout, 0 to disable the feature @@ -419,8 +421,6 @@ // "replication_conns": [], // replicate sessions towards these session services // "debit_interval": "0s", // interval to perform debits on. // "store_session_costs": false, // enable storing of the session costs within CDRs -// "min_call_duration": "0s", // only authorize calls with allowed duration higher than this -// "max_call_duration": "3h", // maximum call duration a prepaid call can last // "session_ttl": "0s", // time after a session with no updates is terminated, not defined by default // //"session_ttl_max_delay": "", // activates session_ttl randomization and limits the maximum possible delay // //"session_ttl_last_used": "", // tweak LastUsed for sessions timing-out, not defined by default diff --git a/packages/debian/changelog b/packages/debian/changelog index 9dbdf94af..af28131d3 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -117,6 +117,8 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [ERs] Added support for *amqpv1_json_map type * [RALs] Send balance update event from rals to threshold ( in case of negative) only once * [SessionS] Use rals_conns when sending refund rounding + * [General] Made tenant optional for all API calls + * [ConfigS] Moved MinCallDuration,MaxCallDuration from sessions config to general config -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/sessions/sessions.go b/sessions/sessions.go index 16cdf1a21..e9f5c466b 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -1398,7 +1398,7 @@ func (sS *SessionS) authEvent(cgrEv *utils.CGREventWithOpts, forceDuration bool) return } err = nil - eventUsage = sS.cgrCfg.SessionSCfg().MaxCallDuration + eventUsage = sS.cgrCfg.GeneralCfg().MaxCallDuration evStart[utils.Usage] = eventUsage // will be used in CD } var s *Session @@ -1472,7 +1472,7 @@ func (sS *SessionS) updateSession(s *Session, updtEv, opts engine.MapEvent, isMs return } err = nil - reqMaxUsage = sS.cgrCfg.SessionSCfg().MaxCallDuration + reqMaxUsage = sS.cgrCfg.GeneralCfg().MaxCallDuration updtEv[utils.Usage] = reqMaxUsage } maxUsage = make(map[string]time.Duration) @@ -2273,7 +2273,7 @@ func (sS *SessionS) BiRPCv1InitiateSession(clnt rpcclient.ClientConnector, isPrepaid := s.debitStop != nil s.RUnlock() if isPrepaid { //active debit - rply.MaxUsage = &sS.cgrCfg.SessionSCfg().MaxCallDuration + rply.MaxUsage = &sS.cgrCfg.GeneralCfg().MaxCallDuration } else { var sRunsUsage map[string]time.Duration if sRunsUsage, err = sS.updateSession(s, nil, args.Opts, false); err != nil { @@ -3424,7 +3424,7 @@ func (sS *SessionS) BiRPCv1ProcessEvent(clnt rpcclient.ClientConnector, s.RUnlock() if isPrepaid { //active debit for _, sr := range s.SRuns { - sRunsMaxUsage[sr.CD.RunID] = sS.cgrCfg.SessionSCfg().MaxCallDuration + sRunsMaxUsage[sr.CD.RunID] = sS.cgrCfg.GeneralCfg().MaxCallDuration } } else if sRunsMaxUsage, err = sS.updateSession(s, nil, args.Opts, false); err != nil { return utils.NewErrRALs(err)