From 330360881329535eaac7276817234537be3f7ead Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 6 Jan 2015 17:36:32 +0100 Subject: [PATCH] Basic json config structures and defaults with tests --- ...ple_cfg.json => cgrates_cfg_defaults.json} | 4 +- config/config_json.go | 358 +++++++++-------- config/config_json_test.go | 376 +++++++++++++++++- config/libconfig_json.go | 210 ++++++++++ utils/coreutils.go | 4 + 5 files changed, 783 insertions(+), 169 deletions(-) rename config/{cgrates_sample_cfg.json => cgrates_cfg_defaults.json} (98%) create mode 100644 config/libconfig_json.go diff --git a/config/cgrates_sample_cfg.json b/config/cgrates_cfg_defaults.json similarity index 98% rename from config/cgrates_sample_cfg.json rename to config/cgrates_cfg_defaults.json index efd11eebf..876824d85 100644 --- a/config/cgrates_sample_cfg.json +++ b/config/cgrates_cfg_defaults.json @@ -118,7 +118,7 @@ "cdre": { "CDRE-FW1": { "cdr_format": "csv", // exported CDRs format - "data_usage_multiply_factor": 1.0, // multiply data usage before export (eg: convert from KBytes to Bytes) + "data_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from KBytes to Bytes) "cost_multiply_factor": 1, // multiply cost before export, eg: add VAT "cost_rounding_decimals": -1, // rounding decimals for Cost values. -1 to disable rounding "cost_shift_digits": 0, // shift digits in the cost on export (eg: convert from EUR to cents) @@ -127,7 +127,7 @@ "export_dir": "/var/log/cgrates/cdre", // path where the exported CDRs will be placed "header_fields": [], // template of the exported header fields "content_fields": [ // template of the exported content fields - {"tag": "CgrId", "type": "cdrfield", "value": "cgrid", "width": "40", "mandatory": "true"}, + {"tag": "CgrId", "type": "cdrfield", "value": "cgrid", "width": 40, "mandatory": true}, {"tag":"RunId", "type": "cdrfield", "value": "mediation_runid", "width": 20}, {"tag":"Tor", "type": "cdrfield", "value": "tor", "width": 6}, {"tag":"AccId", "type": "cdrfield", "value": "accid", "width": 36}, diff --git a/config/config_json.go b/config/config_json.go index 8ef448764..189a987f9 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -26,9 +26,26 @@ import ( ) const ( - GENERAL_JSN = "general" - CDRE_JSN = "cdre" - CONTENT_FIELDS_JSN = "content_fields" + GENERAL_JSN = "general" + LISTEN_JSN = "listen" + RATINGDB_JSN = "rating_db" + ACCOUNTINGDB_JSN = "accounting_db" + STORDB_JSN = "stor_db" + BALANCER_JSN = "balancer" + RATER_JSN = "rater" + SCHEDULER_JSN = "scheduler" + CDRS_JSN = "cdrs" + MEDIATOR_JSN = "mediator" + CDRSTATS_JSN = "cdrstats" + CDRE_JSN = "cdre" + CDRC_JSN = "cdrc" + SM_JSN = "session_manager" + FS_JSN = "freeswitch" + KAMAILIO_JSN = "kamailio" + OSIPS_JSN = "opensips" + HISTSERV_JSN = "history_server" + HISTAGENT_JSN = "history_agent" + MAILER_JSN = "mailer" ) // Loads the json config out of io.Reader, eg other sources than file, maybe over http @@ -55,204 +72,217 @@ func NewCgrJsonCfgFromFile(fpath string) (CgrJsonCfg, error) { type CgrJsonCfg map[string]*json.RawMessage func (self CgrJsonCfg) GeneralJsonCfg() (*GeneralJsonCfg, error) { - rawGCfg, hasKey := self[GENERAL_JSN] + rawCfg, hasKey := self[GENERAL_JSN] if !hasKey { return nil, nil } - gCfg := new(GeneralJsonCfg) - if err := json.Unmarshal(*rawGCfg, gCfg); err != nil { + cfg := new(GeneralJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { return nil, err } - return gCfg, nil + return cfg, nil } -// General config section -type GeneralJsonCfg struct { - Http_skip_tls_veify *bool - Rounding_decimals *int - Dbdata_encoding *string - Tpexport_dir *string - Default_reqtype *string - Default_category *string - Default_tenant *string - Default_subject *string +func (self CgrJsonCfg) ListenJsonCfg() (*ListenJsonCfg, error) { + rawCfg, hasKey := self[LISTEN_JSN] + if !hasKey { + return nil, nil + } + cfg := new(ListenJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Listen config section -type ListenJsonCfg struct { - Rpc_json *string - Rpc_gob *string - Http *string +func (self CgrJsonCfg) DbJsonCfg(section string) (*DbJsonCfg, error) { + rawCfg, hasKey := self[section] + if !hasKey { + return nil, nil + } + cfg := new(DbJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Database config -type DbJsonCfg struct { - Db_type *string - Db_host *string - Db_port *string - Db_name *string - Db_user *string - Db_passwd *string - Max_open_conns *int // Used only in case of storDb - Max_idle_conns *int +func (self CgrJsonCfg) BalancerJsonCfg() (*BalancerJsonCfg, error) { + rawCfg, hasKey := self[BALANCER_JSN] + if !hasKey { + return nil, nil + } + cfg := new(BalancerJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Balancer config section -type BalancerJsonCfg struct { - Enabled *bool +func (self CgrJsonCfg) RaterJsonCfg() (*RaterJsonCfg, error) { + rawCfg, hasKey := self[RATER_JSN] + if !hasKey { + return nil, nil + } + cfg := new(RaterJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Rater config section -type RaterJsonCfg struct { - Enabled *bool - Balancer *string +func (self CgrJsonCfg) SchedulerJsonCfg() (*SchedulerJsonCfg, error) { + rawCfg, hasKey := self[SCHEDULER_JSN] + if !hasKey { + return nil, nil + } + cfg := new(SchedulerJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Scheduler config section -type SchedulerJsonCfg struct { - Enabled *bool +func (self CgrJsonCfg) CdrsJsonCfg() (*CdrsJsonCfg, error) { + rawCfg, hasKey := self[CDRS_JSN] + if !hasKey { + return nil, nil + } + cfg := new(CdrsJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Cdrs config section -type CdrsJsonCfg struct { - Enabled *bool - Extra_fields *[]string - Mediator *string - Cdrstats *string - Store_disable *bool +func (self CgrJsonCfg) MediatorJsonCfg() (*MediatorJsonCfg, error) { + rawCfg, hasKey := self[MEDIATOR_JSN] + if !hasKey { + return nil, nil + } + cfg := new(MediatorJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Mediator config section -type MediatorJsonCfg struct { - Enabled *bool - Reconnects *int - Rater *string - Cdrstats *string - Store_disable *bool +func (self CgrJsonCfg) CdrStatsJsonCfg() (*CdrStatsJsonCfg, error) { + rawCfg, hasKey := self[CDRSTATS_JSN] + if !hasKey { + return nil, nil + } + cfg := new(CdrStatsJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Cdrstats config section -type CdrStatsJsonCfg struct { - Enabled *bool - Queue_length *int - Time_window *string - Metrics *[]string - Setup_interval *[]string - Tors *[]string - Cdr_hosts *[]string - Cdr_sources *[]string - Req_types *[]string - Directions *[]string - Tenants *[]string - Categories *[]string - Accounts *[]string - Subjects *[]string - Destination_prefixes *[]string - Usage_interval *[]string - Mediation_run_ids *[]string - Rated_accounts *[]string - Rated_subjects *[]string - Cost_intervals *[]string +func (self CgrJsonCfg) CdreJsonCfgs() (map[string]*CdreJsonCfg, error) { + rawCfg, hasKey := self[CDRE_JSN] + if !hasKey { + return nil, nil + } + cfg := make(map[string]*CdreJsonCfg) + if err := json.Unmarshal(*rawCfg, &cfg); err != nil { + return nil, err + } + return cfg, nil } -// One cdr field config, used in cdre and cdrc -type CdrFieldJsonCfg struct { - Tag *string - Type *string - Cdr_field_id *string - Value *string - Width *int - Strip *string - Padding *string - Layout *string - Filter *string - Mandatory *bool +func (self CgrJsonCfg) CdrcJsonCfg() (map[string]*CdrcJsonCfg, error) { + rawCfg, hasKey := self[CDRC_JSN] + if !hasKey { + return nil, nil + } + cfg := make(map[string]*CdrcJsonCfg) + if err := json.Unmarshal(*rawCfg, &cfg); err != nil { + return nil, err + } + return cfg, nil } -// Cdre config section -type CdreJsonCfg struct { - Cdr_format *string - Data_usage_multiply_factor *float64 - Cost_multiply_factor *float64 - Cost_rounding_decimals *int - Cost_shift_digits *int - Mask_destination_id *string - Mask_length *int - Export_dir *string - Header_fields *[]CdrFieldJsonCfg - Content_fields *[]CdrFieldJsonCfg - Trailer_fields *[]CdrFieldJsonCfg +func (self CgrJsonCfg) SessionManagerJsonCfg() (*SessionManagerJsonCfg, error) { + rawCfg, hasKey := self[SM_JSN] + if !hasKey { + return nil, nil + } + cfg := new(SessionManagerJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Cdrc config section -type CdrcJsonCfg struct { - Enabled *bool - Cdrs_address *string - Cdr_format *string - Field_separator *string - Run_delay *int64 - Data_usage_multiply_factor *float64 - Cdr_in_dir *string - Cdr_out_dir *string - Cdr_source_id *string - Cdr_fields *[]CdrFieldJsonCfg +func (self CgrJsonCfg) FSJsonCfg() (*FSJsonCfg, error) { + rawCfg, hasKey := self[FS_JSN] + if !hasKey { + return nil, nil + } + cfg := new(FSJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Session manager config section -type SessionManagerJsonCfg struct { - Enabled *bool - Switch_type *string - Rater *string - Cdrs *string - Reconnects *int - Debit_interval *int - Min_call_duration *string - Max_call_duration *string +func (self CgrJsonCfg) KamailioJsonCfg() (*KamailioJsonCfg, error) { + rawCfg, hasKey := self[KAMAILIO_JSN] + if !hasKey { + return nil, nil + } + cfg := new(KamailioJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// FreeSWITCH config section -type FSJsonCfg struct { - Server *string - Password *string - Reconnects *int - Min_dur_low_balance *string - Low_balance_ann_file *string - Empty_balance_context *string - Empty_balance_ann_file *string - Cdr_extra_fields *[]string +func (self CgrJsonCfg) OsipsJsonCfg() (*OsipsJsonCfg, error) { + rawCfg, hasKey := self[OSIPS_JSN] + if !hasKey { + return nil, nil + } + cfg := new(OsipsJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Kamailio config section -type KamailioJsonCfg struct { - Evapi_addr *string - Reconnects *int +func (self CgrJsonCfg) HistServJsonCfg() (*HistServJsonCfg, error) { + rawCfg, hasKey := self[HISTSERV_JSN] + if !hasKey { + return nil, nil + } + cfg := new(HistServJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// Opensips config section -type OsipsJsonCfg struct { - Listen_udp *string - Mi_addr *string - Events_subscribe_interval *string - Reconnects *int +func (self CgrJsonCfg) HistAgentJsonCfg() (*HistAgentJsonCfg, error) { + rawCfg, hasKey := self[HISTAGENT_JSN] + if !hasKey { + return nil, nil + } + cfg := new(HistAgentJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } -// History server config section -type HistServJsonCfg struct { - Enabled *bool - History_dir *string - Save_interval *string -} - -// History agent config section -type HistAgentJsonCfg struct { - Enabled *bool - Server *string -} - -// Mailer config section -type MailerJsonCfg struct { - Server *string - Auth_user *string - Auth_passwd *string - From_address *string +func (self CgrJsonCfg) MailerJsonCfg() (*MailerJsonCfg, error) { + rawCfg, hasKey := self[MAILER_JSN] + if !hasKey { + return nil, nil + } + cfg := new(MailerJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil } diff --git a/config/config_json_test.go b/config/config_json_test.go index 0eb5e35a9..4f4722c43 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -28,13 +28,13 @@ var cgrJsonCfg CgrJsonCfg func TestNewCgrJsonCfgFromFile(t *testing.T) { var err error - if cgrJsonCfg, err = NewCgrJsonCfgFromFile("cgrates_sample_cfg.json"); err != nil { + if cgrJsonCfg, err = NewCgrJsonCfgFromFile("cgrates_cfg_defaults.json"); err != nil { t.Error(err.Error()) } } func TestGeneralJsonCfg(t *testing.T) { - eGCfg := &GeneralJsonCfg{ + eCfg := &GeneralJsonCfg{ Http_skip_tls_veify: utils.BoolPointer(false), Rounding_decimals: utils.IntPointer(10), Dbdata_encoding: utils.StringPointer("msgpack"), @@ -45,7 +45,377 @@ func TestGeneralJsonCfg(t *testing.T) { Default_subject: utils.StringPointer("cgrates")} if gCfg, err := cgrJsonCfg.GeneralJsonCfg(); err != nil { t.Error(err) - } else if !reflect.DeepEqual(eGCfg, gCfg) { + } else if !reflect.DeepEqual(eCfg, gCfg) { t.Error("Received: ", gCfg) } } + +func TestListenJsonCfg(t *testing.T) { + eCfg := &ListenJsonCfg{ + Rpc_json: utils.StringPointer("127.0.0.1:2012"), + Rpc_gob: utils.StringPointer("127.0.0.1:2013"), + Http: utils.StringPointer("127.0.0.1:2080")} + if cfg, err := cgrJsonCfg.ListenJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestDbJsonCfg(t *testing.T) { + eCfg := &DbJsonCfg{ + Db_type: utils.StringPointer("redis"), + Db_host: utils.StringPointer("127.0.0.1"), + Db_port: utils.IntPointer(6379), + Db_name: utils.StringPointer("10"), + Db_user: utils.StringPointer(""), + Db_passwd: utils.StringPointer(""), + } + if cfg, err := cgrJsonCfg.DbJsonCfg(RATINGDB_JSN); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } + eCfg = &DbJsonCfg{ + Db_type: utils.StringPointer("redis"), + Db_host: utils.StringPointer("127.0.0.1"), + Db_port: utils.IntPointer(6379), + Db_name: utils.StringPointer("11"), + Db_user: utils.StringPointer(""), + Db_passwd: utils.StringPointer(""), + } + if cfg, err := cgrJsonCfg.DbJsonCfg(ACCOUNTINGDB_JSN); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } + eCfg = &DbJsonCfg{ + Db_type: utils.StringPointer("mysql"), + Db_host: utils.StringPointer("127.0.0.1"), + Db_port: utils.IntPointer(3306), + Db_name: utils.StringPointer("cgrates"), + Db_user: utils.StringPointer("cgrates"), + Db_passwd: utils.StringPointer("CGRateS.org"), + Max_open_conns: utils.IntPointer(0), + Max_idle_conns: utils.IntPointer(-1), + } + if cfg, err := cgrJsonCfg.DbJsonCfg(STORDB_JSN); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestBalancerJsonCfg(t *testing.T) { + eCfg := &BalancerJsonCfg{Enabled: utils.BoolPointer(false)} + if cfg, err := cgrJsonCfg.BalancerJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestRaterJsonCfg(t *testing.T) { + eCfg := &RaterJsonCfg{Enabled: utils.BoolPointer(false), Balancer: utils.StringPointer("")} + if cfg, err := cgrJsonCfg.RaterJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestSchedulerJsonCfg(t *testing.T) { + eCfg := &SchedulerJsonCfg{Enabled: utils.BoolPointer(false)} + if cfg, err := cgrJsonCfg.SchedulerJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestCdrsJsonCfg(t *testing.T) { + eCfg := &CdrsJsonCfg{ + Enabled: utils.BoolPointer(false), + Extra_fields: utils.StringSlicePointer([]string{}), + Mediator: utils.StringPointer(""), + Cdrstats: utils.StringPointer(""), + Store_disable: utils.BoolPointer(false), + } + if cfg, err := cgrJsonCfg.CdrsJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestMediatorJsonCfg(t *testing.T) { + eCfg := &MediatorJsonCfg{ + Enabled: utils.BoolPointer(false), + Reconnects: utils.IntPointer(3), + Rater: utils.StringPointer("internal"), + Cdrstats: utils.StringPointer(""), + Store_disable: utils.BoolPointer(false), + } + if cfg, err := cgrJsonCfg.MediatorJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestCdrStatsJsonCfg(t *testing.T) { + eCfg := &CdrStatsJsonCfg{ + Enabled: utils.BoolPointer(false), + Queue_length: utils.IntPointer(50), + Time_window: utils.StringPointer("1h"), + Metrics: utils.StringSlicePointer([]string{"ASR", "ACD", "ACC"}), + Setup_interval: utils.StringSlicePointer([]string{}), + Tors: utils.StringSlicePointer([]string{}), + Cdr_hosts: utils.StringSlicePointer([]string{}), + Cdr_sources: utils.StringSlicePointer([]string{}), + Req_types: utils.StringSlicePointer([]string{}), + Directions: utils.StringSlicePointer([]string{}), + Tenants: utils.StringSlicePointer([]string{}), + Categories: utils.StringSlicePointer([]string{}), + Accounts: utils.StringSlicePointer([]string{}), + Subjects: utils.StringSlicePointer([]string{}), + Destination_prefixes: utils.StringSlicePointer([]string{}), + Usage_interval: utils.StringSlicePointer([]string{}), + Mediation_run_ids: utils.StringSlicePointer([]string{}), + Rated_accounts: utils.StringSlicePointer([]string{}), + Rated_subjects: utils.StringSlicePointer([]string{}), + Cost_intervals: utils.StringSlicePointer([]string{}), + } + if cfg, err := cgrJsonCfg.CdrStatsJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestCdreJsonCfgs(t *testing.T) { + eFields := []*CdrFieldJsonCfg{} + eContentFlds := []*CdrFieldJsonCfg{ + &CdrFieldJsonCfg{Tag: utils.StringPointer("CgrId"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("cgrid"), + Width: utils.IntPointer(40), + Mandatory: utils.BoolPointer(true)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("RunId"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("mediation_runid"), + Width: utils.IntPointer(20)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Tor"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("tor"), + Width: utils.IntPointer(6)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("AccId"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("accid"), + Width: utils.IntPointer(36)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("ReqType"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("reqtype"), + Width: utils.IntPointer(13)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("direction"), + Width: utils.IntPointer(4)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("tenant"), + Width: utils.IntPointer(24)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("category"), + Width: utils.IntPointer(10)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("account"), + Width: utils.IntPointer(24)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("subject"), + Width: utils.IntPointer(24)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("destination"), + Width: utils.IntPointer(24)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("setup_time"), + Width: utils.IntPointer(30), + Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("answer_time"), + Width: utils.IntPointer(30), + Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("usage"), + Width: utils.IntPointer(30)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Cost"), + Type: utils.StringPointer("cdrfield"), + Value: utils.StringPointer("cost"), + Width: utils.IntPointer(24)}, + } + eCfg := map[string]*CdreJsonCfg{ + "CDRE-FW1": &CdreJsonCfg{ + Cdr_format: utils.StringPointer("csv"), + Data_usage_multiply_factor: utils.Float64Pointer(1.0), + Cost_multiply_factor: utils.Float64Pointer(1.0), + Cost_rounding_decimals: utils.IntPointer(-1), + Cost_shift_digits: utils.IntPointer(0), + Mask_destination_id: utils.StringPointer("MASKED_DESTINATIONS"), + Mask_length: utils.IntPointer(0), + Export_dir: utils.StringPointer("/var/log/cgrates/cdre"), + Header_fields: &eFields, + Content_fields: &eContentFlds, + Trailer_fields: &eFields, + }, + } + if cfg, err := cgrJsonCfg.CdreJsonCfgs(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestCdrcJsonCfg(t *testing.T) { + cdrFields := []*CdrFieldJsonCfg{ + &CdrFieldJsonCfg{Tag: utils.StringPointer("accid"), Value: utils.StringPointer("0;13")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("reqtype"), Value: utils.StringPointer("1")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("direction"), Value: utils.StringPointer("2")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("tenant"), Value: utils.StringPointer("3")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("category"), Value: utils.StringPointer("4")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("account"), Value: utils.StringPointer("5")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("subject"), Value: utils.StringPointer("6")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("destination"), Value: utils.StringPointer("7")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("setup_time"), Value: utils.StringPointer("8")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("answer_time"), Value: utils.StringPointer("9")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("usage"), Value: utils.StringPointer("10")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("extr1"), Value: utils.StringPointer("11")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("extr2"), Value: utils.StringPointer("12")}, + } + eCfg := map[string]*CdrcJsonCfg{ + "instance1": &CdrcJsonCfg{ + Enabled: utils.BoolPointer(false), + Cdrs_address: utils.StringPointer("internal"), + Cdr_format: utils.StringPointer("csv"), + Field_separator: utils.StringPointer(","), + Run_delay: utils.IntPointer(0), + Data_usage_multiply_factor: utils.Float64Pointer(1024.0), + Cdr_in_dir: utils.StringPointer("/var/log/cgrates/cdrc/in"), + Cdr_out_dir: utils.StringPointer("/var/log/cgrates/cdrc/out"), + Cdr_source_id: utils.StringPointer("freeswitch_csv"), + Cdr_fields: &cdrFields, + }, + } + if cfg, err := cgrJsonCfg.CdrcJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestSessionManagerJsonCfg(t *testing.T) { + eCfg := &SessionManagerJsonCfg{ + Enabled: utils.BoolPointer(false), + Switch_type: utils.StringPointer("freeswitch"), + Rater: utils.StringPointer("internal"), + Cdrs: utils.StringPointer(""), + Reconnects: utils.IntPointer(3), + Debit_interval: utils.IntPointer(10), + Min_call_duration: utils.StringPointer("0s"), + Max_call_duration: utils.StringPointer("3h"), + } + if cfg, err := cgrJsonCfg.SessionManagerJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestFSJsonCfg(t *testing.T) { + eCfg := &FSJsonCfg{ + Server: utils.StringPointer("127.0.0.1:8021"), + Password: utils.StringPointer("ClueCon"), + Reconnects: utils.IntPointer(5), + Min_dur_low_balance: utils.StringPointer("5s"), + Low_balance_ann_file: utils.StringPointer(""), + Empty_balance_context: utils.StringPointer(""), + Empty_balance_ann_file: utils.StringPointer(""), + Cdr_extra_fields: utils.StringSlicePointer([]string{}), + } + if cfg, err := cgrJsonCfg.FSJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestKamailioJsonCfg(t *testing.T) { + eCfg := &KamailioJsonCfg{ + Evapi_addr: utils.StringPointer("127.0.0.1:8448"), + Reconnects: utils.IntPointer(3), + } + if cfg, err := cgrJsonCfg.KamailioJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestOsipsJsonCfg(t *testing.T) { + eCfg := &OsipsJsonCfg{ + Listen_udp: utils.StringPointer("127.0.0.1:2020"), + Mi_addr: utils.StringPointer("127.0.0.1:8020"), + Events_subscribe_interval: utils.StringPointer("60s"), + Reconnects: utils.IntPointer(3), + } + if cfg, err := cgrJsonCfg.OsipsJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestHistServJsonCfg(t *testing.T) { + eCfg := &HistServJsonCfg{ + Enabled: utils.BoolPointer(false), + History_dir: utils.StringPointer("/var/log/cgrates/history"), + Save_interval: utils.StringPointer("1s"), + } + if cfg, err := cgrJsonCfg.HistServJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestHistAgentJsonCfg(t *testing.T) { + eCfg := &HistAgentJsonCfg{ + Enabled: utils.BoolPointer(false), + Server: utils.StringPointer("internal"), + } + if cfg, err := cgrJsonCfg.HistAgentJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} + +func TestMailerJsonCfg(t *testing.T) { + eCfg := &MailerJsonCfg{ + Server: utils.StringPointer("localhost"), + Auth_user: utils.StringPointer("cgrates"), + Auth_passwd: utils.StringPointer("CGRateS.org"), + From_address: utils.StringPointer("cgr-mailer@localhost.localdomain"), + } + if cfg, err := cgrJsonCfg.MailerJsonCfg(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, cfg) { + t.Error("Received: ", cfg) + } +} diff --git a/config/libconfig_json.go b/config/libconfig_json.go new file mode 100644 index 000000000..aecb13696 --- /dev/null +++ b/config/libconfig_json.go @@ -0,0 +1,210 @@ +/* +Real-time Charging System 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 + +// General config section +type GeneralJsonCfg struct { + Http_skip_tls_veify *bool + Rounding_decimals *int + Dbdata_encoding *string + Tpexport_dir *string + Default_reqtype *string + Default_category *string + Default_tenant *string + Default_subject *string +} + +// Listen config section +type ListenJsonCfg struct { + Rpc_json *string + Rpc_gob *string + Http *string +} + +// Database config +type DbJsonCfg struct { + Db_type *string + Db_host *string + Db_port *int + Db_name *string + Db_user *string + Db_passwd *string + Max_open_conns *int // Used only in case of storDb + Max_idle_conns *int +} + +// Balancer config section +type BalancerJsonCfg struct { + Enabled *bool +} + +// Rater config section +type RaterJsonCfg struct { + Enabled *bool + Balancer *string +} + +// Scheduler config section +type SchedulerJsonCfg struct { + Enabled *bool +} + +// Cdrs config section +type CdrsJsonCfg struct { + Enabled *bool + Extra_fields *[]string + Mediator *string + Cdrstats *string + Store_disable *bool +} + +// Mediator config section +type MediatorJsonCfg struct { + Enabled *bool + Reconnects *int + Rater *string + Cdrstats *string + Store_disable *bool +} + +// Cdrstats config section +type CdrStatsJsonCfg struct { + Enabled *bool + Queue_length *int + Time_window *string + Metrics *[]string + Setup_interval *[]string + Tors *[]string + Cdr_hosts *[]string + Cdr_sources *[]string + Req_types *[]string + Directions *[]string + Tenants *[]string + Categories *[]string + Accounts *[]string + Subjects *[]string + Destination_prefixes *[]string + Usage_interval *[]string + Mediation_run_ids *[]string + Rated_accounts *[]string + Rated_subjects *[]string + Cost_intervals *[]string +} + +// One cdr field config, used in cdre and cdrc +type CdrFieldJsonCfg struct { + Tag *string + Type *string + Cdr_field_id *string + Value *string + Width *int + Strip *string + Padding *string + Layout *string + Filter *string + Mandatory *bool +} + +// Cdre config section +type CdreJsonCfg struct { + Cdr_format *string + Data_usage_multiply_factor *float64 + Cost_multiply_factor *float64 + Cost_rounding_decimals *int + Cost_shift_digits *int + Mask_destination_id *string + Mask_length *int + Export_dir *string + Header_fields *[]*CdrFieldJsonCfg + Content_fields *[]*CdrFieldJsonCfg + Trailer_fields *[]*CdrFieldJsonCfg +} + +// Cdrc config section +type CdrcJsonCfg struct { + Enabled *bool + Cdrs_address *string + Cdr_format *string + Field_separator *string + Run_delay *int + Data_usage_multiply_factor *float64 + Cdr_in_dir *string + Cdr_out_dir *string + Cdr_source_id *string + Cdr_fields *[]*CdrFieldJsonCfg +} + +// Session manager config section +type SessionManagerJsonCfg struct { + Enabled *bool + Switch_type *string + Rater *string + Cdrs *string + Reconnects *int + Debit_interval *int + Min_call_duration *string + Max_call_duration *string +} + +// FreeSWITCH config section +type FSJsonCfg struct { + Server *string + Password *string + Reconnects *int + Min_dur_low_balance *string + Low_balance_ann_file *string + Empty_balance_context *string + Empty_balance_ann_file *string + Cdr_extra_fields *[]string +} + +// Kamailio config section +type KamailioJsonCfg struct { + Evapi_addr *string + Reconnects *int +} + +// Opensips config section +type OsipsJsonCfg struct { + Listen_udp *string + Mi_addr *string + Events_subscribe_interval *string + Reconnects *int +} + +// History server config section +type HistServJsonCfg struct { + Enabled *bool + History_dir *string + Save_interval *string +} + +// History agent config section +type HistAgentJsonCfg struct { + Enabled *bool + Server *string +} + +// Mailer config section +type MailerJsonCfg struct { + Server *string + Auth_user *string + Auth_passwd *string + From_address *string +} diff --git a/utils/coreutils.go b/utils/coreutils.go index 3692649f6..e035887a0 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -351,3 +351,7 @@ func Float64Pointer(f float64) *float64 { func BoolPointer(b bool) *bool { return &b } + +func StringSlicePointer(slc []string) *[]string { + return &slc +}