From 4299c56ff4ce9f8735234f97c35abfe1969f4e19 Mon Sep 17 00:00:00 2001 From: TeoV Date: Thu, 14 May 2020 15:08:15 +0300 Subject: [PATCH] Add config infrastructure for RateS --- config/config.go | 13 ++++++++- config/config_defaults.go | 5 ++++ config/config_json.go | 12 +++++++++ config/config_test.go | 21 ++++++++++++--- config/eescfg.go | 9 ++++--- config/eescfg_test.go | 40 ++++++++++++++++------------ config/libconfig_json.go | 4 +++ config/ratescfg.go | 20 ++++++++++++++ config/ratescfg_test.go | 55 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 154 insertions(+), 25 deletions(-) create mode 100644 config/ratescfg_test.go diff --git a/config/config.go b/config/config.go index e4ee118a4..fa52382a5 100755 --- a/config/config.go +++ b/config/config.go @@ -181,6 +181,7 @@ func NewDefaultCGRConfig() (cfg *CGRConfig, err error) { cfg.ersCfg = new(ERsCfg) cfg.eesCfg = new(EEsCfg) cfg.eesCfg.Cache = make(map[string]*CacheParamCfg) + cfg.rateSCfg = new(RateSCfg) cfg.ConfigReloads = make(map[string]chan struct{}) cfg.ConfigReloads[utils.CDRE] = make(chan struct{}, 1) @@ -350,7 +351,8 @@ func (cfg *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) { cfg.loadThresholdSCfg, cfg.loadRouteSCfg, cfg.loadLoaderSCfg, cfg.loadMailerCfg, cfg.loadSureTaxCfg, cfg.loadDispatcherSCfg, cfg.loadLoaderCgrCfg, cfg.loadMigratorCgrCfg, cfg.loadTlsCgrCfg, - cfg.loadAnalyzerCgrCfg, cfg.loadApierCfg, cfg.loadErsCfg, cfg.loadEesCfg} { + cfg.loadAnalyzerCgrCfg, cfg.loadApierCfg, cfg.loadErsCfg, cfg.loadEesCfg, + cfg.loadRateCfg} { if err = loadFunc(jsnCfg); err != nil { return } @@ -741,6 +743,15 @@ func (cfg *CGRConfig) loadEesCfg(jsnCfg *CgrJsonCfg) (err error) { return cfg.eesCfg.loadFromJsonCfg(jsnEEsCfg, cfg.generalCfg.RSRSep, cfg.dfltEvExp) } +// loadEesCfg loads the Ees section of the configuration +func (cfg *CGRConfig) loadRateCfg(jsnCfg *CgrJsonCfg) (err error) { + var jsnRateCfg *RateSJsonCfg + if jsnRateCfg, err = jsnCfg.RateCfgJson(); err != nil { + return + } + return cfg.rateSCfg.loadFromJsonCfg(jsnRateCfg) +} + // SureTaxCfg use locking to retrieve the configuration, possibility later for runtime reload func (cfg *CGRConfig) SureTaxCfg() *SureTaxCfg { cfg.lks[SURETAX_JSON].Lock() diff --git a/config/config_defaults.go b/config/config_defaults.go index a817076b0..5520720d0 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -888,4 +888,9 @@ const CGRATES_CFG_JSON = ` "attributes_conns": [], // connections to AttributeS for CDRExporter }, + +"rates": { + "enabled": false, +}, + }` diff --git a/config/config_json.go b/config/config_json.go index 4fad842ba..2c2e2f9a9 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -507,3 +507,15 @@ func (self CgrJsonCfg) ApierCfgJson() (*ApierJsonCfg, error) { } return cfg, nil } + +func (self CgrJsonCfg) RateCfgJson() (*RateSJsonCfg, error) { + rawCfg, hasKey := self[RateSJson] + if !hasKey { + return nil, nil + } + cfg := new(RateSJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil +} diff --git a/config/config_test.go b/config/config_test.go index d5c259755..94611a9b9 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -1766,6 +1766,15 @@ func TestCgrCfgJSONDefaultApierCfg(t *testing.T) { } } +func TestCgrCfgJSONDefaultRateCfg(t *testing.T) { + eCfg := &RateSCfg{ + Enabled: false, + } + if !reflect.DeepEqual(cgrCfg.rateSCfg, eCfg) { + t.Errorf("received: %+v, expecting: %+v", cgrCfg.rateSCfg, eCfg) + } +} + func TestCgrCfgV1GetConfigSection(t *testing.T) { JSN_CFG := ` { @@ -1872,7 +1881,7 @@ func TestCgrCdfEventExporter(t *testing.T) { Filters: []string{}, AttributeSIDs: []string{}, Flags: utils.FlagsWithParams{}, - Fields: []*FCTemplate{ + ContentFields: []*FCTemplate{ { Tag: utils.CGRID, Path: "*exp.CGRID", @@ -1973,11 +1982,13 @@ func TestCgrCdfEventExporter(t *testing.T) { RoundingDecimals: utils.IntPointer(4), }, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, }, }, } for _, profile := range eCfg.Exporters { - for _, v := range profile.Fields { + for _, v := range profile.ContentFields { v.ComputePath() } } @@ -2046,7 +2057,7 @@ func TestCgrCfgEventExporterDefault(t *testing.T) { Timezone: utils.EmptyString, Filters: nil, Flags: utils.FlagsWithParams{}, - Fields: []*FCTemplate{ + ContentFields: []*FCTemplate{ { Tag: utils.CGRID, Path: "*exp.CGRID", @@ -2147,8 +2158,10 @@ func TestCgrCfgEventExporterDefault(t *testing.T) { RoundingDecimals: utils.IntPointer(4), }, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, } - for _, v := range eCfg.Fields { + for _, v := range eCfg.ContentFields { v.ComputePath() } if !reflect.DeepEqual(cgrCfg.dfltEvExp, eCfg) { diff --git a/config/eescfg.go b/config/eescfg.go index 9b3a61f4f..d13285768 100644 --- a/config/eescfg.go +++ b/config/eescfg.go @@ -188,6 +188,9 @@ func (eeC *EventExporterCfg) loadFromJsonCfg(jsnEec *EventExporterJsonCfg, separ eeC.FieldSep = *jsnEec.Field_separator } if jsnEec.Fields != nil { + eeC.HeaderFields = make([]*FCTemplate, 0) + eeC.ContentFields = make([]*FCTemplate, 0) + eeC.TrailerFields = make([]*FCTemplate, 0) if fields, err := FCTemplatesFromFCTemplatesJsonCfg(*jsnEec.Fields, separator); err != nil { return err } else { @@ -196,14 +199,12 @@ func (eeC *EventExporterCfg) loadFromJsonCfg(jsnEec *EventExporterJsonCfg, separ case utils.MetaHdr: eeC.HeaderFields = append(eeC.HeaderFields, field) case utils.MetaExp: - eeC.ContentFields = append(eeC.HeaderFields, field) + eeC.ContentFields = append(eeC.ContentFields, field) case utils.MetaTrl: - eeC.TrailerFields = append(eeC.HeaderFields, field) + eeC.TrailerFields = append(eeC.TrailerFields, field) } - } } - } return } diff --git a/config/eescfg_test.go b/config/eescfg_test.go index c49587e5d..7da998aed 100644 --- a/config/eescfg_test.go +++ b/config/eescfg_test.go @@ -33,24 +33,26 @@ func TestEventExporterClone(t *testing.T) { FieldSep: ",", Filters: []string{"Filter1", "Filter2"}, Tenant: NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP), - Fields: []*FCTemplate{ + ContentFields: []*FCTemplate{ { Tag: "ToR", - Path: "ToR", + Path: "*exp.ToR", Type: "*composed", Value: NewRSRParsersMustCompile("~*req.2", true, utils.INFIELD_SEP), Mandatory: true, }, { Tag: "RandomField", - Path: "RandomField", + Path: "*exp.RandomField", Type: "*composed", Value: NewRSRParsersMustCompile("Test", true, utils.INFIELD_SEP), Mandatory: true, }, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, } - for _, v := range orig.Fields { + for _, v := range orig.ContentFields { v.ComputePath() } cloned := orig.Clone() @@ -63,31 +65,33 @@ func TestEventExporterClone(t *testing.T) { FieldSep: ",", Filters: []string{"Filter1", "Filter2"}, Tenant: NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP), - Fields: []*FCTemplate{ + ContentFields: []*FCTemplate{ { Tag: "ToR", - Path: "ToR", + Path: "*exp.ToR", Type: "*composed", Value: NewRSRParsersMustCompile("~*req.2", true, utils.INFIELD_SEP), Mandatory: true, }, { Tag: "RandomField", - Path: "RandomField", + Path: "*exp.RandomField", Type: "*composed", Value: NewRSRParsersMustCompile("Test", true, utils.INFIELD_SEP), Mandatory: true, }, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, } - for _, v := range initialOrig.Fields { + for _, v := range initialOrig.ContentFields { v.ComputePath() } orig.Filters = []string{"SingleFilter"} - orig.Fields = []*FCTemplate{ + orig.ContentFields = []*FCTemplate{ { Tag: "ToR", - Path: "ToR", + Path: "*exp.ToR", Type: "*composed", Value: NewRSRParsersMustCompile("~2", true, utils.INFIELD_SEP), Mandatory: true, @@ -121,7 +125,7 @@ func TestEventExporterSameID(t *testing.T) { Filters: []string{}, AttributeSIDs: []string{}, Flags: utils.FlagsWithParams{}, - Fields: []*FCTemplate{ + ContentFields: []*FCTemplate{ { Tag: utils.CGRID, Path: "*exp.CGRID", @@ -222,6 +226,8 @@ func TestEventExporterSameID(t *testing.T) { RoundingDecimals: utils.IntPointer(4), }, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, }, { ID: "file_exporter1", @@ -233,15 +239,17 @@ func TestEventExporterSameID(t *testing.T) { ExportPath: "/var/spool/cgrates/ees", Attempts: 1, Flags: utils.FlagsWithParams{}, - Fields: []*FCTemplate{ - {Tag: "CustomTag2", Path: "CustomPath2", Type: utils.MetaVariable, + ContentFields: []*FCTemplate{ + {Tag: "CustomTag2", Path: "*exp.CustomPath2", Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("CustomValue2", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, }, + HeaderFields: []*FCTemplate{}, + TrailerFields: []*FCTemplate{}, }, }, } for _, profile := range expectedEEsCfg.Exporters { - for _, v := range profile.Fields { + for _, v := range profile.ContentFields { v.ComputePath() } } @@ -254,14 +262,14 @@ func TestEventExporterSameID(t *testing.T) { "id": "file_exporter1", "type": "*file_csv", "fields":[ - {"tag": "CustomTag1", "path": "CustomPath1", "type": "*variable", "value": "CustomValue1", "mandatory": true}, + {"tag": "CustomTag1", "path": "*exp.CustomPath1", "type": "*variable", "value": "CustomValue1", "mandatory": true}, ], }, { "id": "file_exporter1", "type": "*file_csv", "fields":[ - {"tag": "CustomTag2", "path": "CustomPath2", "type": "*variable", "value": "CustomValue2", "mandatory": true}, + {"tag": "CustomTag2", "path": "*exp.CustomPath2", "type": "*variable", "value": "CustomValue2", "mandatory": true}, ], }, ], diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 5a04cadb1..d92296cc5 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -604,3 +604,7 @@ type STIRJsonCfg struct { Publickey_path *string Privatekey_path *string } + +type RateSJsonCfg struct { + Enabled *bool +} diff --git a/config/ratescfg.go b/config/ratescfg.go index f945311a2..9db4bb429 100644 --- a/config/ratescfg.go +++ b/config/ratescfg.go @@ -18,6 +18,26 @@ along with this program. If not, see package config +import ( + "github.com/cgrates/cgrates/utils" +) + type RateSCfg struct { Enabled bool } + +func (rCfg *RateSCfg) loadFromJsonCfg(jsnCfg *RateSJsonCfg) (err error) { + if jsnCfg == nil { + return + } + if jsnCfg.Enabled != nil { + rCfg.Enabled = *jsnCfg.Enabled + } + return +} + +func (rCfg *RateSCfg) AsMapInterface() map[string]interface{} { + return map[string]interface{}{ + utils.EnabledCfg: rCfg.Enabled, + } +} diff --git a/config/ratescfg_test.go b/config/ratescfg_test.go new file mode 100644 index 000000000..ecebdc6eb --- /dev/null +++ b/config/ratescfg_test.go @@ -0,0 +1,55 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package config + +import ( + "reflect" + "testing" +) + +func TestRateSConfigloadFromJsonCfg(t *testing.T) { + var rateCfg, expected RateSCfg + if err := rateCfg.loadFromJsonCfg(nil); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rateCfg, expected) { + t.Errorf("Expected: %+v ,recived: %+v", expected, rateCfg) + } + if err := rateCfg.loadFromJsonCfg(new(RateSJsonCfg)); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rateCfg, expected) { + t.Errorf("Expected: %+v ,recived: %+v", expected, rateCfg) + } + cfgJSONStr := `{ +"rates": { + "enabled": true, +}, +}` + expected = RateSCfg{ + Enabled: true, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnRateSCfg, err := jsnCfg.RateCfgJson(); err != nil { + t.Error(err) + } else if err = rateCfg.loadFromJsonCfg(jsnRateSCfg); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, rateCfg) { + t.Errorf("Expected: %+v , recived: %+v", expected, rateCfg) + } +}