commit
754709f7eb
9 changed files with 267 additions and 22 deletions
43
README.md
43
README.md
|
|
@ -16,12 +16,14 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
||||||
|
|
||||||
## Database Types
|
## Database Types
|
||||||
- MariaDB
|
- MariaDB
|
||||||
- MySQL (soon)
|
- MySQL
|
||||||
- MS-SQL (far future)
|
- MS-SQL
|
||||||
|
|
||||||
| Database Type | Config Type |
|
| Database Type | Config Type |
|
||||||
|-------------------|---------------------------|
|
|---------------|-------------|
|
||||||
| MariaDB | mariadb |
|
| MariaDB | mariadb |
|
||||||
|
| MySQL | mysql |
|
||||||
|
| MS-SQL | mssql |
|
||||||
|
|
||||||
|
|
||||||
## Storage types
|
## Storage types
|
||||||
|
|
@ -69,3 +71,38 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
||||||
| fileshareName | string | The name of the Azure File Share |
|
| fileshareName | string | The name of the Azure File Share |
|
||||||
| storageAccountName | string | Name of your storage account |
|
| storageAccountName | string | Name of your storage account |
|
||||||
| storageAccountKey | string | Key for the 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -1,10 +1,27 @@
|
||||||
package SQL
|
package SQL
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type LogType int64
|
type LogType int64
|
||||||
|
|
||||||
const(
|
const (
|
||||||
LogInfo LogType = 1
|
LogInfo LogType = 1
|
||||||
LogWarning = 2
|
LogWarning = 2
|
||||||
LogError = 3
|
LogError = 3
|
||||||
LogFatal = 4
|
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
144
SQL/MSSQLConnector.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ func GetMariaDBInstance(sqlConfig Tools.SQLConfig) MariaDBConnector {
|
||||||
return mariadb
|
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)
|
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'EventLog';", mariadb.Database)
|
||||||
if !rows.Next() {
|
if !rows.Next() {
|
||||||
return false
|
return false
|
||||||
|
|
@ -39,7 +39,7 @@ func checkIfEventLogTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
|
||||||
return true
|
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)
|
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'Backups';", mariadb.Database)
|
||||||
if !rows.Next() {
|
if !rows.Next() {
|
||||||
return false
|
return false
|
||||||
|
|
@ -47,7 +47,7 @@ func checkIfBackupTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
|
||||||
return true
|
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)
|
rows, _ := db.Query("SELECT * FROM `"+mariadb.Database+"`.Backups WHERE Hostname = ? AND BackupName = ?;", hostname, backupName)
|
||||||
if !rows.Next() {
|
if !rows.Next() {
|
||||||
return false
|
return false
|
||||||
|
|
@ -72,14 +72,14 @@ func (mariadb MariaDBConnector) createDefaultTables() {
|
||||||
|
|
||||||
db := createMariaDBConnection(mariadb)
|
db := createMariaDBConnection(mariadb)
|
||||||
|
|
||||||
if !checkIfBackupTableExist(db, mariadb) {
|
if !mariadb.checkIfBackupTableExist(db) {
|
||||||
_, err := db.Exec(backupSQL)
|
_, err := db.Exec(backupSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !checkIfEventLogTableExist(db, mariadb) {
|
if !mariadb.checkIfEventLogTableExist(db) {
|
||||||
_, err := db.Exec(eventLogSQL)
|
_, err := db.Exec(eventLogSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
|
|
@ -108,7 +108,7 @@ func (mariadb MariaDBConnector) newBackupEntry(backupName string, lastBackup tim
|
||||||
|
|
||||||
hostname, _ := os.Hostname()
|
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)
|
_, 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 {
|
if err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,24 @@
|
||||||
package SQL
|
package SQL
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type RemoteStorageType int64
|
type RemoteStorageType int64
|
||||||
|
|
||||||
const(
|
const (
|
||||||
REMOTE_AZURE_FILE = 1
|
REMOTE_AZURE_FILE = 1
|
||||||
REMOTE_AZURE_BLOB = 2
|
REMOTE_AZURE_BLOB = 2
|
||||||
REMOTE_NONE = 3
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ func GetSQLInstance() SQLService {
|
||||||
{
|
{
|
||||||
return GetMariaDBInstance(sqlConfig)
|
return GetMariaDBInstance(sqlConfig)
|
||||||
}
|
}
|
||||||
|
case "mysql":
|
||||||
|
{
|
||||||
|
return GetMariaDBInstance(sqlConfig)
|
||||||
|
}
|
||||||
|
case "mssql":
|
||||||
|
{
|
||||||
|
return GetMSSQLInstance(sqlConfig)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,24 @@
|
||||||
package SQL
|
package SQL
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type SQLStage int64
|
type SQLStage int64
|
||||||
|
|
||||||
const(
|
const (
|
||||||
SQLStage_Compress = 1
|
SQLStage_Compress = 1
|
||||||
SQLStage_Upload = 2
|
SQLStage_Upload = 2
|
||||||
SQLStage_DeleteTmp = 3
|
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
3
go.mod
|
|
@ -16,7 +16,9 @@ require (
|
||||||
github.com/Azure/azure-pipeline-go v0.2.1 // indirect
|
github.com/Azure/azure-pipeline-go v0.2.1 // indirect
|
||||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // 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/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-colorable v0.1.8 // indirect
|
||||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 // indirect
|
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // 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/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // 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/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||||
golang.org/x/text v0.3.0 // indirect
|
golang.org/x/text v0.3.0 // indirect
|
||||||
|
|
|
||||||
6
go.sum
6
go.sum
|
|
@ -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/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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
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 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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=
|
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 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
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-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 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
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=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|
|
||||||
Reference in a new issue