Merge pull request #20 from netbenix/develop

Implemented MSSQL
This commit is contained in:
netbenix 2022-01-31 20:13:35 +01:00 committed by GitHub
commit 754709f7eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 267 additions and 22 deletions

View file

@ -16,12 +16,14 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
## Database Types
- MariaDB
- MySQL (soon)
- MS-SQL (far future)
- MySQL
- MS-SQL
| Database Type | Config Type |
|-------------------|---------------------------|
|---------------|-------------|
| MariaDB | mariadb |
| MySQL | mysql |
| MS-SQL | mssql |
## Storage types
@ -69,3 +71,38 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
| fileshareName | string | The name of the Azure File Share |
| storageAccountName | string | Name of your storage account |
| storageAccountKey | string | Key for the storage account |
## Config Examples
### config.json (Linux)
```
{
"foldersToBackup": [
{
"backupName": "my-backup",
"folderPath": "/path/to/folder/to/backup",
"remoteStorageType": "remote-type",
"remoteTargetPath": "path/to",
"createLocalBackup": true,
"localTargetPath": "/path/for/local/backup"
}
]
}
```
### config.json (Windows)
```
{
"foldersToBackup": [
{
"backupName": "my-backup",
"folderPath": "D:\\Path\\To\\Folder\\To\\Backup",
"remoteStorageType": "remote-type",
"remoteTargetPath": "path/to",
"createLocalBackup": true,
"localTargetPath": "E:\\Path\\For\\Local Backup"
}
]
}
```

View file

@ -1,5 +1,7 @@
package SQL
import "fmt"
type LogType int64
const (
@ -8,3 +10,18 @@ const(
LogError = 3
LogFatal = 4
)
func (e LogType) String() string {
switch e {
case LogInfo:
return "INFO"
case LogWarning:
return "WARNING"
case LogError:
return "ERROR"
case LogFatal:
return "FATAL"
default:
return fmt.Sprintf("%d", e)
}
}

144
SQL/MSSQLConnector.go Normal file
View file

@ -0,0 +1,144 @@
package SQL
import (
"database/sql"
"fmt"
mssqlpkg "github.com/denisenkom/go-mssqldb"
"github.com/google/uuid"
"net/url"
"os"
"scabiosa/Logging"
"scabiosa/Tools"
"time"
)
type MSSQLConnector struct {
Address string
Port uint16
Database string
DbUser string
DbPassword string
}
func GetMSSQLInstance(sqlConfig Tools.SQLConfig) MSSQLConnector {
var mssql MSSQLConnector
mssql.Address = sqlConfig.SqlAddress
mssql.Port = sqlConfig.SqlPort
mssql.Database = sqlConfig.Database
mssql.DbUser = sqlConfig.DbUser
mssql.DbPassword = sqlConfig.DbPassword
return mssql
}
func (mssql MSSQLConnector) checkIfEventLogTableExist(db *sql.DB) bool {
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'EventLog';")
if !rows.Next() {
return false
}
return true
}
func (mssql MSSQLConnector) checkIfBackupTableExist(db *sql.DB) bool {
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Backups';")
if !rows.Next() {
return false
}
return true
}
func (mssql MSSQLConnector) checkIfBackupEntryExist(db *sql.DB, backupName string, hostname string) bool {
query := fmt.Sprintf("SELECT * FROM dbo.Backups WHERE Hostname = '%s' AND BackupName = '%s'", hostname, backupName)
rows, _ := db.Query(query)
if !rows.Next() {
return false
}
return true
}
func createMSSQLConnection(mssql MSSQLConnector) *sql.DB {
logger := Logging.DetailedLogger("MS-SQL", "createConnection")
query := url.Values{}
query.Add("app name", "scabiosa")
query.Add("database", "scabiosa-test")
sqlSettings := &url.URL{
Scheme: "sqlserver",
User: url.UserPassword(mssql.DbUser, mssql.DbPassword),
Host: fmt.Sprintf("%s:%d", mssql.Address, mssql.Port),
RawQuery: query.Encode(),
}
connector, err := mssqlpkg.NewConnector(sqlSettings.String())
if err != nil {
logger.Fatal(err)
}
connector.SessionInitSQL = "SET ANSI_NULLS ON"
db := sql.OpenDB(connector)
return db
}
func (mssql MSSQLConnector) createDefaultTables() {
logger := Logging.DetailedLogger("MS-SQL", "createDefaultTables")
eventLogSQL := "create table dbo.EventLog(UUID text null, LogType VARCHAR(20) NOT NULL CHECK (LogType IN('INFO', 'WARNING', 'ERROR', 'FATAL')), Hostname varchar(256) null, BackupName varchar(256) null, Stage VARCHAR(20) NOT NULL CHECK (Stage IN('COMPRESS', 'UPLOAD', 'DELETE TMP')), RemoteStorage VARCHAR(20) NOT NULL CHECK (RemoteStorage IN('AZURE-FILE', 'AZURE-BLOB', 'NONE')), Description text null, Timestamp datetime null);"
backupSQL := "create table dbo.Backups(UUID text null, Hostname varchar(256) null, BackupName varchar(256) null, LastBackup datetime null, LocalBackup tinyint null, FilePath varchar(256) null, RemoteStorage VARCHAR(20) NOT NULL CHECK (RemoteStorage IN('AZURE-FILE', 'AZURE-BLOB', 'NONE')), RemotePath varchar(256) null, LocalPath varchar(256) null);"
db := createMSSQLConnection(mssql)
if !mssql.checkIfBackupTableExist(db) {
_, err := db.Exec(backupSQL)
if err != nil {
logger.Fatal(err)
}
}
if !mssql.checkIfEventLogTableExist(db) {
_, err := db.Exec(eventLogSQL)
if err != nil {
logger.Fatal(err)
}
}
_ = db.Close()
}
func (mssql MSSQLConnector) newLogEntry(uuid uuid.UUID, logType LogType, backupName string, stage SQLStage, storageType RemoteStorageType, description string, timestamp time.Time) {
logger := Logging.DetailedLogger("MS-SQL", "newLogEntry")
db := createMSSQLConnection(mssql)
hostname, _ := os.Hostname()
query := fmt.Sprintf("INSERT INTO dbo.EventLog VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", uuid.String(), logType.String(), hostname, backupName, stage.String(), storageType.String(), description, timestamp.Format("2006-01-02 15:04:05.999"))
_, err := db.Query(query)
if err != nil {
logger.Fatal(err)
}
}
func (mssql MSSQLConnector) newBackupEntry(backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string, localPath string) {
logger := Logging.DetailedLogger("MS-SQL", "newBackupEntry")
db := createMSSQLConnection(mssql)
hostname, _ := os.Hostname()
var localBackupInt uint8
if localBackup {
localBackupInt = 1
}
if mssql.checkIfBackupEntryExist(db, backupName, hostname) {
queryUpdate := fmt.Sprintf("UPDATE dbo.Backups SET Lastbackup = '%s', LocalBackup = %d, RemoteStorage = '%s', RemotePath = '%s', LocalPath = '%s' WHERE Hostname = '%s' AND BackupName = '%s'", lastBackup.Format("2006-01-02 15:04:05.999"), localBackupInt, storageType.String(), remotePath, localPath, hostname, backupName)
_, err := db.Query(queryUpdate)
if err != nil {
logger.Fatal(err)
}
} else {
queryInsert := fmt.Sprintf("INSERT INTO dbo.Backups VALUES ('%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s')", uuid.New(), hostname, backupName, lastBackup.Format("2006-01-02 15:04:05.999"), localBackupInt, filePath, storageType.String(), remotePath, localPath)
_, err := db.Query(queryInsert)
if err != nil {
logger.Fatal(err)
}
}
}

View file

@ -31,7 +31,7 @@ func GetMariaDBInstance(sqlConfig Tools.SQLConfig) MariaDBConnector {
return mariadb
}
func checkIfEventLogTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
func (mariadb MariaDBConnector) checkIfEventLogTableExist(db *sql.DB) bool {
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'EventLog';", mariadb.Database)
if !rows.Next() {
return false
@ -39,7 +39,7 @@ func checkIfEventLogTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
return true
}
func checkIfBackupTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
func (mariadb MariaDBConnector) checkIfBackupTableExist(db *sql.DB) bool {
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'Backups';", mariadb.Database)
if !rows.Next() {
return false
@ -47,7 +47,7 @@ func checkIfBackupTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
return true
}
func checkIfBackupEntryExist(db *sql.DB, mariadb MariaDBConnector, backupName string, hostname string) bool {
func (mariadb MariaDBConnector) checkIfBackupEntryExist(db *sql.DB, backupName string, hostname string) bool {
rows, _ := db.Query("SELECT * FROM `"+mariadb.Database+"`.Backups WHERE Hostname = ? AND BackupName = ?;", hostname, backupName)
if !rows.Next() {
return false
@ -72,14 +72,14 @@ func (mariadb MariaDBConnector) createDefaultTables() {
db := createMariaDBConnection(mariadb)
if !checkIfBackupTableExist(db, mariadb) {
if !mariadb.checkIfBackupTableExist(db) {
_, err := db.Exec(backupSQL)
if err != nil {
logger.Fatal(err)
}
}
if !checkIfEventLogTableExist(db, mariadb) {
if !mariadb.checkIfEventLogTableExist(db) {
_, err := db.Exec(eventLogSQL)
if err != nil {
logger.Fatal(err)
@ -108,7 +108,7 @@ func (mariadb MariaDBConnector) newBackupEntry(backupName string, lastBackup tim
hostname, _ := os.Hostname()
if checkIfBackupEntryExist(db, mariadb, backupName, hostname) {
if mariadb.checkIfBackupEntryExist(db, backupName, hostname) {
_, err := db.Query("UPDATE `"+mariadb.Database+"`.Backups SET LastBackup = ?, LocalBackup = ?, RemoteStorage = ?, RemotePath = ?, LocalPath = ? WHERE Hostname = ? AND BackupName = ?;", lastBackup, localBackup, strconv.FormatInt(int64(storageType), 10), remotePath, localPath, hostname, backupName)
if err != nil {
logger.Fatal(err)

View file

@ -1,5 +1,7 @@
package SQL
import "fmt"
type RemoteStorageType int64
const (
@ -7,3 +9,16 @@ const(
REMOTE_AZURE_BLOB = 2
REMOTE_NONE = 3
)
func (e RemoteStorageType) String() string {
switch e {
case REMOTE_AZURE_FILE:
return "AZURE-FILE"
case REMOTE_AZURE_BLOB:
return "AZURE-BLOB"
case REMOTE_NONE:
return "NONE"
default:
return fmt.Sprintf("%d", e)
}
}

View file

@ -45,6 +45,14 @@ func GetSQLInstance() SQLService {
{
return GetMariaDBInstance(sqlConfig)
}
case "mysql":
{
return GetMariaDBInstance(sqlConfig)
}
case "mssql":
{
return GetMSSQLInstance(sqlConfig)
}
}
return nil

View file

@ -1,5 +1,7 @@
package SQL
import "fmt"
type SQLStage int64
const (
@ -7,3 +9,16 @@ const(
SQLStage_Upload = 2
SQLStage_DeleteTmp = 3
)
func (e SQLStage) String() string {
switch e {
case SQLStage_Compress:
return "COMPRESS"
case SQLStage_Upload:
return "UPLOAD"
case SQLStage_DeleteTmp:
return "DELETE TMP"
default:
return fmt.Sprintf("%d", e)
}
}

3
go.mod
View file

@ -16,7 +16,9 @@ require (
github.com/Azure/azure-pipeline-go v0.2.1 // indirect
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/denisenkom/go-mssqldb v0.11.0 // indirect
github.com/fatih/color v1.10.0 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
@ -25,6 +27,7 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c // indirect
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
golang.org/x/text v0.3.0 // indirect

6
go.sum
View file

@ -11,10 +11,14 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI=
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@ -49,6 +53,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=