mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
MSSQL: By default let driver choose port (#32417)
* MSSQL: By default let driver choose port Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
parent
0e47a476fb
commit
2c72f8babc
@ -16,7 +16,7 @@ Grafana ships with a built-in Microsoft SQL Server (MS SQL) data source plugin t
|
|||||||
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `Name` | The data source name. This is how you refer to the data source in panels and queries. |
|
| `Name` | The data source name. This is how you refer to the data source in panels and queries. |
|
||||||
| `Default` | Default data source means that it will be pre-selected for new panels. |
|
| `Default` | Default data source means that it will be pre-selected for new panels. |
|
||||||
| `Host` | The IP address/hostname and optional port of your MS SQL instance. If port is omitted, default 1433 will be used. |
|
| `Host` | The IP address/hostname and optional port of your MS SQL instance. If the port is omitted, the driver default will be used (0). |
|
||||||
| `Database` | Name of your MS SQL database. |
|
| `Database` | Name of your MS SQL database. |
|
||||||
| `Authentication` | Authentication mode. Either using SQL Server Authentication or Windows Authentication (single sign on for Windows users). |
|
| `Authentication` | Authentication mode. Either using SQL Server Authentication or Windows Authentication (single sign on for Windows users). |
|
||||||
| `User` | Database user's login/username |
|
| `User` | Database user's login/username |
|
||||||
|
@ -66,33 +66,44 @@ func ParseURL(u string) (*url.URL, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateConnectionString(datasource *models.DataSource) (string, error) {
|
func generateConnectionString(dataSource *models.DataSource) (string, error) {
|
||||||
|
const dfltPort = "0"
|
||||||
var addr util.NetworkAddress
|
var addr util.NetworkAddress
|
||||||
if datasource.Url != "" {
|
if dataSource.Url != "" {
|
||||||
u, err := ParseURL(datasource.Url)
|
u, err := ParseURL(dataSource.Url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
addr, err = util.SplitHostPortDefault(u.Host, "localhost", "1433")
|
addr, err = util.SplitHostPortDefault(u.Host, "localhost", dfltPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addr = util.NetworkAddress{
|
addr = util.NetworkAddress{
|
||||||
Host: "localhost",
|
Host: "localhost",
|
||||||
Port: "1433",
|
Port: dfltPort,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("Generating connection string", "url", datasource.Url, "host", addr.Host, "port", addr.Port)
|
args := []interface{}{
|
||||||
encrypt := datasource.JsonData.Get("encrypt").MustString("false")
|
"url", dataSource.Url, "host", addr.Host,
|
||||||
connStr := fmt.Sprintf("server=%s;port=%s;database=%s;user id=%s;password=%s;",
|
}
|
||||||
|
if addr.Port != "0" {
|
||||||
|
args = append(args, "port", addr.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug("Generating connection string", args...)
|
||||||
|
encrypt := dataSource.JsonData.Get("encrypt").MustString("false")
|
||||||
|
connStr := fmt.Sprintf("server=%s;database=%s;user id=%s;password=%s;",
|
||||||
addr.Host,
|
addr.Host,
|
||||||
addr.Port,
|
dataSource.Database,
|
||||||
datasource.Database,
|
dataSource.User,
|
||||||
datasource.User,
|
dataSource.DecryptedPassword(),
|
||||||
datasource.DecryptedPassword(),
|
|
||||||
)
|
)
|
||||||
|
// Port number 0 means to determine the port automatically, so we can let the driver choose
|
||||||
|
if addr.Port != "0" {
|
||||||
|
connStr += fmt.Sprintf("port=%s;", addr.Port)
|
||||||
|
}
|
||||||
if encrypt != "false" {
|
if encrypt != "false" {
|
||||||
connStr += fmt.Sprintf("encrypt=%s;", encrypt)
|
connStr += fmt.Sprintf("encrypt=%s;", encrypt)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ var serverIP = "localhost"
|
|||||||
|
|
||||||
func TestMSSQL(t *testing.T) {
|
func TestMSSQL(t *testing.T) {
|
||||||
SkipConvey("MSSQL", t, func() {
|
SkipConvey("MSSQL", t, func() {
|
||||||
x := InitMSSQLTestDB(t)
|
x := initMSSQLTestDB(t)
|
||||||
|
|
||||||
origXormEngine := sqleng.NewXormEngine
|
origXormEngine := sqleng.NewXormEngine
|
||||||
sqleng.NewXormEngine = func(d, c string) (*xorm.Engine, error) {
|
sqleng.NewXormEngine = func(d, c string) (*xorm.Engine, error) {
|
||||||
@ -1161,13 +1162,70 @@ func TestTransformQueryError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitMSSQLTestDB(t *testing.T) *xorm.Engine {
|
func TestGenerateConnectionString(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
dataSource *models.DataSource
|
||||||
|
expConnStr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "From URL w/ port",
|
||||||
|
dataSource: &models.DataSource{
|
||||||
|
Url: "localhost:1001",
|
||||||
|
Database: "database",
|
||||||
|
User: "user",
|
||||||
|
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||||
|
},
|
||||||
|
expConnStr: "server=localhost;database=database;user id=user;password=;port=1001;",
|
||||||
|
},
|
||||||
|
// When no port is specified, the driver should be allowed to choose
|
||||||
|
{
|
||||||
|
desc: "From URL w/o port",
|
||||||
|
dataSource: &models.DataSource{
|
||||||
|
Url: "localhost",
|
||||||
|
Database: "database",
|
||||||
|
User: "user",
|
||||||
|
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||||
|
},
|
||||||
|
expConnStr: "server=localhost;database=database;user id=user;password=;",
|
||||||
|
},
|
||||||
|
// Port 0 should be equivalent to not specifying a port, i.e. let the driver choose
|
||||||
|
{
|
||||||
|
desc: "From URL w port 0",
|
||||||
|
dataSource: &models.DataSource{
|
||||||
|
Url: "localhost:0",
|
||||||
|
Database: "database",
|
||||||
|
User: "user",
|
||||||
|
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||||
|
},
|
||||||
|
expConnStr: "server=localhost;database=database;user id=user;password=;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Defaults",
|
||||||
|
dataSource: &models.DataSource{
|
||||||
|
Database: "database",
|
||||||
|
User: "user",
|
||||||
|
JsonData: simplejson.NewFromAny(map[string]interface{}{}),
|
||||||
|
},
|
||||||
|
expConnStr: "server=localhost;database=database;user id=user;password=;",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
connStr, err := generateConnectionString(tc.dataSource)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, tc.expConnStr, connStr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initMSSQLTestDB(t *testing.T) *xorm.Engine {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
testDB := sqlutil.MSSQLTestDB()
|
testDB := sqlutil.MSSQLTestDB()
|
||||||
x, err := xorm.NewEngine(testDB.DriverName, strings.Replace(testDB.ConnStr, "localhost",
|
x, err := xorm.NewEngine(testDB.DriverName, strings.Replace(testDB.ConnStr, "localhost",
|
||||||
serverIP, 1))
|
serverIP, 1))
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("Failed to init mssql db %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
x.DatabaseTZ = time.UTC
|
x.DatabaseTZ = time.UTC
|
||||||
x.TZLocation = time.UTC
|
x.TZLocation = time.UTC
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
<div class="gf-form max-width-30">
|
<div class="gf-form max-width-30">
|
||||||
<span class="gf-form-label width-7">Host</span>
|
<span class="gf-form-label width-7">Host</span>
|
||||||
<input type="text" class="gf-form-input" style="width: 352px" ng-model='ctrl.current.url' placeholder="localhost:1433" bs-typeahead="{{['localhost', 'localhost:1433']}}" required></input>
|
<input type="text" class="gf-form-input" style="width: 352px" ng-model='ctrl.current.url' placeholder="localhost" bs-typeahead="{{['localhost', 'localhost" required></input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form max-width-30">
|
<div class="gf-form max-width-30">
|
||||||
|
Loading…
Reference in New Issue
Block a user