mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-25 06:36:03 +03:00
Merge pull request #3 from Neur0toxine/master
[enhancement] resource embedding & better migrations
This commit is contained in:
commit
caf46751fe
12
.travis.yml
Normal file
12
.travis.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
language: go
|
||||||
|
env:
|
||||||
|
- GO111MODULE=on
|
||||||
|
go:
|
||||||
|
- '1.12'
|
||||||
|
- '1.13'
|
||||||
|
before_install:
|
||||||
|
- go mod tidy
|
||||||
|
script:
|
||||||
|
- go test ./... -v -cpu 2 -race -cover -coverprofile=coverage.txt -covermode=atomic
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
86
README.md
86
README.md
@ -1,3 +1,87 @@
|
|||||||
## MG Transport Library
|
## MG Transport Library
|
||||||
|
[![Build Status](https://travis-ci.org/retailcrm/mg-transport-core.svg?branch=master)](https://travis-ci.org/retailcrm/mg-transport-core)
|
||||||
|
[![codecov](https://codecov.io/gh/retailcrm/mg-transport-core/branch/master/graph/badge.svg)](https://codecov.io/gh/retailcrm/mg-transport-core)
|
||||||
|
This library provides different functions like error-reporting, logging, localization, etc. in order to make it easier to create transports.
|
||||||
|
Usage:
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
This library provides different functions like error-reporting, logging, localization, etc. in order to make it easier to create transports
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
|
"github.com/retailcrm/mg-transport-core/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := core.New()
|
||||||
|
app.Config = core.NewConfig("config.yml")
|
||||||
|
app.DefaultError = "unknown_error"
|
||||||
|
app.TranslationsPath = "./translations"
|
||||||
|
|
||||||
|
app.ConfigureRouter(func(engine *gin.Engine) {
|
||||||
|
engine.Static("/static", "./static")
|
||||||
|
engine.HTMLRender = app.CreateRenderer(
|
||||||
|
func(renderer *core.Renderer) {
|
||||||
|
// insert templates here. Example:
|
||||||
|
r.Push("home", "templates/layout.html", "templates/home.html")
|
||||||
|
},
|
||||||
|
template.FuncMap{},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := app.Prepare().Run(); err != nil {
|
||||||
|
fmt.Printf("Fatal error: %s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resource embedding
|
||||||
|
[packr](https://github.com/gobuffalo/packr/tree/master/v2) can be used to provide resource embedding. In order to use packr you must follow
|
||||||
|
[this instruction](https://github.com/gobuffalo/packr/tree/master/v2#library-installation), and provide boxes with templates,
|
||||||
|
translations and assets to library. Example:
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
|
"github.com/retailcrm/mg-transport-core/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
static := packr.New("assets", "./static")
|
||||||
|
templates := packr.New("templates", "./templates")
|
||||||
|
translations := packr.New("translations", "./translate")
|
||||||
|
|
||||||
|
app := core.New()
|
||||||
|
app.Config = core.NewConfig("config.yml")
|
||||||
|
app.DefaultError = "unknown_error"
|
||||||
|
app.TranslationsBox = translations
|
||||||
|
|
||||||
|
app.ConfigureRouter(func(engine *gin.Engine) {
|
||||||
|
engine.StaticFS("/static", static)
|
||||||
|
engine.HTMLRender = app.CreateRendererFS(
|
||||||
|
templates,
|
||||||
|
func(renderer *core.Renderer) {
|
||||||
|
// insert templates here. Example:
|
||||||
|
r.Push("home", "layout.html", "home.html")
|
||||||
|
},
|
||||||
|
template.FuncMap{},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := app.Prepare().Run(); err != nil {
|
||||||
|
fmt.Printf("Fatal error: %s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -19,13 +19,11 @@ var (
|
|||||||
slashRegex = regexp.MustCompile(`/+$`)
|
slashRegex = regexp.MustCompile(`/+$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// ConfigInterface settings data structure
|
// ConfigInterface settings data structure
|
||||||
type ConfigInterface interface {
|
type ConfigInterface interface {
|
||||||
GetVersion() string
|
GetVersion() string
|
||||||
GetSentryDSN() string
|
GetSentryDSN() string
|
||||||
GetLogLevel() logging.Level
|
GetLogLevel() logging.Level
|
||||||
GetDebug() bool
|
|
||||||
GetHTTPConfig() HTTPServerConfig
|
GetHTTPConfig() HTTPServerConfig
|
||||||
GetDBConfig() DatabaseConfig
|
GetDBConfig() DatabaseConfig
|
||||||
GetAWSConfig() ConfigAWS
|
GetAWSConfig() ConfigAWS
|
||||||
@ -73,12 +71,12 @@ type ConfigAWS struct {
|
|||||||
|
|
||||||
// DatabaseConfig struct
|
// DatabaseConfig struct
|
||||||
type DatabaseConfig struct {
|
type DatabaseConfig struct {
|
||||||
Connection string `yaml:"connection"`
|
Connection interface{} `yaml:"connection"`
|
||||||
Logging bool `yaml:"logging"`
|
Logging bool `yaml:"logging"`
|
||||||
TablePrefix string `yaml:"table_prefix"`
|
TablePrefix string `yaml:"table_prefix"`
|
||||||
MaxOpenConnections int `yaml:"max_open_connections"`
|
MaxOpenConnections int `yaml:"max_open_connections"`
|
||||||
MaxIdleConnections int `yaml:"max_idle_connections"`
|
MaxIdleConnections int `yaml:"max_idle_connections"`
|
||||||
ConnectionLifetime int `yaml:"connection_lifetime"`
|
ConnectionLifetime int `yaml:"connection_lifetime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPServerConfig struct
|
// HTTPServerConfig struct
|
||||||
@ -145,8 +143,8 @@ func (c Config) GetTransportInfo() InfoInterface {
|
|||||||
return c.TransportInfo
|
return c.TransportInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDebug debug flag
|
// IsDebug debug flag
|
||||||
func (c Config) GetDebug() bool {
|
func (c Config) IsDebug() bool {
|
||||||
return c.Debug
|
return c.Debug
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,11 +168,6 @@ func (c Config) GetUpdateInterval() int {
|
|||||||
return c.UpdateInterval
|
return c.UpdateInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDebug debug state
|
|
||||||
func (c Config) IsDebug() bool {
|
|
||||||
return c.Debug
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName transport name
|
// GetName transport name
|
||||||
func (t Info) GetName() string {
|
func (t Info) GetName() string {
|
||||||
return t.Name
|
return t.Name
|
||||||
|
119
core/config_test.go
Normal file
119
core/config_test.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/op/go-logging"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testConfigFile = path.Join(os.TempDir(), "config_test.yml")
|
||||||
|
|
||||||
|
type ConfigTest struct {
|
||||||
|
suite.Suite
|
||||||
|
config *Config
|
||||||
|
data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) SetupTest() {
|
||||||
|
c.data = []byte(`
|
||||||
|
version: 3.2.1
|
||||||
|
|
||||||
|
database:
|
||||||
|
connection: postgres://user:password@host:5432/dbname?sslmode=disable
|
||||||
|
|
||||||
|
http_server:
|
||||||
|
host: example.com
|
||||||
|
listen: :3001
|
||||||
|
|
||||||
|
transport_info:
|
||||||
|
name: Transport
|
||||||
|
code: mg-transport
|
||||||
|
logo_path: /static/logo.svg
|
||||||
|
|
||||||
|
sentry_dsn: dsn string
|
||||||
|
log_level: 5
|
||||||
|
debug: true
|
||||||
|
update_interval: 24
|
||||||
|
|
||||||
|
config_aws:
|
||||||
|
access_key_id: key
|
||||||
|
secret_access_key: secret
|
||||||
|
region: region
|
||||||
|
bucket: bucket
|
||||||
|
folder_name: folder
|
||||||
|
content_type: image/jpeg`)
|
||||||
|
err := ioutil.WriteFile(testConfigFile, c.data, os.ModePerm)
|
||||||
|
require.Nil(c.T(), err)
|
||||||
|
|
||||||
|
c.config = NewConfig(testConfigFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetConfigData() {
|
||||||
|
assert.Equal(c.T(), c.data, c.config.GetConfigData(testConfigFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetVersion() {
|
||||||
|
assert.Equal(c.T(), "3.2.1", c.config.GetVersion())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetDBConfig() {
|
||||||
|
assert.Equal(c.T(), "postgres://user:password@host:5432/dbname?sslmode=disable", c.config.GetDBConfig().Connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetHttpServer() {
|
||||||
|
assert.Equal(c.T(), "example.com", c.config.GetHTTPConfig().Host)
|
||||||
|
assert.Equal(c.T(), ":3001", c.config.GetHTTPConfig().Listen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetTransportInfo() {
|
||||||
|
assert.Equal(c.T(), "Transport", c.config.GetTransportInfo().GetName())
|
||||||
|
assert.Equal(c.T(), "mg-transport", c.config.GetTransportInfo().GetCode())
|
||||||
|
assert.Equal(c.T(), "/static/logo.svg", c.config.GetTransportInfo().GetLogoPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetSentryDSN() {
|
||||||
|
assert.Equal(c.T(), "dsn string", c.config.GetSentryDSN())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetLogLevel() {
|
||||||
|
assert.Equal(c.T(), logging.Level(5), c.config.GetLogLevel())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_IsDebug() {
|
||||||
|
assert.Equal(c.T(), true, c.config.IsDebug())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetUpdateInterval() {
|
||||||
|
assert.Equal(c.T(), 24, c.config.GetUpdateInterval())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) Test_GetConfigAWS() {
|
||||||
|
assert.Equal(c.T(), "key", c.config.GetAWSConfig().AccessKeyID)
|
||||||
|
assert.Equal(c.T(), "secret", c.config.GetAWSConfig().SecretAccessKey)
|
||||||
|
assert.Equal(c.T(), "region", c.config.GetAWSConfig().Region)
|
||||||
|
assert.Equal(c.T(), "bucket", c.config.GetAWSConfig().Bucket)
|
||||||
|
assert.Equal(c.T(), "folder", c.config.GetAWSConfig().FolderName)
|
||||||
|
assert.Equal(c.T(), "image/jpeg", c.config.GetAWSConfig().ContentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigTest) TearDownTest() {
|
||||||
|
_ = os.Remove(testConfigFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(ConfigTest))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_NoFile(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
assert.NotNil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
_ = NewConfig(path.Join(os.TempDir(), "file_which_should_not_exist_anyway"))
|
||||||
|
}
|
@ -4,6 +4,7 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,7 +78,6 @@ func (e *Engine) Prepare() *Engine {
|
|||||||
e.createRavenClient(e.Config.GetSentryDSN())
|
e.createRavenClient(e.Config.GetSentryDSN())
|
||||||
e.resetUtils(e.Config.GetAWSConfig(), e.Config.IsDebug(), 0)
|
e.resetUtils(e.Config.GetAWSConfig(), e.Config.IsDebug(), 0)
|
||||||
e.Logger = NewLogger(e.Config.GetTransportInfo().GetCode(), e.Config.GetLogLevel(), e.LogFormatter)
|
e.Logger = NewLogger(e.Config.GetTransportInfo().GetCode(), e.Config.GetLogLevel(), e.LogFormatter)
|
||||||
e.Utils.Localizer = &e.Localizer
|
|
||||||
e.Sentry.Localizer = &e.Localizer
|
e.Sentry.Localizer = &e.Localizer
|
||||||
e.Utils.Logger = e.Logger
|
e.Utils.Logger = e.Logger
|
||||||
e.Sentry.Logger = e.Logger
|
e.Sentry.Logger = e.Logger
|
||||||
@ -104,6 +104,14 @@ func (e *Engine) CreateRenderer(callback func(*Renderer), funcs template.FuncMap
|
|||||||
return renderer
|
return renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRendererFS with translation function and packr box with templates data
|
||||||
|
func (e *Engine) CreateRendererFS(box *packr.Box, callback func(*Renderer), funcs template.FuncMap) Renderer {
|
||||||
|
renderer := NewRenderer(e.TemplateFuncMap(funcs))
|
||||||
|
renderer.TemplatesBox = box
|
||||||
|
callback(&renderer)
|
||||||
|
return renderer
|
||||||
|
}
|
||||||
|
|
||||||
// Router will return current gin.Engine or panic if it's not present
|
// Router will return current gin.Engine or panic if it's not present
|
||||||
func (e *Engine) Router() *gin.Engine {
|
func (e *Engine) Router() *gin.Engine {
|
||||||
if !e.prepared {
|
if !e.prepared {
|
||||||
|
160
core/engine_test.go
Normal file
160
core/engine_test.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"html/template"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EngineTest struct {
|
||||||
|
suite.Suite
|
||||||
|
engine *Engine
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) SetupTest() {
|
||||||
|
var (
|
||||||
|
db *sql.DB
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
e.engine = New()
|
||||||
|
require.NotNil(e.T(), e.engine)
|
||||||
|
|
||||||
|
db, _, err = sqlmock.New()
|
||||||
|
require.NoError(e.T(), err)
|
||||||
|
|
||||||
|
if _, err := os.Stat(testTranslationsDir); err != nil && os.IsNotExist(err) {
|
||||||
|
err := os.Mkdir(testTranslationsDir, os.ModePerm)
|
||||||
|
require.Nil(e.T(), err)
|
||||||
|
data := []byte("message: Test message\nmessage_template: Test message with {{.data}}")
|
||||||
|
err = ioutil.WriteFile(testLangFile, data, os.ModePerm)
|
||||||
|
require.Nil(e.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.engine.Config = Config{
|
||||||
|
Version: "1",
|
||||||
|
LogLevel: 5,
|
||||||
|
Database: DatabaseConfig{
|
||||||
|
Connection: db,
|
||||||
|
Logging: true,
|
||||||
|
TablePrefix: "",
|
||||||
|
MaxOpenConnections: 10,
|
||||||
|
MaxIdleConnections: 10,
|
||||||
|
ConnectionLifetime: 60,
|
||||||
|
},
|
||||||
|
SentryDSN: "sentry dsn",
|
||||||
|
HTTPServer: HTTPServerConfig{
|
||||||
|
Host: "0.0.0.0",
|
||||||
|
Listen: ":3001",
|
||||||
|
},
|
||||||
|
Debug: true,
|
||||||
|
UpdateInterval: 30,
|
||||||
|
ConfigAWS: ConfigAWS{},
|
||||||
|
TransportInfo: Info{
|
||||||
|
Name: "test",
|
||||||
|
Code: "test",
|
||||||
|
LogoPath: "/test.svg",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Prepare_Twice() {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
require.NotNil(e.T(), r)
|
||||||
|
assert.Equal(e.T(), "engine already initialized", r.(string))
|
||||||
|
}()
|
||||||
|
|
||||||
|
engine := New()
|
||||||
|
engine.prepared = true
|
||||||
|
engine.Prepare()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Prepare_NoConfig() {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
require.NotNil(e.T(), r)
|
||||||
|
assert.Equal(e.T(), "engine.Config must be loaded before initializing", r.(string))
|
||||||
|
}()
|
||||||
|
|
||||||
|
engine := New()
|
||||||
|
engine.prepared = false
|
||||||
|
engine.Config = nil
|
||||||
|
engine.Prepare()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Prepare() {
|
||||||
|
defer func() {
|
||||||
|
require.Nil(e.T(), recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
e.engine.TranslationsPath = testTranslationsDir
|
||||||
|
e.engine.Prepare()
|
||||||
|
assert.True(e.T(), e.engine.prepared)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_initGin_Release() {
|
||||||
|
engine := New()
|
||||||
|
engine.Config = Config{Debug: false}
|
||||||
|
engine.initGin()
|
||||||
|
assert.NotNil(e.T(), engine.ginEngine)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_TemplateFuncMap() {
|
||||||
|
assert.NotNil(e.T(), e.engine.TemplateFuncMap(template.FuncMap{
|
||||||
|
"test": func() string {
|
||||||
|
return "test"
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_CreateRenderer() {
|
||||||
|
e.engine.CreateRenderer(func(r *Renderer) {
|
||||||
|
assert.NotNil(e.T(), r)
|
||||||
|
}, template.FuncMap{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Router_Fail() {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
require.NotNil(e.T(), r)
|
||||||
|
assert.Equal(e.T(), "prepare engine first", r.(string))
|
||||||
|
}()
|
||||||
|
|
||||||
|
engine := New()
|
||||||
|
engine.Router()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Router() {
|
||||||
|
e.engine.TranslationsPath = testTranslationsDir
|
||||||
|
e.engine.Prepare()
|
||||||
|
assert.NotNil(e.T(), e.engine.Router())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_ConfigureRouter() {
|
||||||
|
e.engine.TranslationsPath = testTranslationsDir
|
||||||
|
e.engine.Prepare()
|
||||||
|
e.engine.ConfigureRouter(func(engine *gin.Engine) {
|
||||||
|
assert.NotNil(e.T(), engine)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EngineTest) Test_Run_Fail() {
|
||||||
|
defer func() {
|
||||||
|
assert.NotNil(e.T(), recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
_ = New().Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEngine_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(EngineTest))
|
||||||
|
}
|
29
core/error_test.go
Normal file
29
core/error_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestError_GetErrorResponse(t *testing.T) {
|
||||||
|
code, resp := GetErrorResponse(http.StatusBadRequest, "error string")
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, code)
|
||||||
|
assert.Equal(t, "error string", resp.(ErrorResponse).Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestError_BadRequest(t *testing.T) {
|
||||||
|
code, resp := BadRequest("error string")
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusBadRequest, code)
|
||||||
|
assert.Equal(t, "error string", resp.(ErrorResponse).Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestError_InternalServerError(t *testing.T) {
|
||||||
|
code, resp := InternalServerError("error string")
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusInternalServerError, code)
|
||||||
|
assert.Equal(t, "error string", resp.(ErrorResponse).Error)
|
||||||
|
}
|
@ -6,6 +6,8 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gobuffalo/packd"
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
@ -14,6 +16,7 @@ import (
|
|||||||
// Localizer struct
|
// Localizer struct
|
||||||
type Localizer struct {
|
type Localizer struct {
|
||||||
i18n *i18n.Localizer
|
i18n *i18n.Localizer
|
||||||
|
TranslationsBox *packr.Box
|
||||||
LocaleBundle *i18n.Bundle
|
LocaleBundle *i18n.Bundle
|
||||||
LocaleMatcher language.Matcher
|
LocaleMatcher language.Matcher
|
||||||
LanguageTag language.Tag
|
LanguageTag language.Tag
|
||||||
@ -86,18 +89,65 @@ func (l *Localizer) getLocaleBundle() *i18n.Bundle {
|
|||||||
return l.LocaleBundle
|
return l.LocaleBundle
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadTranslations will load all translation files from translations directory
|
// LoadTranslations will load all translation files from translations directory or from embedded box
|
||||||
func (l *Localizer) LoadTranslations() {
|
func (l *Localizer) LoadTranslations() {
|
||||||
l.getLocaleBundle().RegisterUnmarshalFunc("yml", yaml.Unmarshal)
|
l.getLocaleBundle().RegisterUnmarshalFunc("yml", yaml.Unmarshal)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case l.TranslationsPath != "":
|
||||||
|
if err := l.loadFromDirectory(); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
case l.TranslationsBox != nil:
|
||||||
|
if err := l.loadFromFS(); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("TranslationsPath or TranslationsBox should be specified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadTranslations will load all translation files from translations directory
|
||||||
|
func (l *Localizer) loadFromDirectory() error {
|
||||||
files, err := ioutil.ReadDir(l.TranslationsPath)
|
files, err := ioutil.ReadDir(l.TranslationsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if !f.IsDir() {
|
if !f.IsDir() {
|
||||||
l.getLocaleBundle().MustLoadMessageFile(path.Join(l.TranslationsPath, f.Name()))
|
l.getLocaleBundle().MustLoadMessageFile(path.Join(l.TranslationsPath, f.Name()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadTranslations will load all translation files from embedded box
|
||||||
|
func (l *Localizer) loadFromFS() error {
|
||||||
|
err := l.TranslationsBox.Walk(func(s string, file packd.File) error {
|
||||||
|
if fileInfo, err := file.FileInfo(); err == nil {
|
||||||
|
if !fileInfo.IsDir() {
|
||||||
|
if data, err := ioutil.ReadAll(file); err == nil {
|
||||||
|
if _, err := l.getLocaleBundle().ParseMessageFileBytes(data, fileInfo.Name()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLocale will change language for current localizer
|
// SetLocale will change language for current localizer
|
||||||
|
101
core/localizer_test.go
Normal file
101
core/localizer_test.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
testTranslationsDir = path.Join(os.TempDir(), "translations_test_dir")
|
||||||
|
testLangFile = path.Join(testTranslationsDir, "translate.en.yml")
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocalizerTest struct {
|
||||||
|
suite.Suite
|
||||||
|
localizer *Localizer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) SetupTest() {
|
||||||
|
if _, err := os.Stat(testTranslationsDir); err != nil && os.IsNotExist(err) {
|
||||||
|
err := os.Mkdir(testTranslationsDir, os.ModePerm)
|
||||||
|
require.Nil(l.T(), err)
|
||||||
|
data := []byte("message: Test message\nmessage_template: Test message with {{.data}}")
|
||||||
|
err = ioutil.WriteFile(testLangFile, data, os.ModePerm)
|
||||||
|
require.Nil(l.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.localizer = NewLocalizer(language.English, DefaultLocalizerBundle(), DefaultLocalizerMatcher(), testTranslationsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_SetLocale() {
|
||||||
|
defer func() {
|
||||||
|
require.Nil(l.T(), recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
l.localizer.SetLocale("en")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_LocalizationMiddleware() {
|
||||||
|
assert.NotNil(l.T(), l.localizer.LocalizationMiddleware())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_LocalizationFuncMap() {
|
||||||
|
functions := l.localizer.LocalizationFuncMap()
|
||||||
|
_, ok := functions["trans"]
|
||||||
|
assert.True(l.T(), ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_GetLocalizedMessage() {
|
||||||
|
defer func() {
|
||||||
|
require.Nil(l.T(), recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
message := l.localizer.GetLocalizedMessage("message")
|
||||||
|
assert.Equal(l.T(), "Test message", message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_GetLocalizedTemplateMessage() {
|
||||||
|
defer func() {
|
||||||
|
require.Nil(l.T(), recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
message := l.localizer.GetLocalizedTemplateMessage("message_template", map[string]interface{}{"data": "template"})
|
||||||
|
assert.Equal(l.T(), "Test message with template", message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) Test_BadRequestLocalized() {
|
||||||
|
status, resp := l.localizer.BadRequestLocalized("message")
|
||||||
|
|
||||||
|
assert.Equal(l.T(), http.StatusBadRequest, status)
|
||||||
|
assert.Equal(l.T(), "Test message", resp.(ErrorResponse).Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LocalizerTest) TearDownTest() {
|
||||||
|
err := os.RemoveAll(testTranslationsDir)
|
||||||
|
require.Nil(l.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(LocalizerTest))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizer_NoDirectory(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
assert.NotNil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
_ = NewLocalizer(
|
||||||
|
language.English,
|
||||||
|
DefaultLocalizerBundle(),
|
||||||
|
DefaultLocalizerMatcher(),
|
||||||
|
path.Join(os.TempDir(), "this directory should not exist"),
|
||||||
|
)
|
||||||
|
}
|
21
core/logger_test.go
Normal file
21
core/logger_test.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/op/go-logging"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLogger_NewLogger(t *testing.T) {
|
||||||
|
logger := NewLogger("code", logging.DEBUG, DefaultLogFormatter())
|
||||||
|
|
||||||
|
assert.NotNil(t, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogger_DefaultLogFormatter(t *testing.T) {
|
||||||
|
formatter := DefaultLogFormatter()
|
||||||
|
|
||||||
|
assert.NotNil(t, formatter)
|
||||||
|
assert.IsType(t, logging.MustStringFormatter(`%{message}`), formatter)
|
||||||
|
}
|
274
core/migrate.go
Normal file
274
core/migrate.go
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gopkg.in/gormigrate.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// migrations default GORMigrate tool
|
||||||
|
var migrations *Migrate
|
||||||
|
|
||||||
|
// Migrate tool, decorates gormigrate.Migration in order to provide better interface & versioning
|
||||||
|
type Migrate struct {
|
||||||
|
db *gorm.DB
|
||||||
|
first *gormigrate.Migration
|
||||||
|
versions []string
|
||||||
|
migrations map[string]*gormigrate.Migration
|
||||||
|
GORMigrate *gormigrate.Gormigrate
|
||||||
|
prepared bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrationInfo with migration info
|
||||||
|
type MigrationInfo struct {
|
||||||
|
ID string `gorm:"column:id; type:varchar(255)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName for MigrationInfo
|
||||||
|
func (MigrationInfo) TableName() string {
|
||||||
|
return "migrations"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrations returns default migrate
|
||||||
|
func Migrations() *Migrate {
|
||||||
|
if migrations == nil {
|
||||||
|
migrations = &Migrate{
|
||||||
|
db: nil,
|
||||||
|
prepared: false,
|
||||||
|
migrations: map[string]*gormigrate.Migration{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return migrations
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add GORMigrate to migrate
|
||||||
|
func (m *Migrate) Add(migration *gormigrate.Migration) {
|
||||||
|
if migration == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.migrations[migration.ID] = migration
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetORM to migrate
|
||||||
|
func (m *Migrate) SetDB(db *gorm.DB) *Migrate {
|
||||||
|
m.db = db
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate all, including schema initialization
|
||||||
|
func (m *Migrate) Migrate() error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.migrations) > 0 {
|
||||||
|
return m.GORMigrate.Migrate()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback all migrations
|
||||||
|
func (m *Migrate) Rollback() error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.first == nil {
|
||||||
|
return errors.New("abnormal termination: first migration is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.GORMigrate.RollbackTo(m.first.ID); err == nil {
|
||||||
|
if err := m.GORMigrate.RollbackMigration(m.first); err == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateTo specified version
|
||||||
|
func (m *Migrate) MigrateTo(version string) error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
current := m.Current()
|
||||||
|
switch {
|
||||||
|
case current > version:
|
||||||
|
return m.GORMigrate.RollbackTo(version)
|
||||||
|
case current < version:
|
||||||
|
return m.GORMigrate.MigrateTo(version)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateNextTo migrate to next version from specified version
|
||||||
|
func (m *Migrate) MigrateNextTo(version string) error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if next, err := m.NextFrom(version); err == nil {
|
||||||
|
current := m.Current()
|
||||||
|
switch {
|
||||||
|
case current < next:
|
||||||
|
return m.GORMigrate.MigrateTo(next)
|
||||||
|
case current > next:
|
||||||
|
return errors.New(fmt.Sprintf("current migration version '%s' is higher than fetched version '%s'", current, next))
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigratePreviousTo migrate to previous version from specified version
|
||||||
|
func (m *Migrate) MigratePreviousTo(version string) error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev, err := m.PreviousFrom(version); err == nil {
|
||||||
|
current := m.Current()
|
||||||
|
switch {
|
||||||
|
case current > prev:
|
||||||
|
return m.GORMigrate.RollbackTo(prev)
|
||||||
|
case current < prev:
|
||||||
|
return errors.New(fmt.Sprintf("current migration version '%s' is lower than fetched version '%s'", current, prev))
|
||||||
|
case prev == "0":
|
||||||
|
return m.GORMigrate.RollbackMigration(m.first)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RollbackTo specified version
|
||||||
|
func (m *Migrate) RollbackTo(version string) error {
|
||||||
|
if err := m.prepareMigrations(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.GORMigrate.RollbackTo(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current migration version
|
||||||
|
func (m *Migrate) Current() string {
|
||||||
|
var migrationInfo MigrationInfo
|
||||||
|
|
||||||
|
if m.db == nil {
|
||||||
|
fmt.Println("warning => db is nil - cannot return migration version")
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.db.HasTable(MigrationInfo{}) {
|
||||||
|
if err := m.db.CreateTable(MigrationInfo{}).Error; err == nil {
|
||||||
|
fmt.Println("info => created migrations table")
|
||||||
|
} else {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.db.Last(&migrationInfo).Error; err == nil {
|
||||||
|
return migrationInfo.ID
|
||||||
|
} else {
|
||||||
|
fmt.Printf("warning => cannot fetch migration version: %s\n", err.Error())
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFrom returns next version from passed version
|
||||||
|
func (m *Migrate) NextFrom(version string) (string, error) {
|
||||||
|
for key, ver := range m.versions {
|
||||||
|
if ver == version {
|
||||||
|
if key < (len(m.versions) - 1) {
|
||||||
|
return m.versions[key+1], nil
|
||||||
|
} else {
|
||||||
|
return "", errors.New("this is last migration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("cannot find specified migration")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreviousFrom returns previous version from passed version
|
||||||
|
func (m *Migrate) PreviousFrom(version string) (string, error) {
|
||||||
|
for key, ver := range m.versions {
|
||||||
|
if ver == version {
|
||||||
|
if key > 0 {
|
||||||
|
return m.versions[key-1], nil
|
||||||
|
} else {
|
||||||
|
return "0", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("cannot find specified migration")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close db connection
|
||||||
|
func (m *Migrate) Close() error {
|
||||||
|
return m.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepareMigrations prepare migrate
|
||||||
|
func (m *Migrate) prepareMigrations() error {
|
||||||
|
var (
|
||||||
|
keys []string
|
||||||
|
migrations []*gormigrate.Migration
|
||||||
|
)
|
||||||
|
|
||||||
|
if m.db == nil {
|
||||||
|
return errors.New("db must not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.prepared {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range m.migrations {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
m.versions = keys
|
||||||
|
|
||||||
|
if len(keys) > 0 {
|
||||||
|
if i, ok := m.migrations[keys[0]]; ok {
|
||||||
|
m.first = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
if i, ok := m.migrations[key]; ok {
|
||||||
|
migrations = append(migrations, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options := &gormigrate.Options{
|
||||||
|
TableName: gormigrate.DefaultOptions.TableName,
|
||||||
|
IDColumnName: gormigrate.DefaultOptions.IDColumnName,
|
||||||
|
IDColumnSize: gormigrate.DefaultOptions.IDColumnSize,
|
||||||
|
UseTransaction: true,
|
||||||
|
ValidateUnknownMigrations: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.GORMigrate = gormigrate.New(m.db, options, migrations)
|
||||||
|
m.prepared = true
|
||||||
|
return nil
|
||||||
|
}
|
371
core/migrate_test.go
Normal file
371
core/migrate_test.go
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"gopkg.in/gormigrate.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestModel struct {
|
||||||
|
Name string `gorm:"column:name; type:varchar(70)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (TestModel) TableName() string {
|
||||||
|
return "test_model"
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrateTest struct {
|
||||||
|
suite.Suite
|
||||||
|
DB *gorm.DB
|
||||||
|
Migrate *Migrate
|
||||||
|
mock sqlmock.Sqlmock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) SetupSuite() {
|
||||||
|
require.NotEmpty(m.T(), (MigrationInfo{}).TableName())
|
||||||
|
m.RefreshMigrate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) RefreshMigrate() {
|
||||||
|
var (
|
||||||
|
db *sql.DB
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
db, m.mock, err = sqlmock.New()
|
||||||
|
require.NoError(m.T(), err)
|
||||||
|
|
||||||
|
m.DB, err = gorm.Open("postgres", db)
|
||||||
|
require.NoError(m.T(), err)
|
||||||
|
|
||||||
|
m.DB.LogMode(true)
|
||||||
|
m.Migrate = &Migrate{
|
||||||
|
db: m.DB,
|
||||||
|
prepared: false,
|
||||||
|
migrations: map[string]*gormigrate.Migration{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Migration_TestModelFirst() *gormigrate.Migration {
|
||||||
|
return &gormigrate.Migration{
|
||||||
|
ID: "1",
|
||||||
|
Migrate: func(db *gorm.DB) error {
|
||||||
|
return db.AutoMigrate(TestModel{}).Error
|
||||||
|
},
|
||||||
|
Rollback: func(db *gorm.DB) error {
|
||||||
|
return db.DropTable(TestModel{}).Error
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Migration_TestModelSecond() *gormigrate.Migration {
|
||||||
|
return &gormigrate.Migration{
|
||||||
|
ID: "2",
|
||||||
|
Migrate: func(db *gorm.DB) error {
|
||||||
|
return db.Model(TestModel{}).ModifyColumn("name", "varchar(100)").Error
|
||||||
|
},
|
||||||
|
Rollback: func(db *gorm.DB) error {
|
||||||
|
return db.Model(TestModel{}).ModifyColumn("name", "varchar(70)").Error
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Add() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(nil)
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
assert.Equal(m.T(), 1, len(m.Migrate.migrations))
|
||||||
|
i, ok := m.Migrate.migrations["1"]
|
||||||
|
require.True(m.T(), ok)
|
||||||
|
assert.Equal(m.T(), "1", i.ID)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_prepareMigrations_NilDB() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.db = nil
|
||||||
|
err := m.Migrate.prepareMigrations()
|
||||||
|
|
||||||
|
require.Error(m.T(), err)
|
||||||
|
assert.Equal(m.T(), "db must not be nil", err.Error())
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_prepareMigrations_AlreadyPrepared() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.prepared = true
|
||||||
|
err := m.Migrate.prepareMigrations()
|
||||||
|
|
||||||
|
require.NoError(m.T(), err)
|
||||||
|
assert.Nil(m.T(), m.Migrate.GORMigrate)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_prepareMigrations_OK() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
err := m.Migrate.prepareMigrations()
|
||||||
|
|
||||||
|
require.NoError(m.T(), err)
|
||||||
|
assert.True(m.T(), m.Migrate.prepared)
|
||||||
|
assert.NotNil(m.T(), m.Migrate.GORMigrate)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Migrate_Fail_NilDB() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.SetDB(nil)
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
err := m.Migrate.Migrate()
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Migrate_Success_NoMigrations() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.Migrate()
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Migrate_Success() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "test_model" ("name" varchar(70) )`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.Migrate()
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Rollback_Fail_NilDB() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.SetDB(nil)
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
err := m.Migrate.Rollback()
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Rollback_Fail_NoMigrations() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.first = m.Migration_TestModelFirst()
|
||||||
|
|
||||||
|
err := m.Migrate.Rollback()
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Rollback_Fail_NoFirstMigration() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
m.Migrate.first = nil
|
||||||
|
|
||||||
|
err := m.Migrate.Rollback()
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_MigrateTo_Fail_NilDB() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.SetDB(nil)
|
||||||
|
|
||||||
|
err := m.Migrate.MigrateTo("version")
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_MigrateTo_DoNothing() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.MigrateTo(m.Migration_TestModelFirst().ID)
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_MigrateTo() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "test_model" ("name" varchar(70) )`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.MigrateTo(m.Migration_TestModelFirst().ID)
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_RollbackTo() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
||||||
|
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.RollbackTo(m.Migration_TestModelSecond().ID)
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_MigrateNextTo() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
||||||
|
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectBegin()
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("1").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||||
|
m.mock.
|
||||||
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
||||||
|
WithArgs("2").
|
||||||
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`ALTER TABLE "test_model" ALTER COLUMN "name" TYPE varchar(100)`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
||||||
|
WithArgs("2").
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
m.mock.ExpectCommit()
|
||||||
|
|
||||||
|
err := m.Migrate.MigrateNextTo(m.Migration_TestModelFirst().ID)
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_MigratePreviousTo() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
||||||
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
||||||
|
|
||||||
|
m.mock.
|
||||||
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
||||||
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||||
|
|
||||||
|
err := m.Migrate.MigratePreviousTo(m.Migration_TestModelSecond().ID)
|
||||||
|
|
||||||
|
assert.Error(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MigrateTest) Test_Close() {
|
||||||
|
m.RefreshMigrate()
|
||||||
|
m.mock.ExpectClose()
|
||||||
|
err := m.Migrate.Close()
|
||||||
|
|
||||||
|
assert.NoError(m.T(), err)
|
||||||
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigrate_Migrate(t *testing.T) {
|
||||||
|
assert.NotNil(t, Migrations())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigrate_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(MigrateTest))
|
||||||
|
}
|
11
core/models_test.go
Normal file
11
core/models_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestModels_TableName(t *testing.T) {
|
||||||
|
assert.NotEmpty(t, (User{}).TableName())
|
||||||
|
}
|
73
core/orm_test.go
Normal file
73
core/orm_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestORM_NewORM(t *testing.T) {
|
||||||
|
var (
|
||||||
|
db *sql.DB
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
require.Nil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
db, _, err = sqlmock.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
config := DatabaseConfig{
|
||||||
|
Connection: db,
|
||||||
|
Logging: true,
|
||||||
|
TablePrefix: "",
|
||||||
|
MaxOpenConnections: 10,
|
||||||
|
MaxIdleConnections: 10,
|
||||||
|
ConnectionLifetime: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = NewORM(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestORM_createDB_Fail(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
assert.NotNil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
NewORM(DatabaseConfig{Connection: nil})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestORM_CloseDB(t *testing.T) {
|
||||||
|
var (
|
||||||
|
db *sql.DB
|
||||||
|
dbMock sqlmock.Sqlmock
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
require.Nil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
db, dbMock, err = sqlmock.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
config := DatabaseConfig{
|
||||||
|
Connection: db,
|
||||||
|
Logging: true,
|
||||||
|
TablePrefix: "",
|
||||||
|
MaxOpenConnections: 10,
|
||||||
|
MaxIdleConnections: 10,
|
||||||
|
ConnectionLifetime: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
dbMock.ExpectClose()
|
||||||
|
orm := NewORM(config)
|
||||||
|
orm.CloseDB()
|
||||||
|
|
||||||
|
assert.NoError(t, dbMock.ExpectationsWereMet())
|
||||||
|
}
|
@ -272,7 +272,7 @@ func (t *SentryTaggedStruct) GetProperty(v interface{}, property string) (name s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct {
|
if val.Kind() != reflect.Struct {
|
||||||
err = fmt.Errorf("passed value must be struct, %s provided", val.String())
|
err = fmt.Errorf("passed value must be struct, %s provided", val.Type().String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ func (t *SentryTaggedStruct) GetProperty(v interface{}, property string) (name s
|
|||||||
err = fmt.Errorf("cannot find property `%s`", property)
|
err = fmt.Errorf("cannot find property `%s`", property)
|
||||||
}
|
}
|
||||||
|
|
||||||
field := val.FieldByName(property)
|
field := reflect.Indirect(val.FieldByName(property))
|
||||||
if !field.IsValid() {
|
if !field.IsValid() {
|
||||||
err = fmt.Errorf("invalid property, got %s", field.String())
|
err = fmt.Errorf("invalid property, got %s", field.String())
|
||||||
return
|
return
|
||||||
@ -477,4 +477,4 @@ func getErrorCause(err error) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return cer.Cause()
|
return cer.Cause()
|
||||||
}
|
}
|
||||||
|
197
core/sentry_test.go
Normal file
197
core/sentry_test.go
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/getsentry/raven-go"
|
||||||
|
pkgErrors "github.com/pkg/errors"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SampleStruct struct {
|
||||||
|
ID int
|
||||||
|
Pointer *int
|
||||||
|
Field string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SentryTest struct {
|
||||||
|
suite.Suite
|
||||||
|
sentry *Sentry
|
||||||
|
structTags *SentryTaggedStruct
|
||||||
|
scalarTags *SentryTaggedScalar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) SetupTest() {
|
||||||
|
s.structTags = NewTaggedStruct(SampleStruct{}, "struct", map[string]string{"fake": "prop"})
|
||||||
|
s.scalarTags = NewTaggedScalar("", "scalar", "Scalar")
|
||||||
|
require.Equal(s.T(), "struct", s.structTags.GetContextKey())
|
||||||
|
require.Equal(s.T(), "scalar", s.scalarTags.GetContextKey())
|
||||||
|
require.Equal(s.T(), "", s.structTags.GetName())
|
||||||
|
require.Equal(s.T(), "Scalar", s.scalarTags.GetName())
|
||||||
|
s.structTags.Tags = map[string]string{}
|
||||||
|
s.sentry = NewSentry("dsn", "unknown_error", SentryTaggedTypes{}, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_AddTag() {
|
||||||
|
s.structTags.AddTag("test field", "Field")
|
||||||
|
require.NotEmpty(s.T(), s.structTags.GetTags())
|
||||||
|
|
||||||
|
tags, err := s.structTags.BuildTags(SampleStruct{Field: "value"})
|
||||||
|
require.NoError(s.T(), err)
|
||||||
|
require.NotEmpty(s.T(), tags)
|
||||||
|
|
||||||
|
i, ok := tags["test field"]
|
||||||
|
require.True(s.T(), ok)
|
||||||
|
assert.Equal(s.T(), "value", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty() {
|
||||||
|
s.structTags.AddTag("test field", "Field")
|
||||||
|
name, value, err := s.structTags.GetProperty(SampleStruct{Field: "test"}, "Field")
|
||||||
|
require.NoError(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "test field", name)
|
||||||
|
assert.Equal(s.T(), "test", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty_InvalidStruct() {
|
||||||
|
_, _, err := s.structTags.GetProperty(nil, "Field")
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "invalid value provided", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty_GotScalar() {
|
||||||
|
_, _, err := s.structTags.GetProperty("", "Field")
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "passed value must be struct, string provided", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty_InvalidType() {
|
||||||
|
_, _, err := s.structTags.GetProperty(Sentry{}, "Field")
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "passed value should be of type `core.SampleStruct`, got `core.Sentry` instead", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty_CannotFindProperty() {
|
||||||
|
_, _, err := s.structTags.GetProperty(SampleStruct{ID: 1}, "ID")
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "cannot find property `ID`", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_GetProperty_InvalidProperty() {
|
||||||
|
s.structTags.AddTag("test invalid", "Pointer")
|
||||||
|
_, _, err := s.structTags.GetProperty(SampleStruct{Pointer: nil}, "Pointer")
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "invalid property, got <invalid Value>", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_BuildTags_Fail() {
|
||||||
|
s.structTags.Tags = map[string]string{}
|
||||||
|
s.structTags.AddTag("test", "Field")
|
||||||
|
_, err := s.structTags.BuildTags(false)
|
||||||
|
assert.Error(s.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestStruct_BuildTags() {
|
||||||
|
s.structTags.Tags = map[string]string{}
|
||||||
|
s.structTags.AddTag("test", "Field")
|
||||||
|
tags, err := s.structTags.BuildTags(SampleStruct{Field: "value"})
|
||||||
|
|
||||||
|
require.NoError(s.T(), err)
|
||||||
|
require.NotEmpty(s.T(), tags)
|
||||||
|
i, ok := tags["test"]
|
||||||
|
require.True(s.T(), ok)
|
||||||
|
assert.Equal(s.T(), "value", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_Get_Nil() {
|
||||||
|
_, err := s.scalarTags.Get(nil)
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "invalid value provided", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_Get_Struct() {
|
||||||
|
_, err := s.scalarTags.Get(struct{}{})
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "passed value must not be struct", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_Get_InvalidType() {
|
||||||
|
_, err := s.scalarTags.Get(false)
|
||||||
|
require.Error(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "passed value should be of type `string`, got `bool` instead", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_Get() {
|
||||||
|
val, err := s.scalarTags.Get("test")
|
||||||
|
require.NoError(s.T(), err)
|
||||||
|
assert.Equal(s.T(), "test", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_GetTags() {
|
||||||
|
assert.Empty(s.T(), s.scalarTags.GetTags())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_BuildTags_Fail() {
|
||||||
|
_, err := s.scalarTags.BuildTags(false)
|
||||||
|
assert.Error(s.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestScalar_BuildTags() {
|
||||||
|
tags, err := s.scalarTags.BuildTags("test")
|
||||||
|
|
||||||
|
require.NoError(s.T(), err)
|
||||||
|
require.NotEmpty(s.T(), tags)
|
||||||
|
i, ok := tags[s.scalarTags.GetName()]
|
||||||
|
require.True(s.T(), ok)
|
||||||
|
assert.Equal(s.T(), "test", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestSentry_ErrorMiddleware() {
|
||||||
|
assert.NotNil(s.T(), s.sentry.ErrorMiddleware())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestSentry_PanicLogger() {
|
||||||
|
assert.NotNil(s.T(), s.sentry.PanicLogger())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestSentry_ErrorLogger() {
|
||||||
|
assert.NotNil(s.T(), s.sentry.ErrorLogger())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestSentry_ErrorResponseHandler() {
|
||||||
|
assert.NotNil(s.T(), s.sentry.ErrorResponseHandler())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SentryTest) TestSentry_ErrorCaptureHandler() {
|
||||||
|
assert.NotNil(s.T(), s.sentry.ErrorCaptureHandler())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSentry_newRavenStackTrace_Fail(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
assert.NotNil(t, recover())
|
||||||
|
}()
|
||||||
|
|
||||||
|
newRavenStackTrace(nil, errors.New("error"), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSentry_newRavenStackTrace(t *testing.T) {
|
||||||
|
st := newRavenStackTrace(&raven.Client{}, errors.New("error"), 0)
|
||||||
|
|
||||||
|
require.NotNil(t, st)
|
||||||
|
assert.NotEmpty(t, st.Frames)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSentry_newRavenStackTrace_ErrorsPkg(t *testing.T) {
|
||||||
|
err := pkgErrors.New("error")
|
||||||
|
st := newRavenStackTrace(&raven.Client{}, err, 0)
|
||||||
|
|
||||||
|
require.NotNil(t, st)
|
||||||
|
assert.NotEmpty(t, st.Frames)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSentry_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(SentryTest))
|
||||||
|
}
|
@ -4,11 +4,13 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
|
|
||||||
"github.com/gin-contrib/multitemplate"
|
"github.com/gin-contrib/multitemplate"
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Renderer wraps multitemplate.Renderer in order to make it easier to use
|
// Renderer wraps multitemplate.Renderer in order to make it easier to use
|
||||||
type Renderer struct {
|
type Renderer struct {
|
||||||
multitemplate.Renderer
|
multitemplate.Renderer
|
||||||
|
TemplatesBox *packr.Box
|
||||||
FuncMap template.FuncMap
|
FuncMap template.FuncMap
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,5 +24,22 @@ func NewRenderer(funcMap template.FuncMap) Renderer {
|
|||||||
|
|
||||||
// Push is an AddFromFilesFuncs wrapper
|
// Push is an AddFromFilesFuncs wrapper
|
||||||
func (r *Renderer) Push(name string, files ...string) *template.Template {
|
func (r *Renderer) Push(name string, files ...string) *template.Template {
|
||||||
return r.AddFromFilesFuncs(name, r.FuncMap, files...)
|
if r.TemplatesBox == nil {
|
||||||
|
return r.AddFromFilesFuncs(name, r.FuncMap, files...)
|
||||||
|
} else {
|
||||||
|
return r.addFromBox(name, r.FuncMap, files...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addFromBox adds embedded template
|
||||||
|
func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...string) *template.Template {
|
||||||
|
var filesData []string
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if data, err := r.TemplatesBox.FindString(file); err == nil {
|
||||||
|
filesData = append(filesData, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.AddFromStringsFuncs(name, funcMap, filesData...)
|
||||||
|
}
|
56
core/template_test.go
Normal file
56
core/template_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
testTemplatesDir = path.Join(os.TempDir(), "templates_test_dir")
|
||||||
|
testTemplatesFile = path.Join(testTemplatesDir, "tpl%d.html")
|
||||||
|
)
|
||||||
|
|
||||||
|
type TemplateTest struct {
|
||||||
|
suite.Suite
|
||||||
|
renderer Renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TemplateTest) SetupTest() {
|
||||||
|
if _, err := os.Stat(testTemplatesDir); err != nil && os.IsNotExist(err) {
|
||||||
|
err := os.Mkdir(testTemplatesDir, os.ModePerm)
|
||||||
|
require.Nil(t.T(), err)
|
||||||
|
data1 := []byte(`data {{template "body" .}}`)
|
||||||
|
data2 := []byte(`{{define "body"}}test {{"test" | trans}}{{end}}`)
|
||||||
|
err1 := ioutil.WriteFile(fmt.Sprintf(testTemplatesFile, 1), data1, os.ModePerm)
|
||||||
|
err2 := ioutil.WriteFile(fmt.Sprintf(testTemplatesFile, 2), data2, os.ModePerm)
|
||||||
|
require.Nil(t.T(), err1)
|
||||||
|
require.Nil(t.T(), err2)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.renderer = NewRenderer(template.FuncMap{
|
||||||
|
"trans": func(data string) string {
|
||||||
|
if data == "test" {
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "fail"
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TemplateTest) Test_Push() {
|
||||||
|
tpl := t.renderer.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||||
|
assert.Equal(t.T(), 3, len(tpl.Templates()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(TemplateTest))
|
||||||
|
}
|
@ -25,18 +25,16 @@ import (
|
|||||||
type Utils struct {
|
type Utils struct {
|
||||||
IsDebug bool
|
IsDebug bool
|
||||||
ConfigAWS ConfigAWS
|
ConfigAWS ConfigAWS
|
||||||
Localizer *Localizer
|
|
||||||
Logger *logging.Logger
|
Logger *logging.Logger
|
||||||
TokenCounter uint32
|
TokenCounter uint32
|
||||||
slashRegex *regexp.Regexp
|
slashRegex *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUtils will create new Utils instance
|
// NewUtils will create new Utils instance
|
||||||
func NewUtils(awsConfig ConfigAWS, localizer *Localizer, logger *logging.Logger, debug bool) *Utils {
|
func NewUtils(awsConfig ConfigAWS, logger *logging.Logger, debug bool) *Utils {
|
||||||
return &Utils{
|
return &Utils{
|
||||||
IsDebug: debug,
|
IsDebug: debug,
|
||||||
ConfigAWS: awsConfig,
|
ConfigAWS: awsConfig,
|
||||||
Localizer: localizer,
|
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
TokenCounter: 0,
|
TokenCounter: 0,
|
||||||
slashRegex: slashRegex,
|
slashRegex: slashRegex,
|
||||||
@ -141,6 +139,11 @@ func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveTrailingSlash will remove slash at the end of any string
|
||||||
|
func (u *Utils) RemoveTrailingSlash(crmURL string) string {
|
||||||
|
return u.slashRegex.ReplaceAllString(crmURL, ``)
|
||||||
|
}
|
||||||
|
|
||||||
// GetMGItemData will upload file to MG by URL and return information about attachable item
|
// GetMGItemData will upload file to MG by URL and return information about attachable item
|
||||||
func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, int, error) {
|
func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, int, error) {
|
||||||
item := v1.Item{}
|
item := v1.Item{}
|
||||||
@ -160,11 +163,6 @@ func GetMGItemData(client *v1.MgClient, url string, caption string) (v1.Item, in
|
|||||||
return item, st, err
|
return item, st, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTrailingSlash will remove slash at the end of any string
|
|
||||||
func (u *Utils) RemoveTrailingSlash(crmURL string) string {
|
|
||||||
return u.slashRegex.ReplaceAllString(crmURL, ``)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntitySHA1 will serialize any value to JSON and return SHA1 hash of this JSON
|
// GetEntitySHA1 will serialize any value to JSON and return SHA1 hash of this JSON
|
||||||
func GetEntitySHA1(v interface{}) (hash string, err error) {
|
func GetEntitySHA1(v interface{}) (hash string, err error) {
|
||||||
res, _ := json.Marshal(v)
|
res, _ := json.Marshal(v)
|
||||||
|
252
core/utils_test.go
Normal file
252
core/utils_test.go
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/h2non/gock"
|
||||||
|
"github.com/op/go-logging"
|
||||||
|
v5 "github.com/retailcrm/api-client-go/v5"
|
||||||
|
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
testCRMURL = "https://fake-uri.retailcrm.ru"
|
||||||
|
testMGURL = "https://mg-url.example.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UtilsTest struct {
|
||||||
|
suite.Suite
|
||||||
|
utils *Utils
|
||||||
|
}
|
||||||
|
|
||||||
|
func mgClient() *v1.MgClient {
|
||||||
|
return v1.New(testMGURL, "token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) SetupTest() {
|
||||||
|
logger := NewLogger("code", logging.DEBUG, DefaultLogFormatter())
|
||||||
|
awsConfig := ConfigAWS{
|
||||||
|
AccessKeyID: "access key id (will be removed)",
|
||||||
|
SecretAccessKey: "secret access key",
|
||||||
|
Region: "region",
|
||||||
|
Bucket: "bucket",
|
||||||
|
FolderName: "folder",
|
||||||
|
ContentType: "image/jpeg",
|
||||||
|
}
|
||||||
|
|
||||||
|
u.utils = NewUtils(awsConfig, logger, false)
|
||||||
|
u.utils.TokenCounter = 12345
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_ResetUtils() {
|
||||||
|
assert.Equal(u.T(), "access key id (will be removed)", u.utils.ConfigAWS.AccessKeyID)
|
||||||
|
assert.Equal(u.T(), uint32(12345), u.utils.TokenCounter)
|
||||||
|
assert.False(u.T(), u.utils.IsDebug)
|
||||||
|
|
||||||
|
awsConfig := u.utils.ConfigAWS
|
||||||
|
awsConfig.AccessKeyID = "access key id"
|
||||||
|
u.utils.resetUtils(awsConfig, true, 0)
|
||||||
|
|
||||||
|
assert.Equal(u.T(), "access key id", u.utils.ConfigAWS.AccessKeyID)
|
||||||
|
assert.Equal(u.T(), uint32(0), u.utils.TokenCounter)
|
||||||
|
assert.True(u.T(), u.utils.IsDebug)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_GenerateToken() {
|
||||||
|
u.utils.TokenCounter = 12345
|
||||||
|
token := u.utils.GenerateToken()
|
||||||
|
assert.NotEmpty(u.T(), token)
|
||||||
|
assert.Equal(u.T(), uint32(12346), u.utils.TokenCounter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_GetAPIClient_FailRuntime() {
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New(testCRMURL)
|
||||||
|
|
||||||
|
_, status, err := u.utils.GetAPIClient(testCRMURL, "key")
|
||||||
|
assert.Equal(u.T(), http.StatusInternalServerError, status)
|
||||||
|
assert.NotNil(u.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_GetAPIClient_FailAPI() {
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New(testCRMURL).
|
||||||
|
Get("/credentials").
|
||||||
|
Reply(http.StatusBadRequest).
|
||||||
|
BodyString(`{"success": false, "errorMsg": "error message"}`)
|
||||||
|
|
||||||
|
_, status, err := u.utils.GetAPIClient(testCRMURL, "key")
|
||||||
|
assert.Equal(u.T(), http.StatusBadRequest, status)
|
||||||
|
if assert.NotNil(u.T(), err) {
|
||||||
|
assert.Equal(u.T(), "invalid credentials", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_GetAPIClient_FailAPICredentials() {
|
||||||
|
resp := v5.CredentialResponse{
|
||||||
|
Success: true,
|
||||||
|
Credentials: []string{},
|
||||||
|
SiteAccess: "all",
|
||||||
|
SitesAvailable: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _ := json.Marshal(resp)
|
||||||
|
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New(testCRMURL).
|
||||||
|
Get("/credentials").
|
||||||
|
Reply(http.StatusOK).
|
||||||
|
BodyString(string(data))
|
||||||
|
|
||||||
|
_, status, err := u.utils.GetAPIClient(testCRMURL, "key")
|
||||||
|
assert.Equal(u.T(), http.StatusBadRequest, status)
|
||||||
|
if assert.NotNil(u.T(), err) {
|
||||||
|
assert.Equal(u.T(), "missing credentials", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_GetAPIClient_Success() {
|
||||||
|
resp := v5.CredentialResponse{
|
||||||
|
Success: true,
|
||||||
|
Credentials: []string{
|
||||||
|
"/api/integration-modules/{code}",
|
||||||
|
"/api/integration-modules/{code}/edit",
|
||||||
|
},
|
||||||
|
SiteAccess: "all",
|
||||||
|
SitesAvailable: []string{"site"},
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _ := json.Marshal(resp)
|
||||||
|
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New(testCRMURL).
|
||||||
|
Get("/credentials").
|
||||||
|
Reply(http.StatusOK).
|
||||||
|
BodyString(string(data))
|
||||||
|
|
||||||
|
_, status, err := u.utils.GetAPIClient(testCRMURL, "key")
|
||||||
|
require.NoError(u.T(), err)
|
||||||
|
assert.Equal(u.T(), 0, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_UploadUserAvatar_FailGet() {
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New("https://example.com")
|
||||||
|
|
||||||
|
uri, err := u.utils.UploadUserAvatar("https://example.com/image.jpg")
|
||||||
|
assert.Empty(u.T(), uri)
|
||||||
|
assert.Error(u.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_UploadUserAvatar_FailBadRequest() {
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New("https://example.com").
|
||||||
|
Get("/image.jpg").
|
||||||
|
Reply(200).
|
||||||
|
BodyString(`no image here`)
|
||||||
|
|
||||||
|
uri, err := u.utils.UploadUserAvatar("https://example.com/image.jpg")
|
||||||
|
assert.Empty(u.T(), uri)
|
||||||
|
assert.Error(u.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UtilsTest) Test_RemoveTrailingSlash() {
|
||||||
|
assert.Equal(u.T(), testCRMURL, u.utils.RemoveTrailingSlash(testCRMURL+"/"))
|
||||||
|
assert.Equal(u.T(), testCRMURL, u.utils.RemoveTrailingSlash(testCRMURL))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_GetMGItemData_FailRuntime_GetImage(t *testing.T) {
|
||||||
|
defer gock.Off()
|
||||||
|
gock.New(testMGURL)
|
||||||
|
gock.New("https://example.com/")
|
||||||
|
|
||||||
|
_, status, err := GetMGItemData(mgClient(), "https://example.com/item.jpg", "")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, 0, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_GetMGItemData_FailAPI(t *testing.T) {
|
||||||
|
defer gock.Off()
|
||||||
|
|
||||||
|
gock.New("https://example.com/").
|
||||||
|
Get("/item.jpg").
|
||||||
|
Reply(200).
|
||||||
|
BodyString(`fake data`)
|
||||||
|
|
||||||
|
gock.New(testMGURL).
|
||||||
|
Post("/files/upload_by_url").
|
||||||
|
Reply(400).
|
||||||
|
BodyString(`{"errors": ["error text"]}`)
|
||||||
|
|
||||||
|
_, status, err := GetMGItemData(mgClient(), "https://example.com/item.jpg", "")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, http.StatusBadRequest, status)
|
||||||
|
assert.Equal(t, "error text", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_GetMGItemData_Success(t *testing.T) {
|
||||||
|
fileID := "file id"
|
||||||
|
size := 40
|
||||||
|
uri := "file uri"
|
||||||
|
resp := v1.UploadFileResponse{
|
||||||
|
ID: fileID,
|
||||||
|
Hash: "file hash",
|
||||||
|
Type: "image/jpeg",
|
||||||
|
Meta: v1.FileMeta{
|
||||||
|
Width: &size,
|
||||||
|
Height: &size,
|
||||||
|
},
|
||||||
|
MimeType: "image/jpeg",
|
||||||
|
Size: 250,
|
||||||
|
Url: &uri,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _ := json.Marshal(resp)
|
||||||
|
|
||||||
|
defer gock.Off()
|
||||||
|
|
||||||
|
gock.New("https://example.com/").
|
||||||
|
Get("/item.jpg").
|
||||||
|
Reply(200).
|
||||||
|
BodyString(`fake data`)
|
||||||
|
|
||||||
|
gock.New(testMGURL).
|
||||||
|
Post("/files/upload_by_url").
|
||||||
|
Reply(200).
|
||||||
|
BodyString(string(data))
|
||||||
|
|
||||||
|
response, status, err := GetMGItemData(mgClient(), "https://example.com/item.jpg", "caption")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, http.StatusOK, status)
|
||||||
|
assert.Equal(t, fileID, response.ID)
|
||||||
|
assert.Equal(t, "caption", response.Caption)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_GetEntitySHA1(t *testing.T) {
|
||||||
|
entity := struct {
|
||||||
|
Field string
|
||||||
|
}{
|
||||||
|
Field: "value",
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := GetEntitySHA1(entity)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "751b56fb98c9fd803140e8287b4236675554a668", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_ReplaceMarkdownSymbols(t *testing.T) {
|
||||||
|
test := "this *is* _test_ `string` [markdown"
|
||||||
|
expected := "this \\*is\\* \\_test\\_ \\`string\\` \\[markdown"
|
||||||
|
assert.Equal(t, expected, ReplaceMarkdownSymbols(test))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtils_Suite(t *testing.T) {
|
||||||
|
suite.Run(t, new(UtilsTest))
|
||||||
|
}
|
17
go.mod
17
go.mod
@ -3,33 +3,36 @@ module github.com/retailcrm/mg-transport-core
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3
|
||||||
github.com/aws/aws-sdk-go v1.23.9
|
github.com/aws/aws-sdk-go v1.23.9
|
||||||
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 // indirect
|
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 // indirect
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd // indirect
|
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd // indirect
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
|
||||||
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03
|
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03
|
||||||
github.com/gin-contrib/multitemplate v0.0.0-20180827023943-5799bbbb6dce
|
github.com/gin-contrib/multitemplate v0.0.0-20180827023943-5799bbbb6dce
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/gin-gonic/gin v1.3.0
|
github.com/gin-gonic/gin v1.3.0
|
||||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
github.com/gobuffalo/packd v0.3.0
|
||||||
|
github.com/gobuffalo/packr/v2 v2.6.0
|
||||||
github.com/golang/protobuf v1.3.2 // indirect
|
github.com/golang/protobuf v1.3.2 // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.0.0 // indirect
|
||||||
github.com/jinzhu/gorm v1.9.1
|
github.com/h2non/gock v1.0.10
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/gorm v1.9.10
|
||||||
github.com/jinzhu/now v1.0.1 // indirect
|
github.com/json-iterator/go v1.1.7 // indirect
|
||||||
github.com/lib/pq v1.2.0 // indirect
|
github.com/lib/pq v1.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.9 // indirect
|
github.com/mattn/go-isatty v0.0.9 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.11.0 // indirect
|
github.com/mattn/go-sqlite3 v1.11.0 // indirect
|
||||||
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5
|
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/retailcrm/api-client-go v1.1.1
|
github.com/retailcrm/api-client-go v1.1.1
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.1.31
|
github.com/retailcrm/mg-transport-api-client-go v1.1.31
|
||||||
github.com/stretchr/testify v1.4.0 // indirect
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/ugorji/go v1.1.7 // indirect
|
github.com/ugorji/go v1.1.7 // indirect
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2
|
||||||
golang.org/x/tools v0.0.0-20190830082254-f340ed3ae274 // indirect
|
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||||
gopkg.in/go-playground/validator.v8 v8.18.2
|
gopkg.in/go-playground/validator.v8 v8.18.2
|
||||||
|
gopkg.in/gormigrate.v1 v1.6.0
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
)
|
)
|
||||||
|
106
go.sum
106
go.sum
@ -1,25 +1,36 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
||||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||||
github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY=
|
github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY=
|
||||||
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/aws/aws-sdk-go v1.23.9 h1:UYWPGrBMlrW5VCYeWMbog1T/kqZzkvvheUDQaaUAhqI=
|
github.com/aws/aws-sdk-go v1.23.9 h1:UYWPGrBMlrW5VCYeWMbog1T/kqZzkvvheUDQaaUAhqI=
|
||||||
github.com/aws/aws-sdk-go v1.23.9/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.23.9/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 h1:UNOqI3EKhvbqV8f1Vm3NIwkrhq388sGCeAH2Op7w0rc=
|
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 h1:UNOqI3EKhvbqV8f1Vm3NIwkrhq388sGCeAH2Op7w0rc=
|
||||||
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
|
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
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.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd h1:DoaaxHqzWPQCWKSTmsi8UDSiFqxbfue+Xt+qi/BFKb8=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd h1:DoaaxHqzWPQCWKSTmsi8UDSiFqxbfue+Xt+qi/BFKb8=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd/go.mod h1:uU0N10vx1abI4qeVe79CxepBP6PPREVTgMS5Gx6/mOk=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190830225923-3302f0226fbd/go.mod h1:uU0N10vx1abI4qeVe79CxepBP6PPREVTgMS5Gx6/mOk=
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
@ -27,7 +38,6 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
|
|||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03 h1:G/9fPivTr5EiyqE9OlW65iMRUxFXMGRHgZFGo50uG8Q=
|
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03 h1:G/9fPivTr5EiyqE9OlW65iMRUxFXMGRHgZFGo50uG8Q=
|
||||||
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
github.com/getsentry/raven-go v0.0.0-20180903072508-084a9de9eb03/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||||
@ -42,6 +52,15 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
|
||||||
|
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||||
|
github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy4=
|
||||||
|
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||||
|
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
|
||||||
|
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||||
|
github.com/gobuffalo/packr/v2 v2.6.0 h1:EMUzJIb5rof6r087PtGmgdzdLKpRBESJ/8jyL9MexfY=
|
||||||
|
github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08=
|
||||||
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
@ -52,43 +71,72 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs
|
|||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
|
|
||||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
|
||||||
github.com/google/wire v0.3.0 h1:imGQZGEVEHpje5056+K+cgdO72p0LQv2xIIFXNGUf60=
|
|
||||||
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/h2non/gock v1.0.10 h1:EzHYzKKSLN4xk0w193uAy3tp8I3+L1jmaI2Mjg4lCgU=
|
||||||
|
github.com/h2non/gock v1.0.10/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/jinzhu/gorm v1.9.1 h1:lDSDtsCt5AGGSKTs8AHlSDbbgif4G4+CKJ8ETBDVHTA=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jinzhu/gorm v1.9.1/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
|
github.com/jinzhu/gorm v1.9.2 h1:lCvgEaqe/HVE+tjAR2mt4HbbHAZsQOv3XAZiEZV37iw=
|
||||||
|
github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
|
||||||
|
github.com/jinzhu/gorm v1.9.10 h1:HvrsqdhCW78xpJF67g1hMxS6eCToo9PZH4LDB8WKPac=
|
||||||
|
github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY=
|
||||||
|
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v0.0.0-20181116074157-8ec929ed50c3/go.mod h1:oHTiXerJ20+SfYcrdlBO7rzZRJWGwSTQ0iUY2jI6Gfc=
|
||||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
|
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/karrick/godirwalk v1.10.12 h1:BqUm+LuJcXjGv1d2mj3gBiQyrQ57a0rYoAmhvJQ7RDU=
|
||||||
|
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||||
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5 h1:/TjjTS4kg7vC+05gD0LE4+97f/+PRFICnK/7wJPk7kE=
|
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5 h1:/TjjTS4kg7vC+05gD0LE4+97f/+PRFICnK/7wJPk7kE=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5/go.mod h1:4Opqa6/HIv0lhG3WRAkqzO0afezkRhxXI0P8EJkqeRU=
|
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5/go.mod h1:4Opqa6/HIv0lhG3WRAkqzO0afezkRhxXI0P8EJkqeRU=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@ -97,6 +145,7 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
@ -115,7 +164,19 @@ github.com/retailcrm/api-client-go v1.1.1 h1:yqsyYjBDdmDwExVlTdGucY9/IpEokXpkfTf
|
|||||||
github.com/retailcrm/api-client-go v1.1.1/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c=
|
github.com/retailcrm/api-client-go v1.1.1/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c=
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.1.31 h1:21pE1JhT49rvbMLDYJa0iiqbb/roz+eSp27fPck4uUw=
|
github.com/retailcrm/mg-transport-api-client-go v1.1.31 h1:21pE1JhT49rvbMLDYJa0iiqbb/roz+eSp27fPck4uUw=
|
||||||
github.com/retailcrm/mg-transport-api-client-go v1.1.31/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI=
|
github.com/retailcrm/mg-transport-api-client-go v1.1.31/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI=
|
||||||
|
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@ -124,13 +185,19 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
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 h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
|
||||||
|
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@ -143,7 +210,7 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
|
|||||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -152,14 +219,18 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
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=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.0.0-20171214130843-f21a4dfb5e38/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20171214130843-f21a4dfb5e38/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -172,12 +243,11 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190830082254-f340ed3ae274 h1:3LEbAKuShoQDlrpbepJOeKph85ROShka+GypY1YNQYQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190830082254-f340ed3ae274/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@ -187,10 +257,16 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
|||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
|
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
|
||||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||||
|
gopkg.in/gormigrate.v1 v1.6.0 h1:XpYM6RHQPmzwY7Uyu+t+xxMXc86JYFJn4nEc9HzQjsI=
|
||||||
|
gopkg.in/gormigrate.v1 v1.6.0/go.mod h1:Lf00lQrHqfSYWiTtPcyQabsDdM6ejZaMgV0OU6JMSlw=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
Loading…
Reference in New Issue
Block a user