Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • orus-io/go-orusapi
1 result
Show changes
Commits on Source (9)
---
image: golang:1.14
image: golang:1.19
stages:
- test
......
......@@ -3,7 +3,7 @@
linters:
enable:
- misspell
- golint
- revive
- whitespace
- unconvert
- gosec
......@@ -7,10 +7,6 @@
- whitespace
- unconvert
- gosec
linters-settings:
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.5
issues:
exclude:
- SA5008 # duplicate struct tag (staticcheck)
GOLANGCI_LINT_VERSION = v1.30.0
GOLANGCI_LINT_VERSION = v1.53.3
GOLANGCI_LINT_BIN = tools/bin/golangci-lint-$(GOLANGCI_LINT_VERSION)
help: ## Display this help
......
......@@ -11,6 +11,7 @@
type ArrayContains map[string]interface{}
//nolint:revive
func (ac ArrayContains) ToSql() (sql string, args []interface{}, err error) {
if len(ac) == 0 {
// Empty Sql{} evaluates to true.
......
......@@ -31,8 +31,8 @@
return h.sqle.GetContext(h.ctx, obj, sql, args...)
}
// GetByPKey loads a mapped structure
// GetByPKey loads a mapped structure by primary key
func (h *SQLHelper) GetByPKey(obj Mapped, value interface{}) error {
return h.GetBy(obj, obj.PKeyColumn(), value)
}
......@@ -35,9 +35,15 @@
func (h *SQLHelper) GetByPKey(obj Mapped, value interface{}) error {
return h.GetBy(obj, obj.PKeyColumn(), value)
}
// GetBy ...
// GetByPKeyForUpdate loads a mapped structure by primary key and get a lock
// (see https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE)
func (h *SQLHelper) GetByPKeyForUpdate(obj Mapped, value interface{}) error {
return h.GetByForUpdate(obj, obj.PKeyColumn(), value)
}
// GetBy loads a mapped structure by a given column
func (h *SQLHelper) GetBy(obj Mapped, column string, value interface{}) error {
return h.GetWhere(obj, sq.Eq{column: value})
}
......@@ -40,5 +46,11 @@
func (h *SQLHelper) GetBy(obj Mapped, column string, value interface{}) error {
return h.GetWhere(obj, sq.Eq{column: value})
}
// GetByForUpdate loads a mapped structure by a given column and get a lock
// (see https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE)
func (h *SQLHelper) GetByForUpdate(obj Mapped, column string, value interface{}) error {
return h.GetWhereForUpdate(obj, sq.Eq{column: value})
}
// GetWhere loads a mapped structure
......@@ -44,4 +56,5 @@
// GetWhere loads a mapped structure
// ex: GetWhere(account, squirrel.Eq{models.AccountDBNameColumn: "somename"})
func (h *SQLHelper) GetWhere(obj Mapped, pred interface{}, args ...interface{}) error {
query := SQ.
Select(obj.Columns(true)...).
......@@ -51,6 +64,29 @@
return h.Get(obj, query)
}
// DeleteWhere deletes from a table corresponding to a mapped structure using the predicate and args
// ex: DeleteWhere(account, squirrel.Eq{models.AccountDBNameColumn: "somename"})
func (h *SQLHelper) DeleteWhere(obj Mapped, pred interface{}, args ...interface{}) error {
query := SQ.
Delete(obj.Table()).
Where(pred, args...)
_, err := h.Exec(query)
return err
}
// GetWhereForUpdate loads a mapped structure and get a lock
// (see https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE)
func (h *SQLHelper) GetWhereForUpdate(obj Mapped, pred interface{}, args ...interface{}) error {
query := SQ.
Select(obj.Columns(true)...).
From(obj.Table()).
Where(pred, args...).
Suffix("FOR UPDATE")
return h.Get(obj, query)
}
// Select loads a structure list
func (h *SQLHelper) Select(obj interface{}, query sq.Sqlizer) error {
return SelectContext(h.ctx, h.sqle, obj, query, &h.log)
......
......@@ -16,5 +16,14 @@
const dbLockID = 15104
func clearDB(t testing.TB, c *sqlx.Conn, dsn string) {
func getDSN(tb testing.TB) string {
dsn := os.Getenv("TEST_DB_DSN")
if dsn == "" {
tb.Fatal("Please define a TEST_DB_DSN environment variable")
}
return dsn
}
//nolint:revive
func clearDB(ctx context.Context, t testing.TB, c *sqlx.Conn, dsn string) {
// Drop all tables, and reinit
......@@ -20,4 +29,4 @@
// Drop all tables, and reinit
if _, err := c.ExecContext(context.Background(), "DROP SCHEMA IF EXISTS public CASCADE"); err != nil {
if _, err := c.ExecContext(ctx, "DROP SCHEMA IF EXISTS public CASCADE"); err != nil {
t.Fatal(err)
}
......@@ -22,6 +31,6 @@
t.Fatal(err)
}
if _, err := c.ExecContext(context.Background(), "CREATE SCHEMA public"); err != nil {
if _, err := c.ExecContext(ctx, "CREATE SCHEMA public"); err != nil {
t.Fatal(err)
}
}
......@@ -29,6 +38,8 @@
// TestDB is a sqlx.DB wrapper that release a global lock on close
type TestDB struct {
*sqlx.DB
DSN string
ctx context.Context
tb testing.TB
lockConn *sqlx.Conn
}
......@@ -44,7 +55,7 @@
// Clear empty the database
func (db *TestDB) Clear() {
tx, err := db.lockConn.BeginTxx(context.Background(), nil)
tx, err := db.lockConn.BeginTxx(db.ctx, nil)
require.NoError(db.tb, err)
for _, name := range dbtablenames {
if _, err := tx.Exec(
......@@ -70,8 +81,6 @@
require.NoError(db.tb, tx.Commit())
}
// GetTestDB creates a db and returns it. It must be closed within the test.
// If it fails, t.Fatal() is called
func GetTestDB(t testing.TB, sourceDriver source.Driver) *TestDB {
func GetTestDBNoInit(ctx context.Context, tb testing.TB) *TestDB {
var success bool
......@@ -76,7 +85,33 @@
var success bool
dsn := os.Getenv("TEST_DB_DSN")
if dsn == "" {
t.Fatal("Please define a TEST_DB_DSN environment variable")
dsn := getDSN(tb)
db, err := Open(dsn, 0)
require.NoError(tb, err)
defer func() {
if !success {
if err := db.Close(); err != nil {
tb.Log("Error closing db:", err)
}
}
}()
c, err := db.Connx(ctx)
require.NoError(tb, err)
defer func() {
if !success {
if err := c.Close(); err != nil {
tb.Log("Error closing conn:", err)
}
}
}()
if _, err := c.ExecContext(
ctx,
"SELECT pg_advisory_lock($1)", dbLockID,
); err != nil {
tb.Fatal(err)
}
......@@ -81,5 +116,17 @@
}
success = true
return &TestDB{db, dsn, ctx, tb, c}
}
// GetTestDB creates a db and returns it. It must be closed within the test.
// If it fails, t.Fatal() is called
func GetTestDB(ctx context.Context, t testing.TB, sourceDriver source.Driver) *TestDB {
var success bool
dsn := getDSN(t)
db, err := Open(dsn, 0)
if err != nil {
t.Fatal(err)
......@@ -87,9 +134,11 @@
defer func() {
if !success {
if err := db.Close(); err != nil {
t.Log("Error closing db:", err)
if ctx.Err() == nil {
if err := db.Close(); err != nil {
t.Log("Error closing db:", err)
}
}
}
}()
......@@ -92,8 +141,8 @@
}
}
}()
c, err := db.Connx(context.Background())
c, err := db.Connx(ctx)
if err != nil {
t.Fatal(err)
}
......@@ -107,10 +156,10 @@
}()
if _, err := c.ExecContext(
context.Background(),
ctx,
"SELECT pg_advisory_lock($1)", dbLockID,
); err != nil {
t.Fatal(err)
}
if len(dbtablenames) == 0 {
......@@ -111,10 +160,10 @@
"SELECT pg_advisory_lock($1)", dbLockID,
); err != nil {
t.Fatal(err)
}
if len(dbtablenames) == 0 {
clearDB(t, c, dsn)
clearDB(ctx, t, c, dsn)
m, err := NewMigrate(dsn, sourceDriver)
if err != nil {
......@@ -127,6 +176,8 @@
t.Fatal(srcErr, dbErr)
}
}
testDB := TestDB{db, dsn, ctx, t, c}
if len(dbtablenames) == 0 {
if err := db.Select(&dbtablenames,
"SELECT tablename "+
......@@ -136,30 +187,7 @@
t.Fatal(err)
}
} else {
for _, name := range dbtablenames {
if _, err := db.Exec(
"ALTER TABLE " + name + " DISABLE TRIGGER ALL",
); err != nil {
t.Fatal(err)
return nil
}
}
for _, name := range dbtablenames {
if _, err := db.Exec(
"DELETE FROM " + name, //nolint:gosec
); err != nil {
t.Fatal(err)
return nil
}
}
for _, name := range dbtablenames {
if _, err := db.Exec(
"ALTER TABLE " + name + " ENABLE TRIGGER ALL",
); err != nil {
t.Fatal(err)
return nil
}
}
testDB.ClearDB()
}
success = true
......@@ -163,8 +191,40 @@
}
success = true
return &TestDB{db, t, c}
return &testDB
}
func (db *TestDB) DisableConstraints() {
for _, name := range dbtablenames {
if _, err := db.Exec(
"ALTER TABLE " + name + " DISABLE TRIGGER ALL",
); err != nil {
db.tb.Fatal(err)
}
}
}
func (db *TestDB) EnableConstraints() {
for _, name := range dbtablenames {
if _, err := db.Exec(
"ALTER TABLE " + name + " ENABLE TRIGGER ALL",
); err != nil {
db.tb.Fatal(err)
}
}
}
func (db *TestDB) ClearDB() {
db.DisableConstraints()
defer db.EnableConstraints()
for _, name := range dbtablenames {
if _, err := db.Exec(
"DELETE FROM " + name, //nolint:gosec
); err != nil {
db.tb.Fatal(err)
}
}
}
// Close the lock connection, then the database
func (db *TestDB) Close() {
......@@ -167,8 +227,11 @@
}
// Close the lock connection, then the database
func (db *TestDB) Close() {
if err := db.lockConn.Close(); err != nil {
db.tb.Error("lockConn.Close() failed", err)
if db.lockConn != nil {
if err := db.lockConn.Close(); err != nil {
db.tb.Error("lockConn.Close() failed", err)
}
db.lockConn = nil
}
......@@ -173,6 +236,9 @@
}
if err := db.DB.Close(); err != nil {
db.tb.Error("db.Close() failed", err)
if db.DB != nil {
if err := db.DB.Close(); err != nil {
db.tb.Error("db.Close() failed", err)
}
db.DB = nil
}
}
module orus.io/orus-io/go-orusapi
go 1.14
go 1.19
require (
github.com/Masterminds/squirrel v1.4.0
......@@ -9,6 +9,7 @@
github.com/go-openapi/runtime v0.19.21
github.com/go-openapi/swag v0.19.9
github.com/golang-migrate/migrate/v4 v4.12.2
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59
github.com/jmoiron/sqlx v1.2.1-0.20200615141059-0794cb1f47ee
github.com/json-iterator/go v1.1.10
github.com/justinas/alice v1.2.0
......@@ -17,5 +18,4 @@
github.com/prometheus/client_golang v1.8.0
github.com/rs/zerolog v1.19.0
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/net v0.0.0-20200707034311-ab3426394381
......@@ -21,2 +21,3 @@
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/term v0.10.0
)
......@@ -22,1 +23,29 @@
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/lib/pq v1.3.0 // indirect
github.com/mailru/easyjson v0.7.1 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.14.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/rs/xid v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
)
This diff is collapsed.
......@@ -4,7 +4,7 @@
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"os"
"runtime/debug"
"strings"
......@@ -383,7 +383,7 @@
var msg = []byte(`{"level": "info", "foo": "bar", "message": "HELLO", "time": "1990-01-01"}`)
w := ConsoleWriter{Out: ioutil.Discard, NoColor: false}
w := ConsoleWriter{Out: io.Discard, NoColor: false}
for i := 0; i < b.N; i++ {
_, _ = w.Write(msg)
......
......@@ -6,7 +6,7 @@
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
)
// NewLoggingOptions creates a LoggingOptions
......@@ -44,6 +44,7 @@
logFinalOutput io.Writer `no-flag:"t"`
logOutput io.Writer `no-flag:"t"`
wrappedOutput io.Writer `no-flag:"t"`
logWrappers []func(io.Writer) io.Writer `no-flag:"t"`
log *zerolog.Logger `no-flag:"t"`
}
......@@ -53,8 +54,12 @@
return *o.log
}
func (o *LoggingOptions) Output() io.Writer {
return o.wrappedOutput
}
func (o *LoggingOptions) resetOutput() {
out := o.logOutput
for _, wrapper := range o.logWrappers {
out = wrapper(out)
}
......@@ -56,8 +61,9 @@
func (o *LoggingOptions) resetOutput() {
out := o.logOutput
for _, wrapper := range o.logWrappers {
out = wrapper(out)
}
o.wrappedOutput = out
*o.log = o.log.Output(out)
}
......@@ -85,7 +91,7 @@
o.Format = func(format string) error {
if format == "auto" {
if outputFile, hasFd := o.logFinalOutput.(interface{ Fd() uintptr }); hasFd && terminal.IsTerminal(int(outputFile.Fd())) {
if outputFile, hasFd := o.logFinalOutput.(interface{ Fd() uintptr }); hasFd && term.IsTerminal(int(outputFile.Fd())) {
format = "pretty"
} else {
format = "json"
......@@ -112,7 +118,7 @@
// default after some potential --verbose that would be ignored
return nil
}
if outputFile, hasFd := o.logFinalOutput.(interface{ Fd() uintptr }); hasFd && terminal.IsTerminal(int(outputFile.Fd())) {
if outputFile, hasFd := o.logFinalOutput.(interface{ Fd() uintptr }); hasFd && term.IsTerminal(int(outputFile.Fd())) {
value = "info"
} else {
value = "warn"
......
......@@ -8,7 +8,6 @@
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
......@@ -267,7 +266,7 @@
if s.TLSCACertificate != "" {
// include specified CA certificate
caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate))
caCert, caCertErr := os.ReadFile(string(s.TLSCACertificate))
if caCertErr != nil {
return caCertErr
}
......@@ -299,7 +298,7 @@
}
// must have at least one certificate or panics
httpsServer.TLSConfig.BuildNameToCertificate()
// httpsServer.TLSConfig.BuildNameToCertificate()
//configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
......