diff --git a/apis/loaders_it_test.go b/apis/loaders_it_test.go index 6414a56c1..3af9355fd 100644 --- a/apis/loaders_it_test.go +++ b/apis/loaders_it_test.go @@ -296,7 +296,6 @@ func testLoadersGetAccount(t *testing.T) { Weight: 20, }, }, - FilterIDs: []string{}, Balances: map[string]*utils.Balance{ "MonetaryBalance": { ID: "MonetaryBalance", @@ -358,10 +357,9 @@ func testLoadersGetActionProfile(t *testing.T) { } expActPrf := engine.ActionProfile{ - Tenant: "cgrates.org", - ID: "ACT_PRF", - FilterIDs: []string{}, - Schedule: utils.MetaASAP, + Tenant: "cgrates.org", + ID: "ACT_PRF", + Schedule: utils.MetaASAP, Targets: map[string]utils.StringSet{ utils.MetaAccounts: { "1001": {}, @@ -415,10 +413,9 @@ func testLoadersGetAttributeProfile(t *testing.T) { Weight: 10, Attributes: []*engine.ExternalAttribute{ { - FilterIDs: []string{}, - Path: "*req.OfficeGroup", - Type: utils.MetaConstant, - Value: "Marketing", + Path: "*req.OfficeGroup", + Type: utils.MetaConstant, + Value: "Marketing", }, }, } @@ -485,17 +482,14 @@ func testLoadersGetDispatcherProfile(t *testing.T) { } expDspPrf := engine.DispatcherProfile{ - Tenant: "cgrates.org", - ID: "DSP1", - FilterIDs: []string{"FLTR_ACCOUNT_1001"}, - Strategy: utils.MetaWeight, - StrategyParams: make(map[string]interface{}), + Tenant: "cgrates.org", + ID: "DSP1", + FilterIDs: []string{"FLTR_ACCOUNT_1001"}, + Strategy: utils.MetaWeight, Hosts: engine.DispatcherHostProfiles{ { - ID: "ALL", - FilterIDs: []string{}, - Weight: 20, - Params: map[string]interface{}{}, + ID: "ALL", + Weight: 20, }, }, Weight: 10, @@ -532,7 +526,6 @@ func testLoadersGetDispatcherHost(t *testing.T) { RemoteHost: &config.RemoteHost{ ID: expIDs[0], Address: utils.MetaInternal, - Transport: utils.MetaJSON, ConnectAttempts: 1, Reconnects: 3, ConnectTimeout: time.Minute, @@ -666,13 +659,12 @@ func testLoadersGetResourceProfile(t *testing.T) { } expRsPrf := engine.ResourceProfile{ - Tenant: "cgrates.org", - ID: "RES_ACNT_1001", - FilterIDs: []string{"FLTR_ACCOUNT_1001"}, - Weight: 10, - UsageTTL: 3600000000000, - Limit: 1, - ThresholdIDs: []string{}, + Tenant: "cgrates.org", + ID: "RES_ACNT_1001", + FilterIDs: []string{"FLTR_ACCOUNT_1001"}, + Weight: 10, + UsageTTL: 3600000000000, + Limit: 1, } var rplyRsPrf engine.ResourceProfile @@ -702,11 +694,10 @@ func testLoadersGetRouteProfile(t *testing.T) { } expRtPrf := engine.APIRouteProfile{ - Tenant: "cgrates.org", - ID: "ROUTE_ACNT_1001", - FilterIDs: []string{"FLTR_ACCOUNT_1001"}, - Sorting: utils.MetaWeight, - SortingParameters: []string{}, + Tenant: "cgrates.org", + ID: "ROUTE_ACNT_1001", + FilterIDs: []string{"FLTR_ACCOUNT_1001"}, + Sorting: utils.MetaWeight, Routes: []*engine.ExternalRoute{ { ID: "route1", diff --git a/config/config_defaults.go b/config/config_defaults.go index 0f8590b94..dec96c3e5 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -1224,7 +1224,7 @@ const CGRATES_CFG_JSON = ` {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4"}, + {"tag": "AttributeFilterIDs", "path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4","new_branch":true}, {"tag": "Path", "path": "Attributes.Path", "type": "*variable", "value": "~*req.5"}, {"tag": "Type", "path": "Attributes.Type", "type": "*variable", "value": "~*req.6"}, {"tag": "Value", "path": "Attributes.Value", "type": "*variable", "value": "~*req.7"}, @@ -1258,8 +1258,8 @@ const CGRATES_CFG_JSON = ` {"tag": "QueueLength", "path": "QueueLength", "type": "*variable", "value": "~*req.4"}, {"tag": "TTL", "path": "TTL", "type": "*variable", "value": "~*req.5"}, {"tag": "MinItems", "path": "MinItems", "type": "*variable", "value": "~*req.6"}, - {"tag": "MetricIDs", "path": "MetricIDs", "type": "*variable", "value": "~*req.7"}, - {"tag": "MetricFilterIDs", "path": "MetricFilterIDs", "type": "*variable", "value": "~*req.8"}, + {"tag": "MetricIDs", "path": "Metrics.MetricID", "type": "*variable", "value": "~*req.7","new_branch":true}, + {"tag": "MetricFilterIDs", "path": "Metrics.FilterIDs", "type": "*variable", "value": "~*req.8"}, {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.9"}, {"tag": "Stored", "path": "Stored", "type": "*variable", "value": "~*req.10"}, {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~*req.11"}, @@ -1291,15 +1291,15 @@ const CGRATES_CFG_JSON = ` {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, {"tag": "Sorting", "path": "Sorting", "type": "*variable", "value": "~*req.4"}, {"tag": "SortingParameters", "path": "SortingParameters", "type": "*variable", "value": "~*req.5"}, - {"tag": "RouteID", "path": "RouteID", "type": "*variable", "value": "~*req.6"}, - {"tag": "RouteFilterIDs", "path": "RouteFilterIDs", "type": "*variable", "value": "~*req.7"}, - {"tag": "RouteAccountIDs", "path": "RouteAccountIDs", "type": "*variable", "value": "~*req.8"}, - {"tag": "RouteRateProfileIDs", "path": "RouteRateProfileIDs", "type": "*variable", "value": "~*req.9"}, - {"tag": "RouteResourceIDs", "path": "RouteResourceIDs", "type": "*variable", "value": "~*req.10"}, - {"tag": "RouteStatIDs", "path": "RouteStatIDs", "type": "*variable", "value": "~*req.11"}, - {"tag": "RouteWeights", "path": "RouteWeights", "type": "*variable", "value": "~*req.12"}, - {"tag": "RouteBlocker", "path": "RouteBlocker", "type": "*variable", "value": "~*req.13"}, - {"tag": "RouteParameters", "path": "RouteParameters", "type": "*variable", "value": "~*req.14"}, + {"tag": "RouteID", "path": "Routes.ID", "type": "*variable", "value": "~*req.6","new_branch":true}, + {"tag": "RouteFilterIDs", "path": "Routes.FilterIDs", "type": "*variable", "value": "~*req.7"}, + {"tag": "RouteAccountIDs", "path": "Routes.AccountIDs", "type": "*variable", "value": "~*req.8"}, + {"tag": "RouteRateProfileIDs", "path": "Routes.RateProfileIDs", "type": "*variable", "value": "~*req.9"}, + {"tag": "RouteResourceIDs", "path": "Routes.ResourceIDs", "type": "*variable", "value": "~*req.10"}, + {"tag": "RouteStatIDs", "path": "Routes.StatIDs", "type": "*variable", "value": "~*req.11"}, + {"tag": "RouteWeights", "path": "Routes.Weights", "type": "*variable", "value": "~*req.12"}, + {"tag": "RouteBlocker", "path": "Routes.Blocker", "type": "*variable", "value": "~*req.13"}, + {"tag": "RouteParameters", "path": "Routes.RouteParameters", "type": "*variable", "value": "~*req.14"}, ], }, { @@ -1323,12 +1323,12 @@ const CGRATES_CFG_JSON = ` {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, {"tag": "Strategy", "path": "Strategy", "type": "*variable", "value": "~*req.4"}, - {"tag": "StrategyParameters", "path": "StrategyParameters", "type": "*variable", "value": "~*req.5"}, - {"tag": "ConnID", "path": "ConnID", "type": "*variable", "value": "~*req.6"}, - {"tag": "ConnFilterIDs", "path": "ConnFilterIDs", "type": "*variable", "value": "~*req.7"}, - {"tag": "ConnWeight", "path": "ConnWeight", "type": "*variable", "value": "~*req.8"}, - {"tag": "ConnBlocker", "path": "ConnBlocker", "type": "*variable", "value": "~*req.9"}, - {"tag": "ConnParameters", "path": "ConnParameters", "type": "*variable", "value": "~*req.10"}, + {"tag": "StrategyParameters", "path": "StrategyParams", "type": "*variable", "value": "~*req.5"}, + {"tag": "ConnID", "path": "Hosts.ID", "type": "*variable", "value": "~*req.6","new_branch":true}, + {"tag": "ConnFilterIDs", "path": "Hosts.FilterIDs", "type": "*variable", "value": "~*req.7"}, + {"tag": "ConnWeight", "path": "Hosts.Weight", "type": "*variable", "value": "~*req.8"}, + {"tag": "ConnBlocker", "path": "Hosts.Blocker", "type": "*variable", "value": "~*req.9"}, + {"tag": "ConnParameters", "path": "Hosts.Params", "type": "*variable", "value": "~*req.10"}, ], }, { @@ -1360,16 +1360,16 @@ const CGRATES_CFG_JSON = ` {"tag": "MinCost", "path": "MinCost", "type": "*variable", "value": "~*req.4"}, {"tag": "MaxCost", "path": "MaxCost", "type": "*variable", "value": "~*req.5"}, {"tag": "MaxCostStrategy", "path": "MaxCostStrategy", "type": "*variable", "value": "~*req.6"}, - {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, - {"tag": "RateFilterIDs", "path": "RateFilterIDs", "type": "*variable", "value": "~*req.8"}, - {"tag": "RateActivationTimes", "path": "RateActivationTimes", "type": "*variable", "value": "~*req.9"}, - {"tag": "RateWeights", "path": "RateWeights", "type": "*variable", "value": "~*req.10"}, - {"tag": "RateBlocker", "path": "RateBlocker", "type": "*variable", "value": "~*req.11"}, - {"tag": "RateIntervalStart", "path": "RateIntervalStart", "type": "*variable", "value": "~*req.12"}, - {"tag": "RateFixedFee", "path": "RateFixedFee", "type": "*variable", "value": "~*req.13"}, - {"tag": "RateRecurrentFee", "path": "RateRecurrentFee", "type": "*variable", "value": "~*req.14"}, - {"tag": "RateUnit", "path": "RateUnit", "type": "*variable", "value": "~*req.15"}, - {"tag": "RateIncrement", "path": "RateIncrement", "type": "*variable", "value": "~*req.16"}, + // {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, + {"tag": "RateFilterIDs", "path": "Rates[<~*req.7>].FilterIDs", "type": "*variable", "value": "~*req.8", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateActivationTimes", "path": "Rates[<~*req.7>].ActivationTimes", "type": "*variable", "value": "~*req.9", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateWeights", "path": "Rates[<~*req.7>].Weights", "type": "*variable", "value": "~*req.10", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateBlocker", "path": "Rates[<~*req.7>].Blocker", "type": "*variable", "value": "~*req.11", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateIntervalStart", "path": "Rates[<~*req.7>].IntervalRates.IntervalStart", "type": "*variable", "value": "~*req.12","new_branch":true, "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateFixedFee", "path": "Rates[<~*req.7>].IntervalRates.FixedFee", "type": "*variable", "value": "~*req.13", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateRecurrentFee", "path": "Rates[<~*req.7>].IntervalRates.RecurrentFee", "type": "*variable", "value": "~*req.14", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateUnit", "path": "Rates[<~*req.7>].IntervalRates.Unit", "type": "*variable", "value": "~*req.15", "filters": ["*notempty:~*req.7:"]}, + {"tag": "RateIncrement", "path": "Rates[<~*req.7>].IntervalRates.Increment", "type": "*variable", "value": "~*req.16", "filters": ["*notempty:~*req.7:"]}, ], }, { @@ -1381,16 +1381,16 @@ const CGRATES_CFG_JSON = ` {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, {"tag": "Schedule", "path": "Schedule", "type": "*variable", "value": "~*req.4"}, - {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, - {"tag": "TargetIDs", "path": "TargetIDs", "type": "*variable", "value": "~*req.6"}, - {"tag": "ActionID", "path": "ActionID", "type": "*variable", "value": "~*req.7"}, - {"tag": "ActionFilterIDs", "path": "ActionFilterIDs", "type": "*variable", "value": "~*req.8"}, - {"tag": "ActionBlocker", "path": "ActionBlocker", "type": "*variable", "value": "~*req.9"}, - {"tag": "ActionTTL", "path": "ActionTTL", "type": "*variable", "value": "~*req.10"}, - {"tag": "ActionType", "path": "ActionType", "type": "*variable", "value": "~*req.11"}, - {"tag": "ActionOpts", "path": "ActionOpts", "type": "*variable", "value": "~*req.12"}, - {"tag": "ActionPath", "path": "ActionPath", "type": "*variable", "value": "~*req.13"}, - {"tag": "ActionValue", "path": "ActionValue", "type": "*variable", "value": "~*req.14"}, + // {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, + {"tag": "TargetIDs", "path": "Targets[<~*req.5>]", "type": "*variable", "value": "~*req.6"}, + // {"tag": "ActionID", "path": "Actions.ID", "type": "*variable", "value": "~*req.7","new_branch":true}, + {"tag": "ActionFilterIDs", "path": "Actions[<~*req.7>].FilterIDs", "type": "*variable", "value": "~*req.8", "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionBlocker", "path": "Actions[<~*req.7>].Blocker", "type": "*variable", "value": "~*req.9", "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionTTL", "path": "Actions[<~*req.7>].TTL", "type": "*variable", "value": "~*req.10", "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionType", "path": "Actions[<~*req.7>].Type", "type": "*variable", "value": "~*req.11", "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionOpts", "path": "Actions[<~*req.7>].Opts", "type": "*variable", "value": "~*req.12", "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionPath", "path": "Actions[<~*req.7>].Diktats.Path", "type": "*variable", "value": "~*req.13","new_branch":true, "filters": ["*notempty:~*req.7:"]}, + {"tag": "ActionValue", "path": "Actions[<~*req.7>].Diktats.Value", "type": "*variable", "value": "~*req.14", "filters": ["*notempty:~*req.7:"]}, ], }, { @@ -1402,16 +1402,16 @@ const CGRATES_CFG_JSON = ` {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, {"tag": "Opts", "path": "Opts", "type": "*variable", "value": "~*req.4"}, - {"tag": "BalanceID", "path": "BalanceID", "type": "*variable", "value": "~*req.5"}, - {"tag": "BalanceFilterIDs", "path": "BalanceFilterIDs", "type": "*variable", "value": "~*req.6"}, - {"tag": "BalanceWeights", "path": "BalanceWeights", "type": "*variable", "value": "~*req.7"}, - {"tag": "BalanceType", "path": "BalanceType", "type": "*variable", "value": "~*req.8"}, - {"tag": "BalanceUnits", "path": "BalanceUnits", "type": "*variable", "value": "~*req.9"}, - {"tag": "BalanceUnitFactors", "path": "BalanceUnitFactors", "type": "*variable", "value": "~*req.10"}, - {"tag": "BalanceOpts", "path": "BalanceOpts", "type": "*variable", "value": "~*req.11"}, - {"tag": "BalanceCostIncrements", "path": "BalanceCostIncrements", "type": "*variable", "value": "~*req.12"}, - {"tag": "BalanceAttributeIDs", "path": "BalanceAttributeIDs", "type": "*variable", "value": "~*req.13"}, - {"tag": "BalanceRateProfileIDs", "path": "BalanceRateProfileIDs", "type": "*variable", "value": "~*req.14"}, + // {"tag": "BalanceID", "path": "Balances.ID", "type": "*variable", "value": "~*req.5"}, + {"tag": "BalanceFilterIDs", "path": "Balances[<~*req.5>].FilterIDs", "type": "*variable", "value": "~*req.6","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceWeights", "path": "Balances[<~*req.5>].Weights", "type": "*variable", "value": "~*req.7","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceType", "path": "Balances[<~*req.5>].Type", "type": "*variable", "value": "~*req.8","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceUnits", "path": "Balances[<~*req.5>].Units", "type": "*variable", "value": "~*req.9","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceUnitFactors", "path": "Balances[<~*req.5>].UnitFactors", "type": "*variable", "value": "~*req.10","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceOpts", "path": "Balances[<~*req.5>].Opts", "type": "*variable", "value": "~*req.11","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceCostIncrements", "path": "Balances[<~*req.5>].CostIncrements", "type": "*variable", "value": "~*req.12","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceAttributeIDs", "path": "Balances[<~*req.5>].AttributeIDs", "type": "*variable", "value": "~*req.13","filters": ["*notempty:~*req.5:"]}, + {"tag": "BalanceRateProfileIDs", "path": "Balances[<~*req.5>].RateProfileIDs", "type": "*variable", "value": "~*req.14","filters": ["*notempty:~*req.5:"]}, {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~*req.15"}, ], }, diff --git a/config/loaderscfg.go b/config/loaderscfg.go index d49e8394f..ea94714f9 100644 --- a/config/loaderscfg.go +++ b/config/loaderscfg.go @@ -276,6 +276,7 @@ func (lData LoaderDataType) Clone() (cln *LoaderDataType) { // Clone itself into a new LoadersConfig func (l LoaderSCfg) Clone() (cln *LoaderSCfg) { + opts := *l.Opts cln = &LoaderSCfg{ ID: l.ID, Enabled: l.Enabled, @@ -288,7 +289,7 @@ func (l LoaderSCfg) Clone() (cln *LoaderSCfg) { TpOutDir: l.TpOutDir, Data: make([]*LoaderDataType, len(l.Data)), Action: l.Action, - Opts: &(*l.Opts), + Opts: &opts, Cache: make(map[string]*CacheParamCfg), } for idx, fld := range l.Data { diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 3953dab03..6c0b0cfdd 100755 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -1189,9 +1189,9 @@ // "fields": [ // {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, // {"tag": "ID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, -// {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.2"}, -// {"tag": "Element", "path": "Element", "type": "*variable", "value": "~*req.3"}, -// {"tag": "Values", "path": "Values", "type": "*variable", "value": "~*req.4"}, +// {"tag": "Type", "path": "Rules.Type", "type": "*variable", "value": "~*req.2"}, +// {"tag": "Element", "path": "Rules.Element", "type": "*variable", "value": "~*req.3"}, +// {"tag": "Values", "path": "Rules.Values", "type": "*variable", "value": "~*req.4"}, // ], // }, // { @@ -1202,10 +1202,10 @@ // {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, // {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, // {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, -// {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, -// {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, -// {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, -// {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, +// {"tag": "AttributeFilterIDs", "path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4"}, +// {"tag": "Path", "path": "Attributes.Path", "type": "*variable", "value": "~*req.5"}, +// {"tag": "Type", "path": "Attributes.Type", "type": "*variable", "value": "~*req.6"}, +// {"tag": "Value", "path": "Attributes.Value", "type": "*variable", "value": "~*req.7"}, // {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, // ], // }, @@ -1236,8 +1236,8 @@ // {"tag": "QueueLength", "path": "QueueLength", "type": "*variable", "value": "~*req.4"}, // {"tag": "TTL", "path": "TTL", "type": "*variable", "value": "~*req.5"}, // {"tag": "MinItems", "path": "MinItems", "type": "*variable", "value": "~*req.6"}, -// {"tag": "MetricIDs", "path": "MetricIDs", "type": "*variable", "value": "~*req.7"}, -// {"tag": "MetricFilterIDs", "path": "MetricFilterIDs", "type": "*variable", "value": "~*req.8"}, +// {"tag": "MetricIDs", "path": "Metrics.MetricID", "type": "*variable", "value": "~*req.7"}, +// {"tag": "MetricFilterIDs", "path": "Metrics.FilterIDs", "type": "*variable", "value": "~*req.8"}, // {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.9"}, // {"tag": "Stored", "path": "Stored", "type": "*variable", "value": "~*req.10"}, // {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~*req.11"}, @@ -1269,15 +1269,15 @@ // {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, // {"tag": "Sorting", "path": "Sorting", "type": "*variable", "value": "~*req.4"}, // {"tag": "SortingParameters", "path": "SortingParameters", "type": "*variable", "value": "~*req.5"}, -// {"tag": "RouteID", "path": "RouteID", "type": "*variable", "value": "~*req.6"}, -// {"tag": "RouteFilterIDs", "path": "RouteFilterIDs", "type": "*variable", "value": "~*req.7"}, -// {"tag": "RouteAccountIDs", "path": "RouteAccountIDs", "type": "*variable", "value": "~*req.8"}, -// {"tag": "RouteRateProfileIDs", "path": "RouteRateProfileIDs", "type": "*variable", "value": "~*req.9"}, -// {"tag": "RouteResourceIDs", "path": "RouteResourceIDs", "type": "*variable", "value": "~*req.10"}, -// {"tag": "RouteStatIDs", "path": "RouteStatIDs", "type": "*variable", "value": "~*req.11"}, -// {"tag": "RouteWeights", "path": "RouteWeights", "type": "*variable", "value": "~*req.12"}, -// {"tag": "RouteBlocker", "path": "RouteBlocker", "type": "*variable", "value": "~*req.13"}, -// {"tag": "RouteParameters", "path": "RouteParameters", "type": "*variable", "value": "~*req.14"}, +// {"tag": "RouteID", "path": "Routes.ID", "type": "*variable", "value": "~*req.6"}, +// {"tag": "RouteFilterIDs", "path": "Routes.FilterIDs", "type": "*variable", "value": "~*req.7"}, +// {"tag": "RouteAccountIDs", "path": "Routes.AccountIDs", "type": "*variable", "value": "~*req.8"}, +// {"tag": "RouteRateProfileIDs", "path": "Routes.RateProfileIDs", "type": "*variable", "value": "~*req.9"}, +// {"tag": "RouteResourceIDs", "path": "Routes.ResourceIDs", "type": "*variable", "value": "~*req.10"}, +// {"tag": "RouteStatIDs", "path": "Routes.StatIDs", "type": "*variable", "value": "~*req.11"}, +// {"tag": "RouteWeights", "path": "Routes.Weights", "type": "*variable", "value": "~*req.12"}, +// {"tag": "RouteBlocker", "path": "Routes.Blocker", "type": "*variable", "value": "~*req.13"}, +// {"tag": "RouteParameters", "path": "Routes.Parameters", "type": "*variable", "value": "~*req.14"}, // ], // }, // { @@ -1302,11 +1302,11 @@ // {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, // {"tag": "Strategy", "path": "Strategy", "type": "*variable", "value": "~*req.4"}, // {"tag": "StrategyParameters", "path": "StrategyParameters", "type": "*variable", "value": "~*req.5"}, -// {"tag": "ConnID", "path": "ConnID", "type": "*variable", "value": "~*req.6"}, -// {"tag": "ConnFilterIDs", "path": "ConnFilterIDs", "type": "*variable", "value": "~*req.7"}, -// {"tag": "ConnWeight", "path": "ConnWeight", "type": "*variable", "value": "~*req.8"}, -// {"tag": "ConnBlocker", "path": "ConnBlocker", "type": "*variable", "value": "~*req.9"}, -// {"tag": "ConnParameters", "path": "ConnParameters", "type": "*variable", "value": "~*req.10"}, +// {"tag": "ConnID", "path": "Hosts.ID", "type": "*variable", "value": "~*req.6"}, +// {"tag": "ConnFilterIDs", "path": "Hosts.FilterIDs", "type": "*variable", "value": "~*req.7"}, +// {"tag": "ConnWeight", "path": "Hosts.Weight", "type": "*variable", "value": "~*req.8"}, +// {"tag": "ConnBlocker", "path": "Hosts.Blocker", "type": "*variable", "value": "~*req.9"}, +// {"tag": "ConnParameters", "path": "Hosts.Params", "type": "*variable", "value": "~*req.10"}, // ], // }, // { @@ -1338,16 +1338,16 @@ // {"tag": "MinCost", "path": "MinCost", "type": "*variable", "value": "~*req.4"}, // {"tag": "MaxCost", "path": "MaxCost", "type": "*variable", "value": "~*req.5"}, // {"tag": "MaxCostStrategy", "path": "MaxCostStrategy", "type": "*variable", "value": "~*req.6"}, -// {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, -// {"tag": "RateFilterIDs", "path": "RateFilterIDs", "type": "*variable", "value": "~*req.8"}, -// {"tag": "RateActivationTimes", "path": "RateActivationTimes", "type": "*variable", "value": "~*req.9"}, -// {"tag": "RateWeights", "path": "RateWeights", "type": "*variable", "value": "~*req.10"}, -// {"tag": "RateBlocker", "path": "RateBlocker", "type": "*variable", "value": "~*req.11"}, -// {"tag": "RateIntervalStart", "path": "RateIntervalStart", "type": "*variable", "value": "~*req.12"}, -// {"tag": "RateFixedFee", "path": "RateFixedFee", "type": "*variable", "value": "~*req.13"}, -// {"tag": "RateRecurrentFee", "path": "RateRecurrentFee", "type": "*variable", "value": "~*req.14"}, -// {"tag": "RateUnit", "path": "RateUnit", "type": "*variable", "value": "~*req.15"}, -// {"tag": "RateIncrement", "path": "RateIncrement", "type": "*variable", "value": "~*req.16"}, +// // {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, +// {"tag": "RateFilterIDs", "path": "Rates[<~*req.7>].FilterIDs", "type": "*variable", "value": "~*req.8"}, +// {"tag": "RateActivationTimes", "path": "Rates[<~*req.7>].ActivationTimes", "type": "*variable", "value": "~*req.9"}, +// {"tag": "RateWeights", "path": "Rates[<~*req.7>].Weights", "type": "*variable", "value": "~*req.10"}, +// {"tag": "RateBlocker", "path": "Rates[<~*req.7>].Blocker", "type": "*variable", "value": "~*req.11"}, +// {"tag": "RateIntervalStart", "path": "Rates[<~*req.7>].IntervalRates.IntervalStart", "type": "*variable", "value": "~*req.12"}, +// {"tag": "RateFixedFee", "path": "Rates[<~*req.7>].IntervalRates.FixedFee", "type": "*variable", "value": "~*req.13"}, +// {"tag": "RateRecurrentFee", "path": "Rates[<~*req.7>].IntervalRates.RecurrentFee", "type": "*variable", "value": "~*req.14"}, +// {"tag": "RateUnit", "path": "Rates[<~*req.7>].IntervalRates.Unit", "type": "*variable", "value": "~*req.15"}, +// {"tag": "RateIncrement", "path": "Rates[<~*req.7>].IntervalRates.Increment", "type": "*variable", "value": "~*req.16"}, // ], // }, // { @@ -1359,16 +1359,16 @@ // {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, // {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, // {"tag": "Schedule", "path": "Schedule", "type": "*variable", "value": "~*req.4"}, -// {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, -// {"tag": "TargetIDs", "path": "TargetIDs", "type": "*variable", "value": "~*req.6"}, -// {"tag": "ActionID", "path": "ActionID", "type": "*variable", "value": "~*req.7"}, -// {"tag": "ActionFilterIDs", "path": "ActionFilterIDs", "type": "*variable", "value": "~*req.8"}, -// {"tag": "ActionBlocker", "path": "ActionBlocker", "type": "*variable", "value": "~*req.9"}, -// {"tag": "ActionTTL", "path": "ActionTTL", "type": "*variable", "value": "~*req.10"}, -// {"tag": "ActionType", "path": "ActionType", "type": "*variable", "value": "~*req.11"}, -// {"tag": "ActionOpts", "path": "ActionOpts", "type": "*variable", "value": "~*req.12"}, -// {"tag": "ActionPath", "path": "ActionPath", "type": "*variable", "value": "~*req.13"}, -// {"tag": "ActionValue", "path": "ActionValue", "type": "*variable", "value": "~*req.14"}, +// // {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, +// {"tag": "TargetIDs", "path": "Targets[<~*req.5>]", "type": "*variable", "value": "~*req.6"}, +// {"tag": "ActionID", "path": "Actions.ID", "type": "*variable", "value": "~*req.7"}, +// {"tag": "ActionFilterIDs", "path": "Actions.FilterIDs", "type": "*variable", "value": "~*req.8"}, +// {"tag": "ActionBlocker", "path": "Actions.Blocker", "type": "*variable", "value": "~*req.9"}, +// {"tag": "ActionTTL", "path": "Actions.TTL", "type": "*variable", "value": "~*req.10"}, +// {"tag": "ActionType", "path": "Actions.Type", "type": "*variable", "value": "~*req.11"}, +// {"tag": "ActionOpts", "path": "Actions.Opts", "type": "*variable", "value": "~*req.12"}, +// {"tag": "ActionPath", "path": "Actions.Path", "type": "*variable", "value": "~*req.13"}, +// {"tag": "ActionValue", "path": "Actions.Value", "type": "*variable", "value": "~*req.14"}, // ], // }, // { @@ -1380,16 +1380,16 @@ // {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, // {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, // {"tag": "Opts", "path": "Opts", "type": "*variable", "value": "~*req.4"}, -// {"tag": "BalanceID", "path": "BalanceID", "type": "*variable", "value": "~*req.5"}, -// {"tag": "BalanceFilterIDs", "path": "BalanceFilterIDs", "type": "*variable", "value": "~*req.6"}, -// {"tag": "BalanceWeights", "path": "BalanceWeights", "type": "*variable", "value": "~*req.7"}, -// {"tag": "BalanceType", "path": "BalanceType", "type": "*variable", "value": "~*req.8"}, -// {"tag": "BalanceUnits", "path": "BalanceUnits", "type": "*variable", "value": "~*req.9"}, -// {"tag": "BalanceUnitFactors", "path": "BalanceUnitFactors", "type": "*variable", "value": "~*req.10"}, -// {"tag": "BalanceOpts", "path": "BalanceOpts", "type": "*variable", "value": "~*req.11"}, -// {"tag": "BalanceCostIncrements", "path": "BalanceCostIncrements", "type": "*variable", "value": "~*req.12"}, -// {"tag": "BalanceAttributeIDs", "path": "BalanceAttributeIDs", "type": "*variable", "value": "~*req.13"}, -// {"tag": "BalanceRateProfileIDs", "path": "BalanceRateProfileIDs", "type": "*variable", "value": "~*req.14"}, +// // {"tag": "BalanceID", "path": "Balances.ID", "type": "*variable", "value": "~*req.5"}, +// {"tag": "BalanceFilterIDs", "path": "Balances[<~*req.5>].FilterIDs", "type": "*variable", "value": "~*req.6"}, +// {"tag": "BalanceWeights", "path": "Balances[<~*req.5>].Weights", "type": "*variable", "value": "~*req.7"}, +// {"tag": "BalanceType", "path": "Balances[<~*req.5>].Type", "type": "*variable", "value": "~*req.8"}, +// {"tag": "BalanceUnits", "path": "Balances[<~*req.5>].Units", "type": "*variable", "value": "~*req.9"}, +// {"tag": "BalanceUnitFactors", "path": "Balances[<~*req.5>].UnitFactors", "type": "*variable", "value": "~*req.10"}, +// {"tag": "BalanceOpts", "path": "Balances[<~*req.5>].Opts", "type": "*variable", "value": "~*req.11"}, +// {"tag": "BalanceCostIncrements", "path": "Balances[<~*req.5>].CostIncrements", "type": "*variable", "value": "~*req.12"}, +// {"tag": "BalanceAttributeIDs", "path": "Balances[<~*req.5>].AttributeIDs", "type": "*variable", "value": "~*req.13"}, +// {"tag": "BalanceRateProfileIDs", "path": "Balances[<~*req.5>].RateProfileIDs", "type": "*variable", "value": "~*req.14"}, // {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~*req.15"}, // ], // }, diff --git a/data/conf/samples/apis_loaders_internal/cgrates.json b/data/conf/samples/apis_loaders_internal/cgrates.json index ac6322f2c..03048829c 100644 --- a/data/conf/samples/apis_loaders_internal/cgrates.json +++ b/data/conf/samples/apis_loaders_internal/cgrates.json @@ -70,7 +70,6 @@ "file_name": "DispatcherHosts.csv", "fields": [ {"tag": "BaseTmpl","type": "*template", "value": "baseTmpl"}, - {"tag": "Address", "path": "Address", "type": "*variable", "value": "~*req.2"}, ], }, { diff --git a/data/conf/samples/apis_loaders_mongo/cgrates.json b/data/conf/samples/apis_loaders_mongo/cgrates.json index 8e06573d3..e5ee6cbdb 100644 --- a/data/conf/samples/apis_loaders_mongo/cgrates.json +++ b/data/conf/samples/apis_loaders_mongo/cgrates.json @@ -74,7 +74,6 @@ "file_name": "DispatcherHosts.csv", "fields": [ {"tag": "BaseTmpl","type": "*template", "value": "baseTmpl"}, - {"tag": "Address", "path": "Address", "type": "*variable", "value": "~*req.2"}, ], }, { diff --git a/data/conf/samples/apis_loaders_mysql/cgrates.json b/data/conf/samples/apis_loaders_mysql/cgrates.json index 9a6ab16ef..06e370950 100644 --- a/data/conf/samples/apis_loaders_mysql/cgrates.json +++ b/data/conf/samples/apis_loaders_mysql/cgrates.json @@ -71,7 +71,6 @@ "file_name": "DispatcherHosts.csv", "fields": [ {"tag": "BaseTmpl","type": "*template", "value": "baseTmpl"}, - {"tag": "Address", "path": "Address", "type": "*variable", "value": "~*req.2"}, ], }, { diff --git a/data/conf/samples/loaders/tutinternal/cgrates.json b/data/conf/samples/loaders/tutinternal/cgrates.json index 10ebd28b7..fffc78217 100644 --- a/data/conf/samples/loaders/tutinternal/cgrates.json +++ b/data/conf/samples/loaders/tutinternal/cgrates.json @@ -60,15 +60,8 @@ "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -89,15 +82,8 @@ "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -118,15 +104,8 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -147,15 +126,8 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -197,12 +169,12 @@ "type": "*attributes", "file_name": "Attributes", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "*req.Destination"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "*constant"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.1"}, + {"path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, + {"path": "Attributes.Path", "type": "*variable", "value": "*req.Destination"}, + {"path": "Attributes.Type", "type": "*variable", "value": "*constant"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.1"}, ], }, ], @@ -224,15 +196,15 @@ "templates": { "attrTemplateLoader": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, + {"path": "Weight", "type": "*variable", "value": "~*req.3"}, + {"path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4","new_branch":true}, + {"path": "Attributes.Path", "type": "*variable", "value": "~*req.5"}, + {"path": "Attributes.Type", "type": "*variable", "value": "~*req.6"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.7"}, + {"path": "Blocker", "type": "*variable", "value": "~*req.8"}, ], }, diff --git a/data/conf/samples/loaders/tutmongo/cgrates.json b/data/conf/samples/loaders/tutmongo/cgrates.json index 9d1298020..54ae86864 100644 --- a/data/conf/samples/loaders/tutmongo/cgrates.json +++ b/data/conf/samples/loaders/tutmongo/cgrates.json @@ -86,35 +86,29 @@ "loaders": [ { - "id": "CustomLoader", - "enabled": true, + "id": "CustomLoader", + "enabled": true, "dry_run": false, - "run_delay": "0", - "lockfile_path": ".cgr.lock", + "tenant": "cgrates.org", + "run_delay": "0", + "lockfile_path": ".cgr.lock", "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/In", - "tp_out_dir": "/tmp/Out", + "field_separator": ",", + "tp_in_dir": "/tmp/In", + "tp_out_dir": "/tmp/Out", "data":[ { "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], }, { - "id": "WithoutMoveToOut", + "id": "WithoutMoveToOut", "enabled": true, "dry_run": false, "tenant": "cgrates.org", @@ -129,15 +123,8 @@ "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -158,15 +145,8 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -187,34 +167,27 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], }, { - "id": "LoaderWithTemplate", - "enabled": true, - "dry_run": false, + "id": "LoaderWithTemplate", + "enabled": true, + "dry_run": false, "tenant": "cgrates.org", - "run_delay": "0", - "lockfile_path": ".cgr.lock", + "run_delay": "0", + "lockfile_path": ".cgr.lock", "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/templateLoaderIn", - "tp_out_dir": "/tmp/templateLoaderOut", + "field_separator": ",", + "tp_in_dir": "/tmp/templateLoaderIn", + "tp_out_dir": "/tmp/templateLoaderOut", "data":[ { - "type": "*attributes", - "file_name": "Attributes.csv", + "type": "*attributes", + "file_name": "Attributes.csv", "fields": [ {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} ], @@ -237,12 +210,12 @@ "type": "*attributes", "file_name": "Attributes", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "*req.Destination"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "*constant"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.1"}, + {"path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, + {"path": "Attributes.Path", "type": "*variable", "value": "*req.Destination"}, + {"path": "Attributes.Type", "type": "*variable", "value": "*constant"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.1"}, ], }, ], @@ -271,21 +244,20 @@ "templates": { "attrTemplateLoader": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, + {"path": "Weight", "type": "*variable", "value": "~*req.3"}, + {"path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4","new_branch":true}, + {"path": "Attributes.Path", "type": "*variable", "value": "~*req.5"}, + {"path": "Attributes.Type", "type": "*variable", "value": "~*req.6"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.7"}, + {"path": "Blocker", "type": "*variable", "value": "~*req.8"}, ], }, - - "admins": { +"admins": { "enabled": true, "scheduler_conns": ["*internal"], }, diff --git a/data/conf/samples/loaders/tutmysql/cgrates.json b/data/conf/samples/loaders/tutmysql/cgrates.json index d5e5896b1..8d8a1a547 100644 --- a/data/conf/samples/loaders/tutmysql/cgrates.json +++ b/data/conf/samples/loaders/tutmysql/cgrates.json @@ -46,36 +46,29 @@ "loaders": [ { - "id": "CustomLoader", - "enabled": true, + "id": "CustomLoader", + "enabled": true, "dry_run": false, "tenant": "cgrates.org", - "run_delay": "0", - "lockfile_path": ".cgr.lock", + "run_delay": "0", + "lockfile_path": ".cgr.lock", "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/In", - "tp_out_dir": "/tmp/Out", + "field_separator": ",", + "tp_in_dir": "/tmp/In", + "tp_out_dir": "/tmp/Out", "data":[ { "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], }, { - "id": "WithoutMoveToOut", + "id": "WithoutMoveToOut", "enabled": true, "dry_run": false, "tenant": "cgrates.org", @@ -90,15 +83,8 @@ "type": "*attributes", "file_name": "Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -119,15 +105,8 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], @@ -148,34 +127,27 @@ "type": "*attributes", "file_name": "folder1/Attributes.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} + ], }, ], }, { - "id": "LoaderWithTemplate", - "enabled": true, - "dry_run": false, + "id": "LoaderWithTemplate", + "enabled": true, + "dry_run": false, "tenant": "cgrates.org", - "run_delay": "0", - "lockfile_path": ".cgr.lock", + "run_delay": "0", + "lockfile_path": ".cgr.lock", "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/templateLoaderIn", - "tp_out_dir": "/tmp/templateLoaderOut", + "field_separator": ",", + "tp_in_dir": "/tmp/templateLoaderIn", + "tp_out_dir": "/tmp/templateLoaderOut", "data":[ { - "type": "*attributes", - "file_name": "Attributes.csv", + "type": "*attributes", + "file_name": "Attributes.csv", "fields": [ {"tag": "AttributesFields","type": "*template", "value": "attrTemplateLoader"} ], @@ -198,12 +170,12 @@ "type": "*attributes", "file_name": "Attributes", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "*req.Destination"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "*constant"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.1"}, + {"path": "Tenant", "type": "*variable", "value": "cgrates.org", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "ATTR_;~*req.0", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "`*string:~*req.Destination:`;~*req.0"}, + {"path": "Attributes.Path", "type": "*variable", "value": "*req.Destination"}, + {"path": "Attributes.Type", "type": "*variable", "value": "*constant"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.1"}, ], }, ], @@ -211,7 +183,6 @@ ], - "attributes": { "enabled": true, "prefix_indexed_fields":["*req.Destination"], @@ -270,20 +241,19 @@ "templates": { "attrTemplateLoader": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, - {"tag": "AttributeFilterIDs", "path": "AttributeFilterIDs", "type": "*variable", "value": "~*req.4"}, - {"tag": "Path", "path": "Path", "type": "*variable", "value": "~*req.5"}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~*req.6"}, - {"tag": "Value", "path": "Value", "type": "*variable", "value": "~*req.7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~*req.8"}, + {"path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, + {"path": "Weight", "type": "*variable", "value": "~*req.3"}, + {"path": "Attributes.FilterIDs", "type": "*variable", "value": "~*req.4","new_branch":true}, + {"path": "Attributes.Path", "type": "*variable", "value": "~*req.5"}, + {"path": "Attributes.Type", "type": "*variable", "value": "~*req.6"}, + {"path": "Attributes.Value", "type": "*variable", "value": "~*req.7"}, + {"path": "Blocker", "type": "*variable", "value": "~*req.8"}, ], }, - "admins": { "enabled": true, "scheduler_conns": ["*internal"], diff --git a/data/conf/samples/preload_internal/cgrates.json b/data/conf/samples/preload_internal/cgrates.json index a091b6496..3f78b7999 100644 --- a/data/conf/samples/preload_internal/cgrates.json +++ b/data/conf/samples/preload_internal/cgrates.json @@ -31,23 +31,23 @@ "type": "*rate_profiles", "file_name": "Rates.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"tag": "ID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, {"tag": "MinCost", "path": "MinCost", "type": "*variable", "value": "~*req.4"}, {"tag": "MaxCost", "path": "MaxCost", "type": "*variable", "value": "~*req.5"}, {"tag": "MaxCostStrategy", "path": "MaxCostStrategy", "type": "*variable", "value": "~*req.6"}, - {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, - {"tag": "RateFilterIDs", "path": "RateFilterIDs", "type": "*variable", "value": "~*req.8"}, - {"tag": "RateActivationTimes", "path": "RateActivationTimes", "type": "*variable", "value": "~*req.9"}, - {"tag": "RateWeights", "path": "RateWeights", "type": "*variable", "value": "~*req.10"}, - {"tag": "RateBlocker", "path": "RateBlocker", "type": "*variable", "value": "~*req.11"}, - {"tag": "RateIntervalStart", "path": "RateIntervalStart", "type": "*variable", "value": "~*req.12"}, - {"tag": "RateFixedFee", "path": "RateFixedFee", "type": "*variable", "value": "~*req.13"}, - {"tag": "RateRecurrentFee", "path": "RateRecurrentFee", "type": "*variable", "value": "~*req.14"}, - {"tag": "RateUnit", "path": "RateUnit", "type": "*variable", "value": "~*req.15"}, - {"tag": "RateIncrement", "path": "RateIncrement", "type": "*variable", "value": "~*req.16"}, + // {"tag": "RateID", "path": "RateID", "type": "*variable", "value": "~*req.7"}, + {"tag": "RateFilterIDs", "path": "Rates[<~*req.7>].FilterIDs", "type": "*variable", "value": "~*req.8"}, + {"tag": "RateActivationTimes", "path": "Rates[<~*req.7>].ActivationTimes", "type": "*variable", "value": "~*req.9"}, + {"tag": "RateWeights", "path": "Rates[<~*req.7>].Weights", "type": "*variable", "value": "~*req.10"}, + {"tag": "RateBlocker", "path": "Rates[<~*req.7>].Blocker", "type": "*variable", "value": "~*req.11"}, + {"tag": "RateIntervalStart", "path": "Rates[<~*req.7>].IntervalRates.IntervalStart", "type": "*variable", "value": "~*req.12","new_branch":true}, + {"tag": "RateFixedFee", "path": "Rates[<~*req.7>].IntervalRates.FixedFee", "type": "*variable", "value": "~*req.13"}, + {"tag": "RateRecurrentFee", "path": "Rates[<~*req.7>].IntervalRates.RecurrentFee", "type": "*variable", "value": "~*req.14"}, + {"tag": "RateUnit", "path": "Rates[<~*req.7>].IntervalRates.Unit", "type": "*variable", "value": "~*req.15"}, + {"tag": "RateIncrement", "path": "Rates[<~*req.7>].IntervalRates.Increment", "type": "*variable", "value": "~*req.16"}, ], }, ], @@ -68,21 +68,21 @@ "type": "*accounts", "file_name": "Accounts.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"tag": "ID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, {"tag": "Opts", "path": "Opts", "type": "*variable", "value": "~*req.4"}, - {"tag": "BalanceID", "path": "BalanceID", "type": "*variable", "value": "~*req.5"}, - {"tag": "BalanceFilterIDs", "path": "BalanceFilterIDs", "type": "*variable", "value": "~*req.6"}, - {"tag": "BalanceWeights", "path": "BalanceWeights", "type": "*variable", "value": "~*req.7"}, - {"tag": "BalanceType", "path": "BalanceType", "type": "*variable", "value": "~*req.8"}, - {"tag": "BalanceUnits", "path": "BalanceUnits", "type": "*variable", "value": "~*req.9"}, - {"tag": "BalanceUnitFactors", "path": "BalanceUnitFactors", "type": "*variable", "value": "~*req.10"}, - {"tag": "BalanceOpts", "path": "BalanceOpts", "type": "*variable", "value": "~*req.11"}, - {"tag": "BalanceCostIncrements", "path": "BalanceCostIncrements", "type": "*variable", "value": "~*req.12"}, - {"tag": "BalanceAttributeIDs", "path": "BalanceAttributeIDs", "type": "*variable", "value": "~*req.13"}, - {"tag": "BalanceRateProfileIDs", "path": "BalanceRateProfileIDs", "type": "*variable", "value": "~*req.14"}, + // {"tag": "BalanceID", "path": "Balances.ID", "type": "*variable", "value": "~*req.5"}, + {"tag": "BalanceFilterIDs", "path": "Balances[<~*req.5>].FilterIDs", "type": "*variable", "value": "~*req.6"}, + {"tag": "BalanceWeights", "path": "Balances[<~*req.5>].Weights", "type": "*variable", "value": "~*req.7"}, + {"tag": "BalanceType", "path": "Balances[<~*req.5>].Type", "type": "*variable", "value": "~*req.8"}, + {"tag": "BalanceUnits", "path": "Balances[<~*req.5>].Units", "type": "*variable", "value": "~*req.9"}, + {"tag": "BalanceUnitFactors", "path": "Balances[<~*req.5>].UnitFactors", "type": "*variable", "value": "~*req.10"}, + {"tag": "BalanceOpts", "path": "Balances[<~*req.5>].Opts", "type": "*variable", "value": "~*req.11"}, + {"tag": "BalanceCostIncrements", "path": "Balances[<~*req.5>].CostIncrements", "type": "*variable", "value": "~*req.12"}, + {"tag": "BalanceAttributeIDs", "path": "Balances[<~*req.5>].AttributeIDs", "type": "*variable", "value": "~*req.13"}, + {"tag": "BalanceRateProfileIDs", "path": "Balances[<~*req.5>].RateProfileIDs", "type": "*variable", "value": "~*req.14"}, {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~*req.15"}, ], }, @@ -104,21 +104,21 @@ "type": "*action_profiles", "file_name": "Actions.csv", "fields": [ - {"tag": "TenantID", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, - {"tag": "ProfileID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, + {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~*req.0", "mandatory": true}, + {"tag": "ID", "path": "ID", "type": "*variable", "value": "~*req.1", "mandatory": true}, {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~*req.2"}, - {"tag": "Weights", "path": "Weights", "type": "*variable", "value": "~*req.3"}, + {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~*req.3"}, {"tag": "Schedule", "path": "Schedule", "type": "*variable", "value": "~*req.4"}, - {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, - {"tag": "TargetIDs", "path": "TargetIDs", "type": "*variable", "value": "~*req.6"}, - {"tag": "ActionID", "path": "ActionID", "type": "*variable", "value": "~*req.7"}, - {"tag": "ActionFilterIDs", "path": "ActionFilterIDs", "type": "*variable", "value": "~*req.8"}, - {"tag": "ActionBlocker", "path": "ActionBlocker", "type": "*variable", "value": "~*req.9"}, - {"tag": "ActionTTL", "path": "ActionTTL", "type": "*variable", "value": "~*req.10"}, - {"tag": "ActionType", "path": "ActionType", "type": "*variable", "value": "~*req.11"}, - {"tag": "ActionOpts", "path": "ActionOpts", "type": "*variable", "value": "~*req.12"}, - {"tag": "ActionPath", "path": "ActionPath", "type": "*variable", "value": "~*req.13"}, - {"tag": "ActionValue", "path": "ActionValue", "type": "*variable", "value": "~*req.14"}, + // {"tag": "TargetType", "path": "TargetType", "type": "*variable", "value": "~*req.5"}, + {"tag": "TargetIDs", "path": "Targets[<~*req.5>]", "type": "*variable", "value": "~*req.6"}, + {"tag": "ActionID", "path": "Actions.ID", "type": "*variable", "value": "~*req.7"}, + {"tag": "ActionFilterIDs", "path": "Actions.FilterIDs", "type": "*variable", "value": "~*req.8"}, + {"tag": "ActionBlocker", "path": "Actions.Blocker", "type": "*variable", "value": "~*req.9"}, + {"tag": "ActionTTL", "path": "Actions.TTL", "type": "*variable", "value": "~*req.10"}, + {"tag": "ActionType", "path": "Actions.Type", "type": "*variable", "value": "~*req.11"}, + {"tag": "ActionOpts", "path": "Actions.Opts", "type": "*variable", "value": "~*req.12"}, + {"tag": "ActionPath", "path": "Actions.Path", "type": "*variable", "value": "~*req.13"}, + {"tag": "ActionValue", "path": "Actions.Value", "type": "*variable", "value": "~*req.14"}, ], }, ], diff --git a/data/conf/samples/tutmysql_internal/cgrates.json b/data/conf/samples/tutmysql_internal/cgrates.json deleted file mode 100644 index bb8131105..000000000 --- a/data/conf/samples/tutmysql_internal/cgrates.json +++ /dev/null @@ -1,227 +0,0 @@ -{ -// CGRateS Configuration file -// - - -"general": { - "log_level": 7, -}, - - -"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"], -}, - - -"schedulers": { - "enabled": true, - "cdrs_conns": ["*internal"], -}, - - -"cdrs": { - "enabled": true, - "chargers_conns":["*internal"], -}, - - -"loaders": [ - { - "id": "TeoLoader", - "enabled": false, - "dry_run": false, - "run_delay": "0", - "lockfile_path": ".cgr.lock", - "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/In", - "tp_out_dir": "/tmp/Out", - "data":[ - { - "type": "*resources", - "file_name": "Resources.csv", - "fields": [ - {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, - {"tag": "ID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~3"}, - {"tag": "TTL", "path": "UsageTTL", "type": "*variable", "value": "~4"}, - {"tag": "Limit", "path": "Limit", "type": "*variable", "value": "~5"}, - {"tag": "AllocationMessage", "path": "AllocationMessage", "type": "*variable", "value": "~6"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~7"}, - {"tag": "Stored", "path": "Stored", "type": "*variable", "value": "~8"}, - {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~9"}, - ], - }, - { - "type": "*stats", - "file_name": "Stats.csv", - "fields": [ - {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, - {"tag": "ID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~3"}, - {"tag": "QueueLength", "path": "QueueLength", "type": "*variable", "value": "~4"}, - {"tag": "TTL", "path": "TTL", "type": "*variable", "value": "~5"}, - {"tag": "Metrics", "path": "Metrics", "type": "*variable", "value": "~6"}, - {"tag": "MetricParams", "path": "Parameters", "type": "*variable", "value": "~7"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~8"}, - {"tag": "Stored", "path": "Stored", "type": "*variable", "value": "~9"}, - {"tag": "MinItems", "path": "MinItems", "type": "*variable", "value": "~10"}, - {"tag": "ThresholdIDs", "path": "ThresholdIDs", "type": "*variable", "value": "~11"}, - ], - }, - { - "type": "*thresholds", - "file_name": "Thresholds.csv", - "fields": [ - {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, - {"tag": "ID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~3"}, - {"tag": "MaxHits", "path": "MaxHits", "type": "*variable", "value": "~4"}, - {"tag": "MinHits", "path": "MinHits", "type": "*variable", "value": "~5"}, - {"tag": "MinSleep", "path": "MinSleep", "type": "*variable", "value": "~6"}, - {"tag": "Blocker", "path": "Blocker", "type": "*variable", "value": "~7"}, - {"tag": "ActionProfileIDs", "path": "ActionProfileIDs", "type": "*variable", "value": "~8"}, - {"tag": "Async", "path": "Async", "type": "*variable", "value": "~9"}, - ], - }, - { - "type": "*routes", - "file_name": "Routes.csv", - "fields": [ - {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, - {"tag": "ID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, - {"tag": "FilterIDs", "path": "FilterIDs", "type": "*variable", "value": "~2"}, - {"tag": "Weight", "path": "Weight", "type": "*variable", "value": "~3"}, - {"tag": "Sorting", "path": "Sorting", "type": "*variable", "value": "~4"}, - {"tag": "SortingParamameters", "path": "SortingParamameters", "type": "*variable", "value": "~5"}, - {"tag": "SupplierID", "path": "SupplierID", "type": "*variable", "value": "~6"}, - {"tag": "SupplierFilterIDs", "path": "SupplierFilterIDs", "type": "*variable", "value": "~7"}, - {"tag": "SupplierAccountIDs", "path": "SupplierAccountIDs", "type": "*variable", "value": "~8"}, - {"tag": "RouteRateProfileIDs", "path": "RouteRateProfileIDs", "type": "*variable", "value": "~9"}, - {"tag": "SupplierResourceIDs", "path": "SupplierResourceIDs", "type": "*variable", "value": "~10"}, - {"tag": "SupplierStatIDs", "path": "SupplierStatIDs", "type": "*variable", "value": "~11"}, - {"tag": "SupplierWeight", "path": "SupplierWeight", "type": "*variable", "value": "~12"}, - {"tag": "SupplierBlocker", "path": "SupplierBlocker", "type": "*variable", "value": "~13"}, - {"tag": "SupplierParameters", "path": "SupplierParameters", "type": "*variable", "value": "~14"}, - ], - }, - ], - }, - { - "id": "FilterLoader", - "enabled": false, - "dry_run": false, - "run_delay": "0", - "lockfile_path": ".cgr.lock", - "caches_conns": ["*internal"], - "field_separator": ",", - "tp_in_dir": "/tmp/FilterIn", - "tp_out_dir": "/tmp/FilterOut", - "data":[ - { - "type": "*filters", - "file_name": "Filters.csv", - "fields": [ - {"tag": "Tenant", "path": "Tenant", "type": "*variable", "value": "~0", "mandatory": true}, - {"tag": "ID", "path": "ID", "type": "*variable", "value": "~1", "mandatory": true}, - {"tag": "Type", "path": "Type", "type": "*variable", "value": "~2"}, - {"tag": "Element", "path": "Element", "type": "*variable", "value": "~3"}, - {"tag": "Values", "path": "Values", "type": "*variable", "value": "~4"}, - ], - }, - ], - }, -], - - - -"attributes": { - "enabled": true, -}, - - -"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"], -}, - - -"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,"enabled": true, - "scheduler_conns": ["*internal"], -}, - - -"filters": { - "accounts_conns": ["*internal"], -}, - -"accounts": { - "enabled": true -}, - -} diff --git a/engine/actionprofile.go b/engine/actionprofile.go index 358959547..540fb7fe2 100644 --- a/engine/actionprofile.go +++ b/engine/actionprofile.go @@ -98,7 +98,7 @@ func (aP *ActionProfile) Set(path []string, val interface{}, newBranch bool, _ s path[0][7] == '[' && path[0][len(path[0])-1] == ']' { var valA []string valA, err = utils.IfaceAsStringSlice(val) - aP.Targets[path[0][8:len(path[0])-1]] = utils.NewStringSet(valA) + aP.Targets[path[0][8:len(path[0])-1]] = utils.JoinStringSet(aP.Targets[path[0][8:len(path[0])-1]], utils.NewStringSet(valA)) return } return utils.ErrWrongPath @@ -109,16 +109,20 @@ func (aP *ActionProfile) Set(path []string, val interface{}, newBranch bool, _ s case utils.Schedule: aP.Schedule = utils.IfaceAsString(val) case utils.FilterIDs: - aP.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + aP.FilterIDs = append(aP.FilterIDs, valA...) case utils.Weight: - aP.Weight, err = utils.IfaceAsFloat64(val) + if val != utils.EmptyString { + aP.Weight, err = utils.IfaceAsFloat64(val) + } } return case 2: if path[0] == utils.Targets { var valA []string valA, err = utils.IfaceAsStringSlice(val) - aP.Targets[path[1]] = utils.NewStringSet(valA) + aP.Targets[path[1]] = utils.JoinStringSet(aP.Targets[path[1]], utils.NewStringSet(valA)) return } default: @@ -173,11 +177,15 @@ func (aP *APAction) Set(path []string, val interface{}, newBranch bool) (err err case utils.Type: aP.Type = utils.IfaceAsString(val) case utils.FilterIDs: - aP.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + aP.FilterIDs = append(aP.FilterIDs, valA...) case utils.Blocker: aP.Blocker, err = utils.IfaceAsBool(val) case utils.TTL: aP.TTL, err = utils.IfaceAsDuration(val) + case utils.Opts: + aP.Opts, err = utils.NewMapFromCSV(utils.IfaceAsString(val)) } case 2: switch path[0] { diff --git a/engine/dispatcherprfl.go b/engine/dispatcherprfl.go index a9954066f..62819fb6b 100644 --- a/engine/dispatcherprfl.go +++ b/engine/dispatcherprfl.go @@ -207,11 +207,15 @@ func (dP *DispatcherProfile) Set(path []string, val interface{}, newBranch bool, case utils.ID: dP.ID = utils.IfaceAsString(val) case utils.FilterIDs: - dP.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + dP.FilterIDs = append(dP.FilterIDs, valA...) case utils.Strategy: dP.Strategy = utils.IfaceAsString(val) case utils.Weight: dP.Weight, err = utils.IfaceAsFloat64(val) + case utils.StrategyParams: + dP.StrategyParams, err = utils.NewMapFromCSV(utils.IfaceAsString(val)) } case 2: switch path[0] { @@ -227,11 +231,15 @@ func (dP *DispatcherProfile) Set(path []string, val interface{}, newBranch bool, case utils.ID: dP.Hosts[len(dP.Hosts)-1].ID = utils.IfaceAsString(val) case utils.FilterIDs: - dP.Hosts[len(dP.Hosts)-1].FilterIDs, err = utils.IfaceAsStringSlice(val) - case utils.Weights: + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + dP.Hosts[len(dP.Hosts)-1].FilterIDs = append(dP.Hosts[len(dP.Hosts)-1].FilterIDs, valA...) + case utils.Weight: dP.Hosts[len(dP.Hosts)-1].Weight, err = utils.IfaceAsFloat64(val) case utils.Blocker: dP.Hosts[len(dP.Hosts)-1].Blocker, err = utils.IfaceAsBool(val) + case utils.Params: + dP.Hosts[len(dP.Hosts)-1].Params, err = utils.NewMapFromCSV(utils.IfaceAsString(val)) default: if strings.HasPrefix(path[0], utils.Params) && path[0][6] == '[' && path[0][len(path[0])-1] == ']' { diff --git a/engine/filters.go b/engine/filters.go index fa0ffd5a1..4e0797a12 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -722,3 +722,17 @@ func (fltr *Filter) Set(path []string, val interface{}, newBranch bool, _ string } return } + +func (fltr *Filter) Compress() { + newRules := make([]*FilterRule, 0, len(fltr.Rules)) + for i, flt := range fltr.Rules { + if i == 0 || + newRules[len(newRules)-1].Type != flt.Type || + newRules[len(newRules)-1].Element != flt.Element { + newRules = append(newRules, flt) + continue + } + newRules[len(newRules)-1].Values = append(newRules[len(newRules)-1].Values, flt.Values...) + } + fltr.Rules = newRules +} diff --git a/engine/libattributes.go b/engine/libattributes.go index 4f79b6bad..21fc7cf7b 100644 --- a/engine/libattributes.go +++ b/engine/libattributes.go @@ -196,11 +196,15 @@ func (ap *AttributeProfile) Set(path []string, val interface{}, newBranch bool, case utils.ID: ap.ID = utils.IfaceAsString(val) case utils.FilterIDs: - ap.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + ap.FilterIDs = append(ap.FilterIDs, valA...) case utils.Blocker: ap.Blocker, err = utils.IfaceAsBool(val) case utils.Weight: - ap.Weight, err = utils.IfaceAsFloat64(val) + if val != utils.EmptyString { + ap.Weight, err = utils.IfaceAsFloat64(val) + } default: return utils.ErrWrongPath } @@ -213,7 +217,9 @@ func (ap *AttributeProfile) Set(path []string, val interface{}, newBranch bool, } switch path[1] { case utils.FilterIDs: - ap.Attributes[len(ap.Attributes)-1].FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + ap.Attributes[len(ap.Attributes)-1].FilterIDs = append(ap.Attributes[len(ap.Attributes)-1].FilterIDs, valA...) case utils.Path: ap.Attributes[len(ap.Attributes)-1].Path = utils.IfaceAsString(val) case utils.Type: diff --git a/engine/libchargers.go b/engine/libchargers.go index f494b43cb..4ac7c016b 100644 --- a/engine/libchargers.go +++ b/engine/libchargers.go @@ -64,11 +64,15 @@ func (cp *ChargerProfile) Set(path []string, val interface{}, newBranch bool, _ case utils.ID: cp.ID = utils.IfaceAsString(val) case utils.FilterIDs: - cp.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + cp.FilterIDs = append(cp.FilterIDs, valA...) case utils.RunID: cp.RunID = utils.IfaceAsString(val) case utils.AttributeIDs: - cp.AttributeIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + cp.AttributeIDs = append(cp.AttributeIDs, valA...) case utils.Weight: cp.Weight, err = utils.IfaceAsFloat64(val) } diff --git a/engine/libstats.go b/engine/libstats.go index d4b33ef2e..43da7492a 100644 --- a/engine/libstats.go +++ b/engine/libstats.go @@ -566,9 +566,13 @@ func (sqp *StatQueueProfile) Set(path []string, val interface{}, newBranch bool, case utils.Weight: sqp.Weight, err = utils.IfaceAsFloat64(val) case utils.FilterIDs: - sqp.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + sqp.FilterIDs = append(sqp.FilterIDs, valA...) case utils.ThresholdIDs: - sqp.ThresholdIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + sqp.ThresholdIDs = append(sqp.ThresholdIDs, valA...) } case 2: if path[0] != utils.Metrics { @@ -579,9 +583,15 @@ func (sqp *StatQueueProfile) Set(path []string, val interface{}, newBranch bool, } switch path[1] { case utils.FilterIDs: - sqp.Metrics[len(sqp.Metrics)-1].FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + sqp.Metrics[len(sqp.Metrics)-1].FilterIDs = append(sqp.Metrics[len(sqp.Metrics)-1].FilterIDs, valA...) case utils.MetricID: - sqp.Metrics[len(sqp.Metrics)-1].MetricID = utils.IfaceAsString(val) + valA := utils.InfieldSplit(utils.IfaceAsString(val)) + sqp.Metrics[len(sqp.Metrics)-1].MetricID = valA[0] + for _, mID := range valA[1:] { // add the rest of the metrics + sqp.Metrics = append(sqp.Metrics, &MetricWithFilters{MetricID: mID}) + } default: return utils.ErrWrongPath } diff --git a/engine/resources.go b/engine/resources.go index f10281c40..24dae601e 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -1032,7 +1032,9 @@ func (rp *ResourceProfile) Set(path []string, val interface{}, _ bool, _ string) case utils.ID: rp.ID = utils.IfaceAsString(val) case utils.FilterIDs: - rp.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rp.FilterIDs = append(rp.FilterIDs, valA...) case utils.UsageTTL: rp.UsageTTL, err = utils.IfaceAsDuration(val) case utils.Limit: @@ -1046,7 +1048,9 @@ func (rp *ResourceProfile) Set(path []string, val interface{}, _ bool, _ string) case utils.Weight: rp.Weight, err = utils.IfaceAsFloat64(val) case utils.ThresholdIDs: - rp.ThresholdIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rp.ThresholdIDs = append(rp.ThresholdIDs, valA...) } return } diff --git a/engine/routes.go b/engine/routes.go index d39134701..481d39b2a 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -466,9 +466,13 @@ func (rp *RouteProfile) Set(path []string, val interface{}, newBranch bool, _ st case utils.ID: rp.ID = utils.IfaceAsString(val) case utils.FilterIDs: - rp.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rp.FilterIDs = append(rp.FilterIDs, valA...) case utils.SortingParameters: - rp.SortingParameters, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rp.SortingParameters = append(rp.SortingParameters, valA...) case utils.Sorting: rp.Sorting = utils.IfaceAsString(val) case utils.Weights: @@ -481,25 +485,36 @@ func (rp *RouteProfile) Set(path []string, val interface{}, newBranch bool, _ st if len(rp.Routes) == 0 || newBranch { rp.Routes = append(rp.Routes, new(Route)) } + rt := rp.Routes[len(rp.Routes)-1] switch path[1] { case utils.ID: - rp.Routes[len(rp.Routes)-1].ID = utils.IfaceAsString(val) + rt.ID = utils.IfaceAsString(val) case utils.FilterIDs: - rp.Routes[len(rp.Routes)-1].FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rt.FilterIDs = append(rt.FilterIDs, valA...) case utils.AccountIDs: - rp.Routes[len(rp.Routes)-1].AccountIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rt.AccountIDs = append(rt.AccountIDs, valA...) case utils.RateProfileIDs: - rp.Routes[len(rp.Routes)-1].RateProfileIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rt.RateProfileIDs = append(rt.RateProfileIDs, valA...) case utils.ResourceIDs: - rp.Routes[len(rp.Routes)-1].ResourceIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rt.ResourceIDs = append(rt.ResourceIDs, valA...) case utils.StatIDs: - rp.Routes[len(rp.Routes)-1].StatIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + rt.StatIDs = append(rt.StatIDs, valA...) case utils.Weights: - rp.Routes[len(rp.Routes)-1].Weights, err = utils.NewDynamicWeightsFromString(utils.IfaceAsString(val), utils.InfieldSep, utils.ANDSep) + rt.Weights, err = utils.NewDynamicWeightsFromString(utils.IfaceAsString(val), utils.InfieldSep, utils.ANDSep) case utils.Blocker: - rp.Routes[len(rp.Routes)-1].Blocker, err = utils.IfaceAsBool(val) + rt.Blocker, err = utils.IfaceAsBool(val) case utils.RouteParameters: - rp.Routes[len(rp.Routes)-1].RouteParameters = utils.IfaceAsString(val) + rt.RouteParameters = utils.IfaceAsString(val) default: return utils.ErrWrongPath } diff --git a/engine/thresholds.go b/engine/thresholds.go index f1f9f4c0f..385cf2fb7 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -607,7 +607,9 @@ func (tp *ThresholdProfile) Set(path []string, val interface{}, _ bool, _ string case utils.Weight: tp.Weight, err = utils.IfaceAsFloat64(val) case utils.FilterIDs: - tp.FilterIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + tp.FilterIDs = append(tp.FilterIDs, valA...) case utils.MaxHits: tp.MaxHits, err = utils.IfaceAsTInt(val) case utils.MinHits: @@ -615,7 +617,9 @@ func (tp *ThresholdProfile) Set(path []string, val interface{}, _ bool, _ string case utils.MinSleep: tp.MinSleep, err = utils.IfaceAsDuration(val) case utils.ActionProfileIDs: - tp.ActionProfileIDs, err = utils.IfaceAsStringSlice(val) + var valA []string + valA, err = utils.IfaceAsStringSlice(val) + tp.ActionProfileIDs = append(tp.ActionProfileIDs, valA...) case utils.Async: tp.Async, err = utils.IfaceAsBool(val) } diff --git a/loaders/libloader.go b/loaders/libloader.go index 35db6f441..8d9b38aa2 100644 --- a/loaders/libloader.go +++ b/loaders/libloader.go @@ -66,17 +66,17 @@ func (r *record) FieldAsString(path []string) (str string, err error) { return utils.IfaceAsString(val), nil } -func TenantIDFromDataProvider(data utils.DataProvider) *utils.TenantID { - tnt, _ := data.FieldAsString([]string{utils.Tenant}) - id, _ := data.FieldAsString([]string{utils.ID}) +func TenantIDFromOrderedNavigableMap(data *utils.OrderedNavigableMap) *utils.TenantID { + tnt, _ := data.FieldAsString([]string{utils.Tenant, "0"}) + id, _ := data.FieldAsString([]string{utils.ID, "0"}) return &utils.TenantID{ Tenant: tnt, ID: id, } } -func RateIDsFromDataProvider(data utils.DataProvider) ([]string, error) { - val, err := data.FieldAsInterface([]string{utils.RateIDs}) +func RateIDsFromOrderedNavigableMap(data *utils.OrderedNavigableMap) ([]string, error) { + val, err := data.FieldAsInterface([]string{utils.RateIDs, "0"}) if err != nil { return nil, fmt.Errorf("cannot find RateIDs in map") } @@ -294,18 +294,16 @@ type profile interface { func prepareData(prf profile, lData []*utils.OrderedNavigableMap, rsrSep string) (err error) { for _, mp := range lData { - newRow := true for el := mp.GetFirstElement(); el != nil; el = el.Next() { path := el.Value nmIt, _ := mp.Field(path) if nmIt == nil { - continue // all attributes, not writable to diameter packet + continue } - // path = path[:len(path)-1] // remove the last index - if err = prf.Set(path, nmIt.Data, nmIt.NewBranch || newRow, rsrSep); err != nil { + path = path[:len(path)-1] // remove the last index + if err = prf.Set(path, nmIt.Data, nmIt.NewBranch, rsrSep); err != nil { return } - newRow = false } } return diff --git a/loaders/libloader_test.go b/loaders/libloader_test.go index 3705e414a..6a33997be 100644 --- a/loaders/libloader_test.go +++ b/loaders/libloader_test.go @@ -31,10 +31,11 @@ import ( func TestTenantIDFromMap(t *testing.T) { exp := utils.NewTenantID("cgrates.org:ATTR1") - r := TenantIDFromDataProvider(utils.MapStorage{ - utils.Tenant: exp.Tenant, - utils.ID: exp.ID, - }) + r := TenantIDFromOrderedNavigableMap( + newOrderNavMap(utils.MapStorage{ + utils.Tenant: exp.Tenant, + utils.ID: exp.ID, + })) if !reflect.DeepEqual(r, exp) { t.Errorf("Expected %+v, received %+q", exp, r) } @@ -42,13 +43,13 @@ func TestTenantIDFromMap(t *testing.T) { func TestRateIDsFromMap(t *testing.T) { expErrMsg := "cannot find RateIDs in map" - if _, err := RateIDsFromDataProvider(utils.MapStorage{}); err == nil || err.Error() != expErrMsg { + if _, err := RateIDsFromOrderedNavigableMap(newOrderNavMap(utils.MapStorage{})); err == nil || err.Error() != expErrMsg { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } exp := []string{"RT1", "RT2"} - r, err := RateIDsFromDataProvider(utils.MapStorage{ + r, err := RateIDsFromOrderedNavigableMap(newOrderNavMap(utils.MapStorage{ utils.RateIDs: "RT1;RT2", - }) + })) if err != nil { t.Fatal(err) } diff --git a/loaders/loader.go b/loaders/loader.go index 2eff8d03a..957271025 100644 --- a/loaders/loader.go +++ b/loaders/loader.go @@ -36,7 +36,7 @@ const ( gprefix = utils.MetaGoogleAPI + utils.ConcatenatedKeySep ) -func removeFromDB(ctx *context.Context, dm *engine.DataManager, lType, tnt, id string, withIndex, ratesPartial bool, ratesData utils.DataProvider) (_ error) { +func removeFromDB(ctx *context.Context, dm *engine.DataManager, lType, tnt, id string, withIndex, ratesPartial bool, ratesData *utils.OrderedNavigableMap) (_ error) { switch lType { case utils.MetaAttributes: return dm.RemoveAttributeProfile(ctx, tnt, id, withIndex) @@ -58,7 +58,7 @@ func removeFromDB(ctx *context.Context, dm *engine.DataManager, lType, tnt, id s return dm.RemoveDispatcherHost(ctx, tnt, id) case utils.MetaRateProfiles: if ratesPartial { - rateIDs, err := RateIDsFromDataProvider(ratesData) + rateIDs, err := RateIDsFromOrderedNavigableMap(ratesData) if err != nil { return err } @@ -101,6 +101,7 @@ func setToDB(ctx *context.Context, dm *engine.DataManager, lType, rsrSep string, if err = prepareData(fltr, lDataSet, rsrSep); err != nil { return } + fltr.Compress() if err = fltr.Compile(); err != nil { return } @@ -237,6 +238,7 @@ func dryRun(ctx *context.Context, lType, rsrSep, ldrID string, tntID *utils.Tena if err = prepareData(fltr, lDataSet, rsrSep); err != nil { return } + fltr.Compress() if err = fltr.Compile(); err != nil { return } @@ -467,7 +469,7 @@ func (l *loader) processData(ctx *context.Context, csv CSVReader, tmpls []*confi utils.LoaderS, l.ldrCfg.ID, csv.Path(), lineNr, err)) return } - tntID := TenantIDFromDataProvider(data) + tntID := TenantIDFromOrderedNavigableMap(data) if !prevTntID.Equal(tntID) { if prevTntID != nil { if err = l.process(ctx, prevTntID, lData, lType, action, caching, withIndex, partialRates); err != nil { diff --git a/loaders/loader_it_test.go b/loaders/loader_it_test.go index 065bc3d86..cd600883c 100644 --- a/loaders/loader_it_test.go +++ b/loaders/loader_it_test.go @@ -238,10 +238,9 @@ func testLoaderCheckAttributes(t *testing.T) { Type: utils.MetaVariable, Value: "Sub1", }, { - FilterIDs: []string{}, - Path: utils.MetaReq + utils.NestingSep + "Field2", - Type: utils.MetaVariable, - Value: "Sub2", + Path: utils.MetaReq + utils.NestingSep + "Field2", + Type: utils.MetaVariable, + Value: "Sub2", }}, Blocker: true, Weight: 20, @@ -284,10 +283,9 @@ func testLoaderCheckForCustomSep(t *testing.T) { FilterIDs: []string{"*string:~*req.Destination:12012000001"}, Attributes: []*engine.ExternalAttribute{ { - FilterIDs: []string{}, - Path: "*req.Destination", - Type: utils.MetaConstant, - Value: "12018209998", + Path: "*req.Destination", + Type: utils.MetaConstant, + Value: "12018209998", }, }, } diff --git a/loaders/loader_test.go b/loaders/loader_test.go index 3372ab6fd..a35e7956b 100644 --- a/loaders/loader_test.go +++ b/loaders/loader_test.go @@ -46,18 +46,18 @@ func TestRemoveFromDB(t *testing.T) { for _, lType := range []string{utils.MetaAttributes, utils.MetaResources, utils.MetaFilters, utils.MetaStats, utils.MetaThresholds, utils.MetaRoutes, utils.MetaChargers, utils.MetaDispatchers, utils.MetaDispatcherHosts, utils.MetaRateProfiles, utils.MetaActionProfiles, utils.MetaAccounts} { - if err := removeFromDB(context.Background(), dm, lType, "cgrates.org", "ID", true, false, utils.MapStorage{}); err != utils.ErrNotFound { + if err := removeFromDB(context.Background(), dm, lType, "cgrates.org", "ID", true, false, utils.NewOrderedNavigableMap()); err != utils.ErrNotFound { t.Error(err) } } expErrMsg := "cannot find RateIDs in map" - if err := removeFromDB(context.Background(), dm, utils.MetaRateProfiles, "cgrates.org", "ID", true, true, utils.MapStorage{}); err == nil || err.Error() != expErrMsg { + if err := removeFromDB(context.Background(), dm, utils.MetaRateProfiles, "cgrates.org", "ID", true, true, utils.NewOrderedNavigableMap()); err == nil || err.Error() != expErrMsg { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } - if err := removeFromDB(context.Background(), dm, utils.MetaRateProfiles, "cgrates.org", "ID", true, true, utils.MapStorage{utils.RateIDs: "RT1"}); err != utils.ErrNotFound { + if err := removeFromDB(context.Background(), dm, utils.MetaRateProfiles, "cgrates.org", "ID", true, true, newOrderNavMap(utils.MapStorage{utils.RateIDs: "RT1"})); err != utils.ErrNotFound { t.Error(err) } - if err := removeFromDB(context.Background(), dm, utils.EmptyString, "cgrates.org", "ID", true, false, utils.MapStorage{}); err != nil { + if err := removeFromDB(context.Background(), dm, utils.EmptyString, "cgrates.org", "ID", true, false, utils.NewOrderedNavigableMap()); err != nil { t.Error(err) } } @@ -70,14 +70,14 @@ func testDryRunWithData(lType string, data []utils.MapStorage) (string, error) { var buf bytes.Buffer utils.Logger = utils.NewStdLoggerWithWriter(&buf, "", 7) - err := dryRun(context.Background(), lType, utils.InfieldSep, "test", TenantIDFromDataProvider(data[0]), data) + err := dryRun(context.Background(), lType, utils.InfieldSep, "test", TenantIDFromOrderedNavigableMap(data[0]), data) return buf.String(), err } func testDryRun(t *testing.T, lType string) string { data := utils.NewOrderedNavigableMap() - data.Set(utils.NewFullPath(utils.Tenant), "cgrates.org") - data.Set(utils.NewFullPath(utils.ID), "ID") + data.SetAsSlice(utils.NewFullPath(utils.Tenant), []*utils.DataNode{utils.NewLeafNode("cgrates.org")}) + data.SetAsSlice(utils.NewFullPath(utils.ID), []*utils.DataNode{utils.NewLeafNode("ID")}) buf, err := testDryRunWithData(lType, []*utils.OrderedNavigableMap{data}) if err != nil { t.Fatal(lType, err) @@ -88,7 +88,7 @@ func testDryRun(t *testing.T, lType string) string { func newOrderNavMap(mp utils.MapStorage) (o *utils.OrderedNavigableMap) { o = utils.NewOrderedNavigableMap() for k, v := range mp { - o.Set(utils.NewFullPath(k), v) + o.SetAsSlice(utils.NewFullPath(k), []*utils.DataNode{utils.NewLeafNode(v)}) } return } @@ -101,7 +101,7 @@ func TestDryRun(t *testing.T) { testDryRun(t, utils.MetaResources); !strings.Contains(rplyLog, expLog) { t.Errorf("Expected %+q, received %+q", expLog, rplyLog) } - if expLog, rplyLog := "[INFO] DRY_RUN: Filter: {\"Tenant\":\"cgrates.org\",\"ID\":\"ID\",\"Rules\":null}", + if expLog, rplyLog := "[INFO] DRY_RUN: Filter: {\"Tenant\":\"cgrates.org\",\"ID\":\"ID\",\"Rules\":[]}", testDryRun(t, utils.MetaFilters); !strings.Contains(rplyLog, expLog) { t.Errorf("Expected %+q, received %+q", expLog, rplyLog) } @@ -174,20 +174,6 @@ func TestDryRunWithUpdateStructErrors(t *testing.T) { if _, err := testDryRunWithData(utils.MetaActionProfiles, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Weight: "notWeight"})}); err == nil || err.Error() != expErrMsg { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } - - expErrMsg = `cannot update unsupported struct field: 0` - if _, err := testDryRunWithData(utils.MetaRoutes, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if _, err := testDryRunWithData(utils.MetaDispatcherHosts, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if _, err := testDryRunWithData(utils.MetaRateProfiles, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if _, err := testDryRunWithData(utils.MetaAccounts, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } } func TestDryRunWithModelsErrors(t *testing.T) { @@ -218,14 +204,6 @@ func TestDryRunWithModelsErrors(t *testing.T) { if _, err := testDryRunWithData(utils.MetaDispatcherHosts, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "ReplyTimeout": "float", "Address": "127.0.0.1"})}); err == nil || err.Error() != expErrMsg { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } - - if _, err := testDryRunWithData(utils.MetaActionProfiles, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "ActionTTL": "float", "ActionID": "ACCT"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - expErrMsg = `invalid key: <1> for BalanceCostIncrements` - if _, err := testDryRunWithData(utils.MetaAccounts, []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "BalanceCostIncrements": "1", "BalanceID": "BalID"})}); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } } func TestSetToDBWithUpdateStructErrors(t *testing.T) { @@ -255,19 +233,6 @@ func TestSetToDBWithUpdateStructErrors(t *testing.T) { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } - expErrMsg = `cannot update unsupported struct field: 0` - if err := setToDB(context.Background(), nil, utils.MetaRoutes, utils.InfieldSep, utils.NewTenantID(""), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if err := setToDB(context.Background(), nil, utils.MetaDispatcherHosts, utils.InfieldSep, utils.NewTenantID(""), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if err := setToDB(context.Background(), nil, utils.MetaRateProfiles, utils.InfieldSep, utils.NewTenantID(""), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - if err := setToDB(context.Background(), nil, utils.MetaAccounts, utils.InfieldSep, utils.NewTenantID(""), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{"PK": "notWeight"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } } func TestSetToDBWithModelsErrors(t *testing.T) { @@ -297,14 +262,6 @@ func TestSetToDBWithModelsErrors(t *testing.T) { if err := setToDB(context.Background(), nil, utils.MetaDispatcherHosts, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "ReplyTimeout": "float", "Address": "127.0.0.1"})}, true, false); err == nil || err.Error() != expErrMsg { t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) } - - if err := setToDB(context.Background(), nil, utils.MetaActionProfiles, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "ActionTTL": "float", "ActionID": "ACCT"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } - expErrMsg = `invalid key: <1> for BalanceCostIncrements` - if err := setToDB(context.Background(), nil, utils.MetaAccounts, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", "BalanceCostIncrements": "1", "BalanceID": "BalID"})}, true, false); err == nil || err.Error() != expErrMsg { - t.Errorf("Expeceted: %v, received: %v", expErrMsg, err) - } } func TestSetToDBWithDBError(t *testing.T) { @@ -345,9 +302,6 @@ func TestSetToDBWithDBError(t *testing.T) { if err := setToDB(context.Background(), nil, utils.MetaRateProfiles, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != utils.ErrNoDatabaseConn { t.Fatal(err) } - if err := setToDB(context.Background(), nil, utils.MetaRateProfiles, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID", utils.RateIDs: "RT1;RT2"})}, true, true); err != utils.ErrNoDatabaseConn { - t.Fatal(err) - } if err := setToDB(context.Background(), nil, utils.MetaAccounts, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != utils.ErrNoDatabaseConn { t.Fatal(err) } @@ -379,7 +333,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaStats, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v3 := &engine.StatQueueProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, ThresholdIDs: []string{}, Metrics: []*engine.MetricWithFilters{}} + v3 := &engine.StatQueueProfile{Tenant: "cgrates.org", ID: "ID"} if prf, err := dm.GetStatQueueProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v3, prf) { @@ -389,7 +343,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaThresholds, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v4 := &engine.ThresholdProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, ActionProfileIDs: []string{}} + v4 := &engine.ThresholdProfile{Tenant: "cgrates.org", ID: "ID"} if prf, err := dm.GetThresholdProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v4, prf) { @@ -399,7 +353,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaChargers, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v5 := &engine.ChargerProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, AttributeIDs: []string{}} + v5 := &engine.ChargerProfile{Tenant: "cgrates.org", ID: "ID"} if prf, err := dm.GetChargerProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v5, prf) { @@ -409,7 +363,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaDispatchers, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v6 := &engine.DispatcherProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, StrategyParams: make(map[string]interface{}), Hosts: engine.DispatcherHostProfiles{}} + v6 := &engine.DispatcherProfile{Tenant: "cgrates.org", ID: "ID", StrategyParams: make(map[string]interface{})} if prf, err := dm.GetDispatcherProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v6, prf) { @@ -419,7 +373,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaActionProfiles, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v7 := &engine.ActionProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Targets: map[string]utils.StringSet{}, Actions: []*engine.APAction{}} + v7 := &engine.ActionProfile{Tenant: "cgrates.org", ID: "ID", Targets: map[string]utils.StringSet{}} if prf, err := dm.GetActionProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v7, prf) { @@ -429,7 +383,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaFilters, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v8 := &engine.Filter{Tenant: "cgrates.org", ID: "ID"} + v8 := &engine.Filter{Tenant: "cgrates.org", ID: "ID", Rules: make([]*engine.FilterRule, 0)} v8.Compile() if prf, err := dm.GetFilter(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) @@ -440,7 +394,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaRoutes, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v9 := &engine.RouteProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, SortingParameters: []string{}, Routes: []*engine.Route{}} + v9 := &engine.RouteProfile{Tenant: "cgrates.org", ID: "ID"} if prf, err := dm.GetRouteProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v9, prf) { @@ -460,7 +414,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaRateProfiles, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v11 := &utils.RateProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Rates: map[string]*utils.Rate{}, MinCost: utils.NewDecimal(0, 0), MaxCost: utils.NewDecimal(0, 0)} + v11 := &utils.RateProfile{Tenant: "cgrates.org", ID: "ID", Rates: map[string]*utils.Rate{}, MinCost: utils.NewDecimal(0, 0), MaxCost: utils.NewDecimal(0, 0)} if prf, err := dm.GetRateProfile(context.Background(), "cgrates.org", "ID", true, true, utils.NonTransactional); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v11, prf) { @@ -470,7 +424,7 @@ func TestSetToDB(t *testing.T) { if err := setToDB(context.Background(), dm, utils.MetaAccounts, utils.InfieldSep, utils.NewTenantID("cgrates.org:ID"), []*utils.OrderedNavigableMap{newOrderNavMap(utils.MapStorage{utils.Tenant: "cgrates.org", utils.ID: "ID"})}, true, false); err != nil { t.Fatal(err) } - v12 := &utils.Account{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Balances: map[string]*utils.Balance{}, ThresholdIDs: []string{}} + v12 := &utils.Account{Tenant: "cgrates.org", ID: "ID", Balances: map[string]*utils.Balance{}, Opts: make(map[string]interface{})} if prf, err := dm.GetAccount(context.Background(), "cgrates.org", "ID"); err != nil { t.Fatal(err) } else if !reflect.DeepEqual(v12, prf) { @@ -606,7 +560,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetStatQueueProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.StatQueueProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, ThresholdIDs: []string{}, Metrics: []*engine.MetricWithFilters{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.StatQueueProfile{Tenant: "cgrates.org", ID: "ID"}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{StatsQueueProfileIDs: []string{tntID}, StatsQueueIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -621,7 +575,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetThresholdProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.ThresholdProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, ActionProfileIDs: []string{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.ThresholdProfile{Tenant: "cgrates.org", ID: "ID"}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{ThresholdProfileIDs: []string{tntID}, ThresholdIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -636,7 +590,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetRouteProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.RouteProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, SortingParameters: []string{}, Routes: []*engine.Route{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.RouteProfile{Tenant: "cgrates.org", ID: "ID"}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{RouteProfileIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -651,7 +605,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetChargerProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.ChargerProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, AttributeIDs: []string{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.ChargerProfile{Tenant: "cgrates.org", ID: "ID"}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{ChargerProfileIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -666,7 +620,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetDispatcherProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.DispatcherProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, StrategyParams: make(map[string]interface{}), Hosts: engine.DispatcherHostProfiles{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.DispatcherProfile{Tenant: "cgrates.org", ID: "ID", StrategyParams: make(map[string]interface{})}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{DispatcherProfileIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -681,7 +635,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetRateProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&utils.RateProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Rates: map[string]*utils.Rate{}, MinCost: utils.NewDecimal(0, 0), MaxCost: utils.NewDecimal(0, 0)}); !reflect.DeepEqual(v, prf) { + } else if v := (&utils.RateProfile{Tenant: "cgrates.org", ID: "ID", Rates: map[string]*utils.Rate{}, MinCost: utils.NewDecimal(0, 0), MaxCost: utils.NewDecimal(0, 0)}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{RateProfileIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -696,7 +650,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetActionProfile(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.ActionProfile{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Targets: map[string]utils.StringSet{}, Actions: []*engine.APAction{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.ActionProfile{Tenant: "cgrates.org", ID: "ID", Targets: map[string]utils.StringSet{}}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{ActionProfileIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -713,7 +667,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetFilter(context.Background(), "cgrates.org", "ID", false, true, utils.NonTransactional); err != nil { t.Fatal(err) - } else if v := (&engine.Filter{Tenant: "cgrates.org", ID: "ID"}); !reflect.DeepEqual(v, prf) { + } else if v := (&engine.Filter{Tenant: "cgrates.org", ID: "ID", Rules: make([]*engine.FilterRule, 0)}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{FilterIDs: []string{tntID}}); !reflect.DeepEqual(exp, reloadCache) { @@ -745,7 +699,7 @@ func TestLoaderProcessCallCahe(t *testing.T) { } if prf, err := dm.GetAccount(context.Background(), "cgrates.org", "ID"); err != nil { t.Fatal(err) - } else if v := (&utils.Account{Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{}, Balances: map[string]*utils.Balance{}, ThresholdIDs: []string{}}); !reflect.DeepEqual(v, prf) { + } else if v := (&utils.Account{Tenant: "cgrates.org", ID: "ID", Balances: map[string]*utils.Balance{}, Opts: make(map[string]interface{})}); !reflect.DeepEqual(v, prf) { t.Errorf("Expeceted: %v, received: %v", utils.ToJSON(v), utils.ToJSON(prf)) } if exp := (&utils.AttrReloadCacheWithAPIOpts{}); !reflect.DeepEqual(exp, reloadCache) { diff --git a/utils/account.go b/utils/account.go index 83ae47a9d..5f54ee749 100644 --- a/utils/account.go +++ b/utils/account.go @@ -19,6 +19,7 @@ along with this program. If not, see package utils import ( + "fmt" "sort" "strings" "time" @@ -667,11 +668,17 @@ func (ap *Account) Set(path []string, val interface{}, newBranch bool, _ string) case ID: ap.ID = IfaceAsString(val) case FilterIDs: - ap.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + ap.FilterIDs = append(ap.FilterIDs, valA...) case ThresholdIDs: - ap.ThresholdIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + ap.ThresholdIDs = append(ap.ThresholdIDs, valA...) case Weights: ap.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep) + case Opts: + ap.Opts, err = NewMapFromCSV(IfaceAsString(val)) } return default: @@ -684,14 +691,14 @@ func (ap *Account) Set(path []string, val interface{}, newBranch bool, _ string) return MapStorage(ap.Opts).Set(path[1:], val) } var id string - if strings.HasPrefix(path[0], Balances) && - path[0][8] == '[' && path[0][len(path[0])-1] == ']' { - id = path[0][9 : len(path[0])-1] - } else if path[0] == Balances { + if path[0] == Balances { id = path[1] path = path[1:] + } else if strings.HasPrefix(path[0], Balances) && + path[0][8] == '[' && path[0][len(path[0])-1] == ']' { + id = path[0][9 : len(path[0])-1] } - if id == EmptyString { + if id != EmptyString { if _, has := ap.Balances[id]; !has { ap.Balances[id] = &Balance{ID: path[0], Opts: make(map[string]interface{}), Units: NewDecimal(0, 0)} } @@ -718,17 +725,70 @@ func (bL *Balance) Set(path []string, val interface{}, newBranch bool) (err erro case Type: bL.Type = IfaceAsString(val) case FilterIDs: - bL.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + bL.FilterIDs = append(bL.FilterIDs, valA...) case AttributeIDs: - bL.AttributeIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + bL.AttributeIDs = append(bL.AttributeIDs, valA...) case RateProfileIDs: - bL.RateProfileIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + bL.RateProfileIDs = append(bL.RateProfileIDs, valA...) case Units: var valB *decimal.Big valB, err = IfaceAsBig(val) bL.Units = &Decimal{valB} case Weights: bL.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep) + case UnitFactors: + sls := strings.Split(IfaceAsString(val), InfieldSep) + if len(sls)%2 != 0 { + return fmt.Errorf("invalid key: <%s> for BalanceUnitFactors", IfaceAsString(val)) + } + for j := 0; j < len(sls); j += 2 { + uf := new(UnitFactor) + if len(sls[j]) != 0 { + uf.FilterIDs = strings.Split(sls[j], ANDSep) + } + + var valB *decimal.Big + if valB, err = IfaceAsBig(sls[j+1]); err != nil { + return + } + uf.Factor = &Decimal{valB} + bL.UnitFactors = append(bL.UnitFactors, uf) + } + case CostIncrements: + sls := strings.Split(IfaceAsString(val), InfieldSep) + if len(sls)%4 != 0 { + return fmt.Errorf("invalid key: <%s> for BalanceCostIncrements", IfaceAsString(val)) + } + for j := 0; j < len(sls); j += 4 { + cI := new(CostIncrement) + if len(sls[j]) != 0 { + cI.FilterIDs = strings.Split(sls[j], ANDSep) + } + if len(sls[j+1]) != 0 { + if cI.Increment, err = NewDecimalFromString(sls[j+1]); err != nil { + return + } + } + if len(sls[j+2]) != 0 { + if cI.FixedFee, err = NewDecimalFromString(sls[j+2]); err != nil { + return + } + } + if len(sls[j+3]) != 0 { + if cI.RecurrentFee, err = NewDecimalFromString(sls[j+3]); err != nil { + return + } + } + bL.CostIncrements = append(bL.CostIncrements, cI) + } + case Opts: + bL.Opts, err = NewMapFromCSV(IfaceAsString(val)) } return case 2: @@ -743,35 +803,47 @@ func (bL *Balance) Set(path []string, val interface{}, newBranch bool) (err erro default: return ErrWrongPath case FilterIDs: - uf.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + uf.FilterIDs = append(uf.FilterIDs, valA...) case Factor: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - uf.Factor = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + uf.Factor = &Decimal{valB} + } } return case CostIncrements: if len(bL.CostIncrements) == 0 || newBranch { - bL.CostIncrements = append(bL.CostIncrements, new(CostIncrement)) + bL.CostIncrements = append(bL.CostIncrements, &CostIncrement{FixedFee: NewDecimal(0, 0)}) } cI := bL.CostIncrements[len(bL.CostIncrements)-1] switch path[1] { default: return ErrWrongPath case FilterIDs: - cI.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + cI.FilterIDs = append(cI.FilterIDs, valA...) case Increment: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - cI.Increment = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + cI.Increment = &Decimal{valB} + } case FixedFee: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - cI.FixedFee = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + cI.FixedFee = &Decimal{valB} + } case RecurrentFee: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - cI.RecurrentFee = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + cI.RecurrentFee = &Decimal{valB} + } } return } diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 7832b5cda..38287ce5a 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1033,19 +1033,19 @@ type TPBalanceCostIncrement struct { func (costIncr *TPBalanceCostIncrement) AsString() (s string) { if len(costIncr.FilterIDs) != 0 { - s = s + strings.Join(costIncr.FilterIDs, ANDSep) + s += strings.Join(costIncr.FilterIDs, ANDSep) } - s = s + InfieldSep + s += InfieldSep if costIncr.Increment != EmptyString { - s = s + costIncr.Increment + s += costIncr.Increment } - s = s + InfieldSep + s += InfieldSep if costIncr.FixedFee != nil { - s = s + strconv.FormatFloat(*costIncr.FixedFee, 'f', -1, 64) + s += strconv.FormatFloat(*costIncr.FixedFee, 'f', -1, 64) } - s = s + InfieldSep + s += InfieldSep if costIncr.RecurrentFee != nil { - s = s + strconv.FormatFloat(*costIncr.RecurrentFee, 'f', -1, 64) + s += strconv.FormatFloat(*costIncr.RecurrentFee, 'f', -1, 64) } return } @@ -1054,9 +1054,7 @@ func NewTPBalanceUnitFactor(filtersStr, factorStr string) (unitFactor *TPBalance unitFactor = &TPBalanceUnitFactor{ FilterIDs: strings.Split(filtersStr, ANDSep), } - if unitFactor.Factor, err = strconv.ParseFloat(factorStr, 64); err != nil { - return - } + unitFactor.Factor, err = strconv.ParseFloat(factorStr, 64) return } @@ -1065,10 +1063,6 @@ type TPBalanceUnitFactor struct { Factor float64 } -func (unitFactor *TPBalanceUnitFactor) AsString() (s string) { - if len(unitFactor.FilterIDs) != 0 { - s = s + strings.Join(unitFactor.FilterIDs, ANDSep) - } - s = s + InfieldSep + strconv.FormatFloat(unitFactor.Factor, 'f', -1, 64) - return +func (unitFactor *TPBalanceUnitFactor) AsString() string { + return strings.Join(unitFactor.FilterIDs, ANDSep) + InfieldSep + strconv.FormatFloat(unitFactor.Factor, 'f', -1, 64) } diff --git a/utils/dynamicweight.go b/utils/dynamicweight.go index a886743d7..c656f83db 100644 --- a/utils/dynamicweight.go +++ b/utils/dynamicweight.go @@ -26,14 +26,16 @@ import ( // NewDynamicWeightsFromString creates a DynamicWeight list based on the string received from .csv/StorDB func NewDynamicWeightsFromString(s, dWSep, fltrSep string) (dWs DynamicWeights, err error) { - nrFlds := 2 + if len(s) == 0 { + return DynamicWeights{{}}, nil + } dwStrs := strings.Split(s, dWSep) lnDwStrs := len(dwStrs) - if lnDwStrs%nrFlds != 0 { // need to have multiples of number of fields in one DynamicWeight + if lnDwStrs%2 != 0 { // need to have multiples of number of fields in one DynamicWeight return nil, fmt.Errorf("invalid DynamicWeight format for string <%s>", s) } - dWs = make([]*DynamicWeight, 0, lnDwStrs/nrFlds) - for i := 0; i < lnDwStrs; i += nrFlds { + dWs = make([]*DynamicWeight, 0, lnDwStrs/2) + for i := 0; i < lnDwStrs; i += 2 { var fltrIDs []string if len(dwStrs[i]) != 0 { fltrIDs = strings.Split(dwStrs[i], fltrSep) diff --git a/utils/librates.go b/utils/librates.go index 75fa2f463..624df1cb1 100644 --- a/utils/librates.go +++ b/utils/librates.go @@ -573,12 +573,12 @@ func (rp *RateProfile) Set(path []string, val interface{}, newBranch bool, _ str return ErrWrongPath } var rtID string - if strings.HasPrefix(path[0], Rates) && - path[0][5] == '[' && path[0][len(path[0])-1] == ']' { - rtID = path[0][6 : len(path[0])-1] - } else if len(path) != 1 && path[0] == Rates { + if len(path) != 1 && path[0] == Rates { rtID = path[1] path = path[1:] + } else if strings.HasPrefix(path[0], Rates) && + path[0][5] == '[' && path[0][len(path[0])-1] == ']' { + rtID = path[0][6 : len(path[0])-1] } if rtID != EmptyString { if _, has := rp.Rates[rtID]; !has { @@ -599,17 +599,23 @@ func (rp *RateProfile) Set(path []string, val interface{}, newBranch bool, _ str case ID: rp.ID = IfaceAsString(val) case FilterIDs: - rp.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + rp.FilterIDs = append(rp.FilterIDs, valA...) case Weights: rp.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep) case MinCost: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - rp.MinCost = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + rp.MinCost = &Decimal{valB} + } case MaxCost: - var valB *decimal.Big - valB, err = IfaceAsBig(val) - rp.MaxCost = &Decimal{valB} + if val != EmptyString { + var valB *decimal.Big + valB, err = IfaceAsBig(val) + rp.MaxCost = &Decimal{valB} + } case MaxCostStrategy: rp.MaxCostStrategy = IfaceAsString(val) } @@ -628,7 +634,9 @@ func (rt *Rate) Set(path []string, val interface{}, newBranch bool) (err error) case ID: rt.ID = IfaceAsString(val) case FilterIDs: - rt.FilterIDs, err = IfaceAsStringSlice(val) + var valA []string + valA, err = IfaceAsStringSlice(val) + rt.FilterIDs = append(rt.FilterIDs, valA...) case Weights: rt.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep) case ActivationTimes: diff --git a/utils/mapstorage.go b/utils/mapstorage.go index 0f66c25fa..0e9f92740 100644 --- a/utils/mapstorage.go +++ b/utils/mapstorage.go @@ -36,6 +36,21 @@ type DataStorage interface { GetKeys(nested bool, nesteedLimit int, prefix string) []string } +func NewMapFromCSV(str string) (MapStorage, error) { + m := make(MapStorage) + if len(str) == 0 { + return nil, nil + } + for _, opt := range InfieldSplit(str) { + keyVal := strings.SplitN(opt, ConcatenatedKeySep, 2) + if len(keyVal) != 2 { + return nil, fmt.Errorf("malformed map pair: <%q>", opt) + } + m[keyVal[0]] = keyVal[1] + } + return m, nil +} + // MapStorage is the basic dataStorage type MapStorage map[string]interface{} diff --git a/utils/reflect.go b/utils/reflect.go index 92551aa07..a7e8aeb90 100644 --- a/utils/reflect.go +++ b/utils/reflect.go @@ -73,6 +73,9 @@ func IfaceAsTime(itm interface{}, timezone string) (t time.Time, err error) { } func StringAsBig(itm string) (b *decimal.Big, err error) { + if len(itm) == 0 { + return decimal.New(0, 0), nil + } if strings.HasSuffix(itm, NsSuffix) || strings.HasSuffix(itm, UsSuffix) || strings.HasSuffix(itm, µSuffix) || @@ -242,6 +245,9 @@ func IfaceAsBool(itm interface{}) (b bool, err error) { case bool: return v, nil case string: + if len(v) == 0 { + return + } return strconv.ParseBool(v) case int: return v > 0, nil @@ -749,7 +755,9 @@ func IfaceAsStringSlice(fld interface{}) (ss []string, err error) { ss[i] = IfaceAsString(v) } case string: - ss = strings.Split(value, InfieldSep) + if value != EmptyString { + ss = strings.Split(value, InfieldSep) + } default: // Maybe we are lucky and the value converts to string err = fmt.Errorf("cannot convert field: %+v to []string", value) }