From ce222cf4468e81c06811c436a0f103bd0d2333e6 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 3 Dec 2015 11:34:18 +0200 Subject: [PATCH] updated config for ha --- config/config_defaults.go | 32 +++++++--- config/config_json_test.go | 52 +++++++++++----- config/libconfig_json.go | 21 ++++--- config/smconfig.go | 77 ++++++++++++++++++------ data/conf/cgrates/cgrates.json | 34 ++++++++--- data/conf/samples/dmtagent/cgrates.json | 8 ++- data/conf/samples/smgeneric/cgrates.json | 32 +++++++--- devel.yaml | 1 + 8 files changed, 190 insertions(+), 67 deletions(-) diff --git a/config/config_defaults.go b/config/config_defaults.go index 0ffd77b09..d8c3e153c 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -201,8 +201,12 @@ const CGRATES_CFG_JSON = ` "sm_generic": { "enabled": false, // starts SessionManager service: "listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests - "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> - "cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234> + "ha_rater": [ + {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> + ], + "ha_cdrs": [ + {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing + ], "debit_interval": "0s", // interval to perform debits on. "min_call_duration": "0s", // only authorize calls with allowed duration higher than this "max_call_duration": "3h", // maximum call duration a prepaid call can last @@ -211,8 +215,12 @@ const CGRATES_CFG_JSON = ` "sm_freeswitch": { "enabled": false, // starts SessionManager service: - "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> - "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> + "ha_rater": [ + {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> + ], + "ha_cdrs": [ + {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing + ], "create_cdr": false, // create CDR out of events and sends them to CDRS component "extra_fields": [], // extra fields to store in auth/CDRs when creating them "debit_interval": "10s", // interval to perform debits on. @@ -232,8 +240,12 @@ const CGRATES_CFG_JSON = ` "sm_kamailio": { "enabled": false, // starts SessionManager service: - "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> - "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> + "ha_rater": [ + {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> + ], + "ha_cdrs": [ + {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing + ], "create_cdr": false, // create CDR out of events and sends them to CDRS component "debit_interval": "10s", // interval to perform debits on. "min_call_duration": "0s", // only authorize calls with allowed duration higher than this @@ -247,8 +259,12 @@ const CGRATES_CFG_JSON = ` "sm_opensips": { "enabled": false, // starts SessionManager service: "listen_udp": "127.0.0.1:2020", // address where to listen for datagram events coming from OpenSIPS - "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> - "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> + "ha_rater": [ + {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> + ], + "ha_cdrs": [ + {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing + ], "reconnects": 5, // number of reconnects if connection is lost "create_cdr": false, // create CDR out of events and sends them to CDRS component "debit_interval": "10s", // interval to perform debits on. diff --git a/config/config_json_test.go b/config/config_json_test.go index b618bb1c8..5784001c7 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -326,10 +326,16 @@ func TestDfCdrcJsonCfg(t *testing.T) { func TestSmGenericJsonCfg(t *testing.T) { eCfg := &SmGenericJsonCfg{ - Enabled: utils.BoolPointer(false), - Listen_bijson: utils.StringPointer("127.0.0.1:2014"), - Rater: utils.StringPointer("internal"), - Cdrs: utils.StringPointer("internal"), + Enabled: utils.BoolPointer(false), + Listen_bijson: utils.StringPointer("127.0.0.1:2014"), + Ha_rater: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, + Ha_cdrs: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, Debit_interval: utils.StringPointer("0s"), Min_call_duration: utils.StringPointer("0s"), Max_call_duration: utils.StringPointer("3h"), @@ -343,9 +349,15 @@ func TestSmGenericJsonCfg(t *testing.T) { func TestSmFsJsonCfg(t *testing.T) { eCfg := &SmFsJsonCfg{ - Enabled: utils.BoolPointer(false), - Rater: utils.StringPointer("internal"), - Cdrs: utils.StringPointer("internal"), + Enabled: utils.BoolPointer(false), + Ha_rater: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, + Ha_cdrs: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, Create_cdr: utils.BoolPointer(false), Extra_fields: utils.StringSlicePointer([]string{}), Debit_interval: utils.StringPointer("10s"), @@ -373,9 +385,15 @@ func TestSmFsJsonCfg(t *testing.T) { func TestSmKamJsonCfg(t *testing.T) { eCfg := &SmKamJsonCfg{ - Enabled: utils.BoolPointer(false), - Rater: utils.StringPointer("internal"), - Cdrs: utils.StringPointer("internal"), + Enabled: utils.BoolPointer(false), + Ha_rater: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, + Ha_cdrs: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, Create_cdr: utils.BoolPointer(false), Debit_interval: utils.StringPointer("10s"), Min_call_duration: utils.StringPointer("0s"), @@ -396,10 +414,16 @@ func TestSmKamJsonCfg(t *testing.T) { func TestSmOsipsJsonCfg(t *testing.T) { eCfg := &SmOsipsJsonCfg{ - Enabled: utils.BoolPointer(false), - Listen_udp: utils.StringPointer("127.0.0.1:2020"), - Rater: utils.StringPointer("internal"), - Cdrs: utils.StringPointer("internal"), + Enabled: utils.BoolPointer(false), + Listen_udp: utils.StringPointer("127.0.0.1:2020"), + Ha_rater: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, + Ha_cdrs: &[]*HaPoolJsonCfg{ + &HaPoolJsonCfg{ + Server: utils.StringPointer("internal"), + }}, Create_cdr: utils.BoolPointer(false), Debit_interval: utils.StringPointer("10s"), Min_call_duration: utils.StringPointer("0s"), diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 82240478d..69fc4902c 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -164,8 +164,8 @@ type CdrcJsonCfg struct { type SmGenericJsonCfg struct { Enabled *bool Listen_bijson *string - Rater *string - Cdrs *string + Ha_rater *[]*HaPoolJsonCfg + Ha_cdrs *[]*HaPoolJsonCfg Debit_interval *string Min_call_duration *string Max_call_duration *string @@ -174,8 +174,8 @@ type SmGenericJsonCfg struct { // SM-FreeSWITCH config section type SmFsJsonCfg struct { Enabled *bool - Rater *string - Cdrs *string + Ha_rater *[]*HaPoolJsonCfg + Ha_cdrs *[]*HaPoolJsonCfg Create_cdr *bool Extra_fields *[]string Debit_interval *string @@ -190,6 +190,11 @@ type SmFsJsonCfg struct { Connections *[]*FsConnJsonCfg } +// Represents one connection instance towards a rater/cdrs server +type HaPoolJsonCfg struct { + Server *string +} + // Represents one connection instance towards FreeSWITCH type FsConnJsonCfg struct { Server *string @@ -200,8 +205,8 @@ type FsConnJsonCfg struct { // SM-Kamailio config section type SmKamJsonCfg struct { Enabled *bool - Rater *string - Cdrs *string + Ha_rater *[]*HaPoolJsonCfg + Ha_cdrs *[]*HaPoolJsonCfg Create_cdr *bool Debit_interval *string Min_call_duration *string @@ -219,8 +224,8 @@ type KamConnJsonCfg struct { type SmOsipsJsonCfg struct { Enabled *bool Listen_udp *string - Rater *string - Cdrs *string + Ha_rater *[]*HaPoolJsonCfg + Ha_cdrs *[]*HaPoolJsonCfg Create_cdr *bool Debit_interval *string Min_call_duration *string diff --git a/config/smconfig.go b/config/smconfig.go index b06ad7c20..82c1d14b6 100644 --- a/config/smconfig.go +++ b/config/smconfig.go @@ -35,8 +35,17 @@ func NewDfltHaPoolConfig() *HaPoolConfig { // One connection to Rater type HaPoolConfig struct { - Server string - Timeout time.Duration + Server string +} + +func (self *HaPoolConfig) loadFromJsonCfg(jsnCfg *HaPoolJsonCfg) error { + if jsnCfg == nil { + return nil + } + if jsnCfg.Server != nil { + self.Server = *jsnCfg.Server + } + return nil } // Returns the first cached default value for a SM-FreeSWITCH connection @@ -92,11 +101,19 @@ func (self *SmGenericConfig) loadFromJsonCfg(jsnCfg *SmGenericJsonCfg) error { if jsnCfg.Listen_bijson != nil { self.ListenBijson = *jsnCfg.Listen_bijson } - if jsnCfg.Rater != nil { - self.HaRater = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Rater, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_rater != nil { + self.HaRater = make([]*HaPoolConfig, len(*jsnCfg.Ha_rater)) + for idx, jsnHaCfg := range *jsnCfg.Ha_rater { + self.HaRater[idx] = NewDfltHaPoolConfig() + self.HaRater[idx].loadFromJsonCfg(jsnHaCfg) + } } - if jsnCfg.Cdrs != nil { - self.HaCdrs = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Cdrs, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_cdrs != nil { + self.HaCdrs = make([]*HaPoolConfig, len(*jsnCfg.Ha_cdrs)) + for idx, jsnHaCfg := range *jsnCfg.Ha_cdrs { + self.HaCdrs[idx] = NewDfltHaPoolConfig() + self.HaCdrs[idx].loadFromJsonCfg(jsnHaCfg) + } } if jsnCfg.Debit_interval != nil { if self.DebitInterval, err = utils.ParseDurationWithSecs(*jsnCfg.Debit_interval); err != nil { @@ -142,11 +159,19 @@ func (self *SmFsConfig) loadFromJsonCfg(jsnCfg *SmFsJsonCfg) error { if jsnCfg.Enabled != nil { self.Enabled = *jsnCfg.Enabled } - if jsnCfg.Rater != nil { - self.HaRater = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Rater, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_rater != nil { + self.HaRater = make([]*HaPoolConfig, len(*jsnCfg.Ha_rater)) + for idx, jsnHaCfg := range *jsnCfg.Ha_rater { + self.HaRater[idx] = NewDfltHaPoolConfig() + self.HaRater[idx].loadFromJsonCfg(jsnHaCfg) + } } - if jsnCfg.Cdrs != nil { - self.HaCdrs = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Cdrs, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_cdrs != nil { + self.HaCdrs = make([]*HaPoolConfig, len(*jsnCfg.Ha_cdrs)) + for idx, jsnHaCfg := range *jsnCfg.Ha_cdrs { + self.HaCdrs[idx] = NewDfltHaPoolConfig() + self.HaCdrs[idx].loadFromJsonCfg(jsnHaCfg) + } } if jsnCfg.Create_cdr != nil { self.CreateCdr = *jsnCfg.Create_cdr @@ -251,11 +276,19 @@ func (self *SmKamConfig) loadFromJsonCfg(jsnCfg *SmKamJsonCfg) error { if jsnCfg.Enabled != nil { self.Enabled = *jsnCfg.Enabled } - if jsnCfg.Rater != nil { - self.HaRater = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Rater, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_rater != nil { + self.HaRater = make([]*HaPoolConfig, len(*jsnCfg.Ha_rater)) + for idx, jsnHaCfg := range *jsnCfg.Ha_rater { + self.HaRater[idx] = NewDfltHaPoolConfig() + self.HaRater[idx].loadFromJsonCfg(jsnHaCfg) + } } - if jsnCfg.Cdrs != nil { - self.HaCdrs = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Cdrs, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_cdrs != nil { + self.HaCdrs = make([]*HaPoolConfig, len(*jsnCfg.Ha_cdrs)) + for idx, jsnHaCfg := range *jsnCfg.Ha_cdrs { + self.HaCdrs[idx] = NewDfltHaPoolConfig() + self.HaCdrs[idx].loadFromJsonCfg(jsnHaCfg) + } } if jsnCfg.Create_cdr != nil { self.CreateCdr = *jsnCfg.Create_cdr @@ -323,11 +356,19 @@ func (self *SmOsipsConfig) loadFromJsonCfg(jsnCfg *SmOsipsJsonCfg) error { if jsnCfg.Listen_udp != nil { self.ListenUdp = *jsnCfg.Listen_udp } - if jsnCfg.Rater != nil { - self.HaRater = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Rater, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_rater != nil { + self.HaRater = make([]*HaPoolConfig, len(*jsnCfg.Ha_rater)) + for idx, jsnHaCfg := range *jsnCfg.Ha_rater { + self.HaRater[idx] = NewDfltHaPoolConfig() + self.HaRater[idx].loadFromJsonCfg(jsnHaCfg) + } } - if jsnCfg.Cdrs != nil { - self.HaCdrs = []*HaPoolConfig{&HaPoolConfig{Server: *jsnCfg.Cdrs, Timeout: time.Duration(1) * time.Second}} + if jsnCfg.Ha_cdrs != nil { + self.HaCdrs = make([]*HaPoolConfig, len(*jsnCfg.Ha_cdrs)) + for idx, jsnHaCfg := range *jsnCfg.Ha_cdrs { + self.HaCdrs[idx] = NewDfltHaPoolConfig() + self.HaCdrs[idx].loadFromJsonCfg(jsnHaCfg) + } } if jsnCfg.Create_cdr != nil { self.CreateCdr = *jsnCfg.Create_cdr diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index e35dd57c7..d31fa7e98 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -180,8 +180,12 @@ //"sm_generic": { // "enabled": false, // starts SessionManager service: // "listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "debit_interval": "0s", // interval to perform debits on. // "min_call_duration": "0s", // only authorize calls with allowed duration higher than this // "max_call_duration": "3h", // maximum call duration a prepaid call can last @@ -190,8 +194,12 @@ //"sm_freeswitch": { // "enabled": false, // starts SessionManager service: -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "extra_fields": [], // extra fields to store in auth/CDRs when creating them // "debit_interval": "10s", // interval to perform debits on. @@ -211,8 +219,12 @@ //"sm_kamailio": { // "enabled": false, // starts SessionManager service: -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "debit_interval": "10s", // interval to perform debits on. // "min_call_duration": "0s", // only authorize calls with allowed duration higher than this @@ -226,8 +238,12 @@ //"sm_opensips": { // "enabled": false, // starts SessionManager service: // "listen_udp": "127.0.0.1:2020", // address where to listen for datagram events coming from OpenSIPS -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "reconnects": 5, // number of reconnects if connection is lost // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "debit_interval": "10s", // interval to perform debits on. @@ -334,4 +350,4 @@ // "tax_exemption_code_list": "", // template extracting tax exemption code list out of StoredCdr; <$RSRFields> //}, -} \ No newline at end of file +} diff --git a/data/conf/samples/dmtagent/cgrates.json b/data/conf/samples/dmtagent/cgrates.json index ff1387e85..d955b34fc 100644 --- a/data/conf/samples/dmtagent/cgrates.json +++ b/data/conf/samples/dmtagent/cgrates.json @@ -47,8 +47,12 @@ "sm_generic": { "enabled": true, - "rater": "internal", - "cdrs": "internal", + "ha_rater": [ + {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> + ], + "ha_cdrs": [ + {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing + ], }, "diameter_agent": { diff --git a/data/conf/samples/smgeneric/cgrates.json b/data/conf/samples/smgeneric/cgrates.json index 7907e7a47..385242808 100644 --- a/data/conf/samples/smgeneric/cgrates.json +++ b/data/conf/samples/smgeneric/cgrates.json @@ -179,8 +179,12 @@ "sm_generic": { "enabled": true, // starts SessionManager service: // "listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "debit_interval": "10s", // interval to perform debits on. // "min_call_duration": "0s", // only authorize calls with allowed duration higher than this // "max_call_duration": "3h", // maximum call duration a prepaid call can last @@ -189,8 +193,12 @@ //"sm_freeswitch": { // "enabled": false, // starts SessionManager service: -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "extra_fields": [], // extra fields to store in auth/CDRs when creating them // "debit_interval": "10s", // interval to perform debits on. @@ -210,8 +218,12 @@ //"sm_kamailio": { // "enabled": false, // starts SessionManager service: -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "debit_interval": "10s", // interval to perform debits on. // "min_call_duration": "0s", // only authorize calls with allowed duration higher than this @@ -225,8 +237,12 @@ //"sm_opensips": { // "enabled": false, // starts SessionManager service: // "listen_udp": "127.0.0.1:2020", // address where to listen for datagram events coming from OpenSIPS -// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013> -// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234> +// "ha_rater": [ +// {"server": "internal"} // address where to reach the Rater <""|internal|127.0.0.1:2013> +// ], +// "ha_cdrs": [ +// {"server": "internal"} // address where to reach CDR Server, empty to disable CDR capturing +// ], // "reconnects": 5, // number of reconnects if connection is lost // "create_cdr": false, // create CDR out of events and sends them to CDRS component // "debit_interval": "10s", // interval to perform debits on. diff --git a/devel.yaml b/devel.yaml index 3af8b74b5..d2a7d0226 100644 --- a/devel.yaml +++ b/devel.yaml @@ -2,6 +2,7 @@ package: github.com/cgrates/cgrates import: - package: github.com/ugorji/go - package: github.com/jinzhu/gorm + - package: github.com/jinzhu/inflection - package: golang.org/x/net - package: github.com/DisposaBoy/JsonConfigReader - package: github.com/go-sql-driver/mysql