Browse Source
Move database settings from models to setting (#7806)
Move database settings from models to setting (#7806)
* move database settings from models to setting * update docs * fix checkout pr * fix tests * fix lint * remove unsupported tidb options * correct wrong variable name * remove tidb totallyrelease/v1.10
committed by
Antoine GIRARD
35 changed files with 424 additions and 377 deletions
-
2cmd/cmd.go
-
4cmd/convert.go
-
5cmd/dump.go
-
2cmd/migrate.go
-
10contrib/pr/checkout.go
-
4custom/conf/app.ini.sample
-
2docs/content/doc/advanced/config-cheat-sheet.en-us.md
-
2docs/content/doc/advanced/config-cheat-sheet.zh-cn.md
-
26integrations/integration_test.go
-
2integrations/lfs_getobject_test.go
-
48integrations/migration-test/migration_test.go
-
8models/convert.go
-
8models/migrations/migrations.go
-
2models/migrations/v19.go
-
2models/migrations/v22.go
-
2models/migrations/v26.go
-
2models/migrations/v27.go
-
4models/migrations/v33.go
-
4models/migrations/v45.go
-
4models/migrations/v50.go
-
4models/migrations/v67.go
-
2models/migrations/v81.go
-
148models/models.go
-
91models/models_test.go
-
6models/repo.go
-
2models/unit_tests.go
-
5models/user.go
-
8models/user_heatmap.go
-
171modules/setting/database.go
-
4modules/setting/database_sqlite.go
-
94modules/setting/database_test.go
-
38modules/setting/setting.go
-
4routers/admin/admin.go
-
19routers/init.go
-
62routers/install.go
@ -0,0 +1,171 @@ |
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|||
// Use of this source code is governed by a MIT-style
|
|||
// license that can be found in the LICENSE file.
|
|||
|
|||
package setting |
|||
|
|||
import ( |
|||
"errors" |
|||
"fmt" |
|||
"net/url" |
|||
"os" |
|||
"path" |
|||
"path/filepath" |
|||
"strings" |
|||
"time" |
|||
) |
|||
|
|||
var ( |
|||
// SupportedDatabases includes all supported databases type
|
|||
SupportedDatabases = []string{"MySQL", "PostgreSQL", "MSSQL"} |
|||
dbTypes = map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3"} |
|||
|
|||
// EnableSQLite3 use SQLite3, set by build flag
|
|||
EnableSQLite3 bool |
|||
|
|||
// Database holds the database settings
|
|||
Database = struct { |
|||
Type string |
|||
Host string |
|||
Name string |
|||
User string |
|||
Passwd string |
|||
SSLMode string |
|||
Path string |
|||
LogSQL bool |
|||
Charset string |
|||
Timeout int // seconds
|
|||
UseSQLite3 bool |
|||
UseMySQL bool |
|||
UseMSSQL bool |
|||
UsePostgreSQL bool |
|||
DBConnectRetries int |
|||
DBConnectBackoff time.Duration |
|||
MaxIdleConns int |
|||
ConnMaxLifetime time.Duration |
|||
IterateBufferSize int |
|||
}{ |
|||
Timeout: 500, |
|||
MaxIdleConns: 0, |
|||
ConnMaxLifetime: 3 * time.Second, |
|||
} |
|||
) |
|||
|
|||
// GetDBTypeByName returns the dataase type as it defined on XORM according the given name
|
|||
func GetDBTypeByName(name string) string { |
|||
return dbTypes[name] |
|||
} |
|||
|
|||
// InitDBConfig loads the database settings
|
|||
func InitDBConfig() { |
|||
sec := Cfg.Section("database") |
|||
Database.Type = sec.Key("DB_TYPE").String() |
|||
switch Database.Type { |
|||
case "sqlite3": |
|||
Database.UseSQLite3 = true |
|||
case "mysql": |
|||
Database.UseMySQL = true |
|||
case "postgres": |
|||
Database.UsePostgreSQL = true |
|||
case "mssql": |
|||
Database.UseMSSQL = true |
|||
} |
|||
Database.Host = sec.Key("HOST").String() |
|||
Database.Name = sec.Key("NAME").String() |
|||
Database.User = sec.Key("USER").String() |
|||
if len(Database.Passwd) == 0 { |
|||
Database.Passwd = sec.Key("PASSWD").String() |
|||
} |
|||
Database.SSLMode = sec.Key("SSL_MODE").MustString("disable") |
|||
Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) |
|||
Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) |
|||
Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) |
|||
Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(0) |
|||
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second) |
|||
|
|||
Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50) |
|||
Database.LogSQL = sec.Key("LOG_SQL").MustBool(true) |
|||
Database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10) |
|||
Database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second) |
|||
} |
|||
|
|||
// DBConnStr returns database connection string
|
|||
func DBConnStr() (string, error) { |
|||
connStr := "" |
|||
var Param = "?" |
|||
if strings.Contains(Database.Name, Param) { |
|||
Param = "&" |
|||
} |
|||
switch Database.Type { |
|||
case "mysql": |
|||
connType := "tcp" |
|||
if Database.Host[0] == '/' { // looks like a unix socket
|
|||
connType = "unix" |
|||
} |
|||
tls := Database.SSLMode |
|||
if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL
|
|||
tls = "false" |
|||
} |
|||
connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s", |
|||
Database.User, Database.Passwd, connType, Database.Host, Database.Name, Param, Database.Charset, tls) |
|||
case "postgres": |
|||
connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Param, Database.SSLMode) |
|||
case "mssql": |
|||
host, port := ParseMSSQLHostPort(Database.Host) |
|||
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd) |
|||
case "sqlite3": |
|||
if !EnableSQLite3 { |
|||
return "", errors.New("this binary version does not build support for SQLite3") |
|||
} |
|||
if err := os.MkdirAll(path.Dir(Database.Path), os.ModePerm); err != nil { |
|||
return "", fmt.Errorf("Failed to create directories: %v", err) |
|||
} |
|||
connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", Database.Path, Database.Timeout) |
|||
default: |
|||
return "", fmt.Errorf("Unknown database type: %s", Database.Type) |
|||
} |
|||
|
|||
return connStr, nil |
|||
} |
|||
|
|||
// parsePostgreSQLHostPort parses given input in various forms defined in
|
|||
// https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
|||
// and returns proper host and port number.
|
|||
func parsePostgreSQLHostPort(info string) (string, string) { |
|||
host, port := "127.0.0.1", "5432" |
|||
if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") { |
|||
idx := strings.LastIndex(info, ":") |
|||
host = info[:idx] |
|||
port = info[idx+1:] |
|||
} else if len(info) > 0 { |
|||
host = info |
|||
} |
|||
return host, port |
|||
} |
|||
|
|||
func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) { |
|||
host, port := parsePostgreSQLHostPort(dbHost) |
|||
if host[0] == '/' { // looks like a unix socket
|
|||
connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s", |
|||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host) |
|||
} else { |
|||
connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s", |
|||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode) |
|||
} |
|||
return |
|||
} |
|||
|
|||
// ParseMSSQLHostPort splits the host into host and port
|
|||
func ParseMSSQLHostPort(info string) (string, string) { |
|||
host, port := "127.0.0.1", "1433" |
|||
if strings.Contains(info, ":") { |
|||
host = strings.Split(info, ":")[0] |
|||
port = strings.Split(info, ":")[1] |
|||
} else if strings.Contains(info, ",") { |
|||
host = strings.Split(info, ",")[0] |
|||
port = strings.TrimSpace(strings.Split(info, ",")[1]) |
|||
} else if len(info) > 0 { |
|||
host = info |
|||
} |
|||
return host, port |
|||
} |
@ -0,0 +1,94 @@ |
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|||
// Use of this source code is governed by a MIT-style
|
|||
// license that can be found in the LICENSE file.
|
|||
|
|||
package setting |
|||
|
|||
import ( |
|||
"testing" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func Test_parsePostgreSQLHostPort(t *testing.T) { |
|||
tests := []struct { |
|||
HostPort string |
|||
Host string |
|||
Port string |
|||
}{ |
|||
{ |
|||
HostPort: "127.0.0.1:1234", |
|||
Host: "127.0.0.1", |
|||
Port: "1234", |
|||
}, |
|||
{ |
|||
HostPort: "127.0.0.1", |
|||
Host: "127.0.0.1", |
|||
Port: "5432", |
|||
}, |
|||
{ |
|||
HostPort: "[::1]:1234", |
|||
Host: "[::1]", |
|||
Port: "1234", |
|||
}, |
|||
{ |
|||
HostPort: "[::1]", |
|||
Host: "[::1]", |
|||
Port: "5432", |
|||
}, |
|||
{ |
|||
HostPort: "/tmp/pg.sock:1234", |
|||
Host: "/tmp/pg.sock", |
|||
Port: "1234", |
|||
}, |
|||
{ |
|||
HostPort: "/tmp/pg.sock", |
|||
Host: "/tmp/pg.sock", |
|||
Port: "5432", |
|||
}, |
|||
} |
|||
for _, test := range tests { |
|||
host, port := parsePostgreSQLHostPort(test.HostPort) |
|||
assert.Equal(t, test.Host, host) |
|||
assert.Equal(t, test.Port, port) |
|||
} |
|||
} |
|||
|
|||
func Test_getPostgreSQLConnectionString(t *testing.T) { |
|||
tests := []struct { |
|||
Host string |
|||
Port string |
|||
User string |
|||
Passwd string |
|||
Name string |
|||
Param string |
|||
SSLMode string |
|||
Output string |
|||
}{ |
|||
{ |
|||
Host: "/tmp/pg.sock", |
|||
Port: "4321", |
|||
User: "testuser", |
|||
Passwd: "space space !#$%^^%^```-=?=", |
|||
Name: "gitea", |
|||
Param: "", |
|||
SSLMode: "false", |
|||
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock", |
|||
}, |
|||
{ |
|||
Host: "localhost", |
|||
Port: "1234", |
|||
User: "pgsqlusername", |
|||
Passwd: "I love Gitea!", |
|||
Name: "gitea", |
|||
Param: "", |
|||
SSLMode: "true", |
|||
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true", |
|||
}, |
|||
} |
|||
|
|||
for _, test := range tests { |
|||
connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode) |
|||
assert.Equal(t, test.Output, connStr) |
|||
} |
|||
} |