Skip to content

Commit

Permalink
Database interface & auditing feature (thrasher-corp#332)
Browse files Browse the repository at this point in the history
* added audit manager

* Basic database DOA setup

* Added base config file

* added sqlite support and creation of schema

* added basic tests and config entry

* corrected issues of database is disabled

* fixed path for test

* WIP

* Added tests fixed config checking

* reverted files back to upstream

* reverted go.mod files

* no more test test test

* removed local testing details for psql

* hello

* added comments

* increased ping to 30 seconds

* renamed database table and added additional condition around test

* removed database test details

* goimport ran on all files

* WIP

* first attempt at migration

* fixes for migration system

* Migration system logger interface implemented

* fixes to print functions

* added write pooling pass

* gofmt :D

* formatted imports correctly

* removed old code

* added creation of migration

* gofmt

* :D Hello

* ❌ 🏎️

* maybe one day i will remember to revert go mod files

* checked err return condition correctly

* first changes for PR feedback

* code clean up

* protect Connected with RWmutex & event with mutex

* : D

* we can just pretend like it never happened

* MOved migrations back to source directory and added README

* readme formatting update

* Addd command line override for datadir

* use correct var when creating a migration and confirm folder is created

* Check if database version is newer than latest migration and also you know make migrations work.....

* uses filepath instead of manual path to use correct path seperator

* Add connection message and lower timeout

* Added support for sslmode for psql

* no longer force Close of database instead allow driver to maage

* Added closer func to test output

* sslmode added to example config
  • Loading branch information
xtda authored and thrasher- committed Aug 20, 2019
1 parent b178dd2 commit 0c76789
Show file tree
Hide file tree
Showing 30 changed files with 1,295 additions and 19 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ update_deps:
.PHONY: profile_heap
profile_heap:
go tool pprof -http "localhost:$(GCTPROFILERLISTENPORT)" 'http://localhost:$(GCTLISTENPORT)/debug/pprof/heap'

.PHONY: profile_cpu
profile_cpu:
go tool pprof -http "localhost:$(GCTPROFILERLISTENPORT)" 'http://localhost:$(GCTLISTENPORT)/debug/pprof/profile'
go tool pprof -http "localhost:$(GCTPROFILERLISTENPORT)" 'http://localhost:$(GCTLISTENPORT)/debug/pprof/profile'

db_migrate:
go run ./cmd/dbmigrate
168 changes: 168 additions & 0 deletions cmd/dbmigrate/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package main

import (
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"time"

"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/database"
db "github.com/thrasher-corp/gocryptotrader/database/drivers/postgres"
dbsqlite3 "github.com/thrasher-corp/gocryptotrader/database/drivers/sqlite"
mg "github.com/thrasher-corp/gocryptotrader/database/migration"
)

var (
dbConn *database.Database
configFile string
defaultDataDir string
createMigration string
migrationDir string
)

var defaultMigration = []byte(`-- up
-- down
`)

func openDbConnection(driver string) (err error) {
if driver == "postgres" {
dbConn, err = db.Connect()
if err != nil {
return fmt.Errorf("database failed to connect: %v Some features that utilise a database will be unavailable", err)
}

dbConn.SQL.SetMaxOpenConns(2)
dbConn.SQL.SetMaxIdleConns(1)
dbConn.SQL.SetConnMaxLifetime(time.Hour)

} else if driver == "sqlite" {
dbConn, err = dbsqlite3.Connect()

if err != nil {
return fmt.Errorf("database failed to connect: %v Some features that utilise a database will be unavailable", err)
}
}
return nil
}

type tmpLogger struct{}

// Printf implantation of migration Logger interface
// Passes directly to Printf from fmt package
func (t tmpLogger) Printf(format string, v ...interface{}) {
fmt.Printf(format, v...)
}

// Println implantation of migration Logger interface
// Passes directly to Println from fmt package
func (t tmpLogger) Println(v ...interface{}) {
fmt.Println(v...)
}

// Errorf implantation of migration Logger interface
// Passes directly to Printf from fmt package
func (t tmpLogger) Errorf(format string, v ...interface{}) {
fmt.Printf(format, v...)
}

func main() {
fmt.Println("GoCryptoTrader database migration tool")
fmt.Println(core.Copyright)
fmt.Println()

defaultPath, err := config.GetFilePath("")
if err != nil {
fmt.Println(err)
os.Exit(1)
}

flag.StringVar(&configFile, "config", defaultPath, "config file to load")
flag.StringVar(&defaultDataDir, "datadir", common.GetDefaultDataDir(runtime.GOOS), "default data directory for GoCryptoTrader files")
flag.StringVar(&createMigration, "create", "", "create a new empty migration file")
flag.StringVar(&migrationDir, "migrationdir", mg.MigrationDir, "override migration folder")

flag.Parse()

if createMigration != "" {
err = newMigrationFile(createMigration)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("Migration created successfully")
os.Exit(0)
}

tempLogger := tmpLogger{}

temp := mg.Migrator{
Log: tempLogger,
}

err = temp.LoadMigrations()
if err != nil {
fmt.Println(err)
os.Exit(0)
}

conf := config.GetConfig()

err = conf.LoadConfig(configFile)
if err != nil {
fmt.Println(err)
os.Exit(0)
}

err = openDbConnection(conf.Database.Driver)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

fmt.Printf("Connected to: %s\n", conf.Database.Host)

temp.Conn = dbConn

err = temp.RunMigration()

if err != nil {
fmt.Println(err)
os.Exit(1)
}

if dbConn.SQL != nil {
err = dbConn.SQL.Close()
if err != nil {
fmt.Println(err)
}
}
}

func newMigrationFile(filename string) error {
curTime := strconv.FormatInt(time.Now().Unix(), 10)
path := filepath.Join(migrationDir, curTime+"_"+filename+".sql")
err := common.CreateDir(migrationDir)
if err != nil {
return err
}
fmt.Printf("Creating new empty migration: %v\n", path)
f, err := os.Create(path)

if err != nil {
return err
}

_, err = f.Write(defaultMigration)

if err != nil {
return err
}

return f.Close()
}
10 changes: 5 additions & 5 deletions cmd/documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">


[![Build Status](https://travis-ci.org/thrasher-/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-/gocryptotrader)
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/cmd/documentation)
[![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)


Expand All @@ -22,7 +22,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader

#### This tool allows for the generation of new documentation through templating

From the `gocryptotrader/cmd/documentation/` folder, using the go command: **go run documentation.go** this will auto-generate and regenerate documentation across the **GoCryptoTrader** code base.
From the `gocryptotrader/cmd/documentation/` folder, using the go command: **go run documentation.go** this will auto-generate and regenerate documentation across the **GoCryptoTrader** code base.
>Using the -v command will, ie **go run documentation.go -v** put the tool into verbose mode allowing you to see what is happening with a little more depth.
Be aware, this tool will:
Expand All @@ -36,7 +36,7 @@ Be aware, this tool will:

```json
{
"githubRepo": "https://api.github.com/repos/thrasher-/gocryptotrader", This is your current repo
"githubRepo": "https://api.github.com/repos/thrasher-corp/gocryptotrader", This is your current repo
"exclusionList": { This allows for excluded directories and files
"Files": null,
"Directories": [
Expand All @@ -55,7 +55,7 @@ Be aware, this tool will:
>place a new template **example_file.tmpl** located in the current gocryptotrader/cmd/documentation/ folder; when the documentation tool finishes it will give you the define template associated name e.g. ``Template not found for path ../../cmd/documentation create new template with \{\{define "cmd documentation" -\}\} TEMPLATE HERE \{\{end}}`` so you can replace the below example with ``\{\{define "cmd documentation" -}}``
```
\{\{\define "example_definition_created_by_documentation_tool" -}}
\{\{\define "example_definition_created_by_documentation_tool" -}}
\{\{\template "header" .}}
## Current Features for documentation
Expand Down
10 changes: 5 additions & 5 deletions cmd/documentation/cmd_templates/documentation.tmpl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{{define "cmd documentation" -}}
{{define "cmd documentation" -}}
{{template "header" .}}
## Current Features for {{.Name}}

#### This tool allows for the generation of new documentation through templating

From the `gocryptotrader/cmd/documentation/` folder, using the go command: **go run documentation.go** this will auto-generate and regenerate documentation across the **GoCryptoTrader** code base.
From the `gocryptotrader/cmd/documentation/` folder, using the go command: **go run documentation.go** this will auto-generate and regenerate documentation across the **GoCryptoTrader** code base.
>Using the -v command will, ie **go run documentation.go -v** put the tool into verbose mode allowing you to see what is happening with a little more depth.

Be aware, this tool will:
Expand All @@ -18,7 +18,7 @@ Be aware, this tool will:

```json
{
"githubRepo": "https://api.github.com/repos/thrasher-/gocryptotrader", This is your current repo
"githubRepo": "https://api.github.com/repos/thrasher-corp/gocryptotrader", This is your current repo
"exclusionList": { This allows for excluded directories and files
"Files": null,
"Directories": [
Expand All @@ -37,7 +37,7 @@ Be aware, this tool will:
>place a new template **example_file.tmpl** located in the current gocryptotrader/cmd/documentation/ folder; when the documentation tool finishes it will give you the define template associated name e.g. ``Template not found for path ../../cmd/documentation create new template with \{\{define "cmd documentation" -\}\} TEMPLATE HERE \{\{end}}`` so you can replace the below example with ``\{\{define "cmd documentation" -}}``

```
\{\{\define "example_definition_created_by_documentation_tool" -}}
\{\{\define "example_definition_created_by_documentation_tool" -}}
\{\{\template "header" .}}
## Current Features for {{.Name}}

Expand All @@ -60,4 +60,4 @@ upper := strings.ToUpper(testString)
### Please click GoDocs chevron above to view current GoDoc information for this package
{{template "contributions"}}
{{template "donations"}}
{{end}}
{{end}}
29 changes: 29 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider"
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider/base"
"github.com/thrasher-corp/gocryptotrader/database"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
log "github.com/thrasher-corp/gocryptotrader/logger"
)
Expand Down Expand Up @@ -1293,6 +1294,29 @@ func (c *Config) CheckLoggerConfig() error {
return nil
}

func (c *Config) checkDatabaseConfig() error {
m.Lock()
defer m.Unlock()

if !common.StringDataCompare(database.SupportedDrivers, c.Database.Driver) {
c.Database.Enabled = false
return fmt.Errorf("unsupported database driver %v database disabled", c.Database.Driver)
}

if c.Database.Driver == "sqlite" {
databaseDir := filepath.Join(common.GetDefaultDataDir(runtime.GOOS), "/database")
err := common.CreateDir(databaseDir)
if err != nil {
return err
}
database.Conn.DataPath = databaseDir
}

database.Conn.Config = &c.Database

return nil
}

// CheckNTPConfig checks for missing or incorrectly configured NTPClient and recreates with known safe defaults
func (c *Config) CheckNTPConfig() {
m.Lock()
Expand Down Expand Up @@ -1608,6 +1632,11 @@ func (c *Config) CheckConfig() error {
log.Errorf(log.ConfigMgr, "Failed to configure logger, some logging features unavailable: %s\n", err)
}

err = c.checkDatabaseConfig()
if err != nil {
log.Errorf(log.DatabaseMgr, "Failed to configure database: %v", err)
}

err = c.CheckExchangeConfigValues()
if err != nil {
return fmt.Errorf(ErrCheckingConfigValues, err)
Expand Down
2 changes: 2 additions & 0 deletions config/config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/currency/forexprovider/base"
"github.com/thrasher-corp/gocryptotrader/database"
log "github.com/thrasher-corp/gocryptotrader/logger"
"github.com/thrasher-corp/gocryptotrader/portfolio"
)
Expand All @@ -16,6 +17,7 @@ type Config struct {
Name string `json:"name"`
EncryptConfig int `json:"encryptConfig"`
GlobalHTTPTimeout time.Duration `json:"globalHTTPTimeout"`
Database database.Config `json:"database"`
Logging log.Config `json:"logging"`
ConnectionMonitor ConnectionMonitorConfig `json:"connectionMonitor"`
Profiler ProfilerConfig `json:"profiler"`
Expand Down
12 changes: 12 additions & 0 deletions config_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
"name": "Skynet",
"encryptConfig": 0,
"globalHTTPTimeout": 15000000000,
"database": {
"enabled": false,
"driver": "sqlite",
"connectionDetails": {
"Host": "",
"Port": 0,
"Username": "",
"Password": "",
"Database": "",
"SSLMode": ""
}
},
"logging": {
"enabled": true,
"level": "INFO|WARN|DEBUG|ERROR",
Expand Down
2 changes: 1 addition & 1 deletion currency/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func TestConversionsRatesSystem(t *testing.T) {

err = SuperDuperConversionSystem.Update(nil)
if err == nil {
t.Fatal("Test Failed - Update() error cannnot be nil")
t.Fatal("Test Failed - Update() error cannot be nil")
}

if !SuperDuperConversionSystem.HasData() {
Expand Down
Loading

0 comments on commit 0c76789

Please sign in to comment.