Skip to content

Commit

Permalink
refactor: use pure go sqlite driver (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
MaineK00n authored May 10, 2023
1 parent 4867240 commit 81d7f4f
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 103 deletions.
17 changes: 7 additions & 10 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ jobs:
go-version-file: go.mod
-
name: Run GoReleaser
run: |
docker run --rm \
-e CGO_ENABLED=1 \
-e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/go/src/github.com/vulsio/go-cti \
-w /go/src/github.com/vulsio/go-cti \
ghcr.io/goreleaser/goreleaser-cross:v1.20 \
release --clean
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35 changes: 2 additions & 33 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,15 @@ release:
owner: vulsio
name: go-cti
env:
- GO111MODULE=on
- CGO_ENABLED=1
- CGO_ENABLED=0
builds:
- id: linux-amd64
- id: go-cti
goos:
- linux
goarch:
- amd64
env:
- CC=x86_64-linux-gnu-gcc
main: .
ldflags: -s -w -X github.com/vulsio/go-cti/config.Version={{.Version}} -X github.com/vulsio/go-cti/config.Revision={{.Commit}}
binary: go-cti
- id: linux-arm64
goos:
- linux
goarch:
- arm64
env:
- CC=aarch64-linux-gnu-gcc
main: .
ldflags: -s -w -X github.com/vulsio/go-cti/config.Version={{.Version}} -X github.com/vulsio/go-cti/config.Revision={{.Commit}}
binary: go-cti
- id: windows-amd64
goos:
- windows
goarch:
- amd64
env:
- CC=x86_64-w64-mingw32-gcc
main: .
ldflags: -s -w -X github.com/vulsio/go-cti/config.Version={{.Version}} -X github.com/vulsio/go-cti/config.Revision={{.Commit}}
binary: go-cti
- id: windows-arm64
goos:
- windows
goarch:
- arm64
env:
- CC=/llvm-mingw/bin/aarch64-w64-mingw32-gcc
main: .
ldflags: -s -w -X github.com/vulsio/go-cti/config.Version={{.Version}} -X github.com/vulsio/go-cti/config.Revision={{.Commit}}
binary: go-cti
Expand Down
6 changes: 3 additions & 3 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ REVISION := $(shell git rev-parse --short HEAD)
BUILDTIME := $(shell date "+%Y%m%d_%H%M%S")
LDFLAGS := -X 'github.com/vulsio/go-cti/config.Version=$(VERSION)' \
-X 'github.com/vulsio/go-cti/config.Revision=$(REVISION)'
GO := GO111MODULE=on go
GO := CGO_ENABLED=0 go

all: build test

Expand All @@ -40,11 +40,11 @@ install: main.go
$(GO) install -ldflags "$(LDFLAGS)"

lint:
$(GO) install github.com/mgechev/revive@latest
go install github.com/mgechev/revive@latest
revive -config ./.revive.toml -formatter plain $(PKGS)

golangci:
$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run

vet:
Expand Down
6 changes: 3 additions & 3 deletions commands/fetch-cti.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ func fetchMitreCti(_ *cobra.Command, _ []string) (err error) {
return xerrors.Errorf("Failed to SetLogger. err: %w", err)
}

driver, locked, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{})
driver, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{})
if err != nil {
if locked {
return xerrors.Errorf("Failed to initialize DB. Close DB connection before fetching. err: %w", err)
if xerrors.Is(err, db.ErrDBLocked) {
return xerrors.Errorf("Failed to open DB. Close DB connection before fetching. err: %w", err)
}
return xerrors.Errorf("Failed to open DB. err: %w", err)
}
Expand Down
13 changes: 4 additions & 9 deletions commands/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var searchCmd = &cobra.Command{
Use: "search",
Short: "Search the data of mitre/cti form DB",
Long: `Search the data of mitrc/cti form DB`,
Args: func(cmd *cobra.Command, args []string) error {
Args: func(_ *cobra.Command, args []string) error {
if len(args) < 2 {
fmt.Println("[usage] $ go-cti search (cti|cve|attacker) $id1(, $id2...)")
return xerrors.New("Failed to search. err: argument is missing")
Expand All @@ -41,15 +41,10 @@ func searchCti(_ *cobra.Command, args []string) error {
return xerrors.Errorf("Failed to SetLogger. err: %w", err)
}

driver, locked, err := db.NewDB(
viper.GetString("dbtype"),
viper.GetString("dbpath"),
viper.GetBool("debug-sql"),
db.Option{},
)
driver, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{})
if err != nil {
if locked {
return xerrors.Errorf("Failed to initialize DB. Close DB connection before fetching. err: %w", err)
if xerrors.Is(err, db.ErrDBLocked) {
return xerrors.Errorf("Failed to open DB. Close DB connection before fetching. err: %w", err)
}
return xerrors.Errorf("Failed to open DB. err: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ func executeServer(_ *cobra.Command, _ []string) (err error) {
return xerrors.Errorf("Failed to SetLogger. err: %w", err)
}

driver, locked, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{})
driver, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{})
if err != nil {
if locked {
return xerrors.Errorf("Failed to initialize DB. Close DB connection before fetching. err: %w", err)
if xerrors.Is(err, db.ErrDBLocked) {
return xerrors.Errorf("Failed to open DB. Close DB connection before fetching. err: %w", err)
}
return xerrors.Errorf("Failed to open DB. err: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion commands/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var versionCmd = &cobra.Command{
Use: "version",
Short: "Show version",
Long: `Show version`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
fmt.Printf("go-cti %s %s\n", config.Version, config.Revision)
},
}
21 changes: 9 additions & 12 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// DB :
type DB interface {
Name() string
OpenDB(dbType, dbPath string, debugSQL bool, option Option) (bool, error)
OpenDB(dbType, dbPath string, debugSQL bool, option Option) error
MigrateDB() error
CloseDB() error

Expand All @@ -34,30 +34,27 @@ type Option struct {
}

// NewDB :
func NewDB(dbType string, dbPath string, debugSQL bool, option Option) (driver DB, locked bool, err error) {
func NewDB(dbType string, dbPath string, debugSQL bool, option Option) (driver DB, err error) {
if driver, err = newDB(dbType); err != nil {
return driver, false, xerrors.Errorf("Failed to new db. err: %w", err)
return driver, xerrors.Errorf("Failed to new db. err: %w", err)
}

if locked, err := driver.OpenDB(dbType, dbPath, debugSQL, option); err != nil {
if locked {
return nil, true, err
}
return nil, false, err
if err := driver.OpenDB(dbType, dbPath, debugSQL, option); err != nil {
return nil, xerrors.Errorf("Failed to open db. err: %w", err)
}

isV1, err := driver.IsGoCTIModelV1()
if err != nil {
return nil, false, xerrors.Errorf("Failed to IsGoCTIModelV1. err: %w", err)
return nil, xerrors.Errorf("Failed to IsGoCTIModelV1. err: %w", err)
}
if isV1 {
return nil, false, xerrors.New("Failed to NewDB. Since SchemaVersion is incompatible, delete Database and fetch again.")
return nil, xerrors.New("Failed to NewDB. Since SchemaVersion is incompatible, delete Database and fetch again.")
}

if err := driver.MigrateDB(); err != nil {
return driver, false, xerrors.Errorf("Failed to migrate db. err: %w", err)
return driver, xerrors.Errorf("Failed to migrate db. err: %w", err)
}
return driver, false, nil
return driver, nil
}

func newDB(dbType string) (DB, error) {
Expand Down
94 changes: 74 additions & 20 deletions db/rdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ package db

import (
"database/sql"
"encoding/json"
"errors"
"log"
"os"
"time"

"github.com/cheggaaa/pb/v3"
"github.com/glebarez/sqlite"
"github.com/inconshreveable/log15"
"github.com/mattn/go-sqlite3"
"github.com/spf13/viper"
"golang.org/x/xerrors"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/logger"
Expand All @@ -35,13 +35,29 @@ type RDBDriver struct {
conn *gorm.DB
}

// https://github.com/mattn/go-sqlite3/blob/edc3bb69551dcfff02651f083b21f3366ea2f5ab/error.go#L18-L66
type errNo int

type sqliteError struct {
Code errNo /* The error code returned by SQLite */
}

// result codes from http://www.sqlite.org/c3ref/c_abort.html
var (
errBusy = errNo(5) /* The database file is locked */
errLocked = errNo(6) /* A table in the database is locked */
)

// ErrDBLocked :
var ErrDBLocked = xerrors.New("database is locked")

// Name return db name
func (r *RDBDriver) Name() string {
return r.name
}

// OpenDB opens Database
func (r *RDBDriver) OpenDB(dbType, dbPath string, debugSQL bool, _ Option) (locked bool, err error) {
func (r *RDBDriver) OpenDB(dbType, dbPath string, debugSQL bool, _ Option) (err error) {
gormConfig := gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
Logger: logger.New(
Expand All @@ -66,28 +82,40 @@ func (r *RDBDriver) OpenDB(dbType, dbPath string, debugSQL bool, _ Option) (lock
switch r.name {
case dialectSqlite3:
r.conn, err = gorm.Open(sqlite.Open(dbPath), &gormConfig)
case dialectMysql:
r.conn, err = gorm.Open(mysql.Open(dbPath), &gormConfig)
case dialectPostgreSQL:
r.conn, err = gorm.Open(postgres.Open(dbPath), &gormConfig)
default:
err = xerrors.Errorf("Not Supported DB dialects. r.name: %s", r.name)
}
if err != nil {
parsedErr, marshalErr := json.Marshal(err)
if marshalErr != nil {
return xerrors.Errorf("Failed to marshal err. err: %w", marshalErr)
}

if err != nil {
if r.name == dialectSqlite3 {
switch err.(sqlite3.Error).Code {
case sqlite3.ErrLocked, sqlite3.ErrBusy:
return true, xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, err)
var errMsg sqliteError
if unmarshalErr := json.Unmarshal(parsedErr, &errMsg); unmarshalErr != nil {
return xerrors.Errorf("Failed to unmarshal. err: %w", unmarshalErr)
}

switch errMsg.Code {
case errBusy, errLocked:
return xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, ErrDBLocked)
default:
return xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, err)
}
}
return false, xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, err)
}

if r.name == dialectSqlite3 {
r.conn.Exec("PRAGMA foreign_keys = ON")
case dialectMysql:
r.conn, err = gorm.Open(mysql.Open(dbPath), &gormConfig)
if err != nil {
return xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, err)
}
case dialectPostgreSQL:
r.conn, err = gorm.Open(postgres.Open(dbPath), &gormConfig)
if err != nil {
return xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dbType, dbPath, err)
}
default:
return xerrors.Errorf("Not Supported DB dialects. r.name: %s", r.name)
}
return false, nil
return nil
}

// CloseDB close Database
Expand Down Expand Up @@ -155,7 +183,33 @@ func (r *RDBDriver) MigrateDB() error {
&models.SoftwarePlatform{},
&models.GroupUsed{},
); err != nil {
return xerrors.Errorf("Failed to migrate. err: %w", err)
switch r.name {
case dialectSqlite3:
if r.name == dialectSqlite3 {
parsedErr, marshalErr := json.Marshal(err)
if marshalErr != nil {
return xerrors.Errorf("Failed to marshal err. err: %w", marshalErr)
}

var errMsg sqliteError
if unmarshalErr := json.Unmarshal(parsedErr, &errMsg); unmarshalErr != nil {
return xerrors.Errorf("Failed to unmarshal. err: %w", unmarshalErr)
}

switch errMsg.Code {
case errBusy, errLocked:
return xerrors.Errorf("Failed to migrate. err: %w", ErrDBLocked)
default:
return xerrors.Errorf("Failed to migrate. err: %w", err)
}
}
case dialectMysql, dialectPostgreSQL:
if err != nil {
return xerrors.Errorf("Failed to migrate. err: %w", err)
}
default:
return xerrors.Errorf("Not Supported DB dialects. r.name: %s", r.name)
}
}

return nil
Expand Down
7 changes: 5 additions & 2 deletions db/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ func (r *RedisDriver) Name() string {
}

// OpenDB opens Database
func (r *RedisDriver) OpenDB(_, dbPath string, _ bool, option Option) (bool, error) {
return false, r.connectRedis(dbPath, option)
func (r *RedisDriver) OpenDB(_, dbPath string, _ bool, option Option) error {
if err := r.connectRedis(dbPath, option); err != nil {
return xerrors.Errorf("Failed to open DB. dbtype: %s, dbpath: %s, err: %w", dialectRedis, dbPath, err)
}
return nil
}

func (r *RedisDriver) connectRedis(dbPath string, option Option) error {
Expand Down
Loading

0 comments on commit 81d7f4f

Please sign in to comment.