diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 96fb2695a..b52693702 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -62,5 +62,12 @@ jobs: - name: Run Tests run: | - go mod vendor make test + + - name: Upload coverage + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV }} + file: ./coverage.out + name: codecov-umbrella + verbose: true diff --git a/Makefile b/Makefile index 19751fdc0..a10408249 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ install: cp ${BUILD_DIR}/$(SVC) $(GOBIN)/magistrala-${SVC} test: - go test -v -race -count 1 -tags test $(shell go list ./... | grep -v 'cmd') + go test -v -race -count 1 -tags test -coverprofile=coverage.out $(shell go list ./... | grep -v 'cmd') lint: golangci-lint run --config .golangci.yml diff --git a/cmd/ui/main.go b/cmd/ui/main.go index cf6cca921..65f756bb9 100644 --- a/cmd/ui/main.go +++ b/cmd/ui/main.go @@ -88,12 +88,15 @@ func main() { oauthProvider := google.NewProvider(oauthConfig) dbConfig := postgres.Config{} + if err := env.Parse(&dbConfig); err != nil { + log.Fatalf("failed to load database configuration : %s", err.Error()) + } db, err := postgres.Setup(dbConfig, *repo.Migration()) if err != nil { log.Fatalf("Failed to setup postgres db : %s", err) } - dbs := repo.New(db) + dbs := repo.NewRepository(db) idp := uuid.New() diff --git a/go.mod b/go.mod index 048dffc1d..a7787eb4c 100644 --- a/go.mod +++ b/go.mod @@ -3,26 +3,23 @@ module github.com/absmach/magistrala-ui go 1.21.5 require ( + github.com/0x6flab/namegenerator v1.2.0 github.com/absmach/agent v0.0.0-20240202075640-cc619e6685c8 github.com/absmach/magistrala v0.14.1-0.20240305111255-42d433a92f39 github.com/absmach/senml v1.0.5 github.com/caarlos0/env/v10 v10.0.0 github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/go-chi/chi/v5 v5.0.12 - github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-kit/kit v0.13.0 github.com/go-zoo/bone v1.3.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/gorilla/securecookie v1.1.2 - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/pgx/v5 v5.5.5 - github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jmoiron/sqlx v1.3.5 - github.com/pkg/errors v0.9.1 + github.com/ory/dockertest/v3 v3.10.0 github.com/prometheus/client_golang v1.19.0 github.com/rubenv/sql-migrate v1.6.1 - golang.org/x/crypto v0.21.0 // indirect + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 @@ -32,28 +29,61 @@ require ( require ( cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/containerd/continuity v0.4.3 // indirect github.com/creack/pty v1.1.18 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/docker/cli v24.0.7+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/edgexfoundry/go-mod-core-contracts v0.1.70 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/mainflux/export v0.1.1-0.20230724124847-67d0bc7f38cb // indirect github.com/mainflux/mainflux v0.12.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.1.12 // indirect github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.22.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.18.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6f67a7970..efe64dd8b 100644 --- a/go.sum +++ b/go.sum @@ -23,13 +23,20 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/0x6flab/namegenerator v1.2.0 h1:RuHRO7NDGQpZ9ajRFP5ALcl66cyi0hqjs1fXDV+3pZE= +github.com/0x6flab/namegenerator v1.2.0/go.mod h1:h28wadnJ13Q7PxpUzAHckVj9ToyAEdx5T186Zj1kp+k= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -85,6 +92,8 @@ github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -100,6 +109,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/continuity v0.0.0-20180416230128-c6cef3483023/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -126,11 +137,18 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xb github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dsnet/golib/memfile v0.0.0-20190531212259-571cdbcff553/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= github.com/dsnet/golib/memfile v0.0.0-20200723050859-c110804dfa93/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= github.com/dustin/go-coap v0.0.0-20170214053734-ddcc80675fa4/go.mod h1:as2rZ2aojRzZF8bGx1bPAn1yi9ICG6LwkiPOj6PBtjc= @@ -253,6 +271,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -302,6 +322,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -395,6 +417,8 @@ github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:p github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY= github.com/influxdata/influxdb v1.6.4/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= @@ -450,6 +474,7 @@ github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0Lh github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -539,6 +564,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -580,9 +607,15 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -595,6 +628,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.0+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/ory/dockertest/v3 v3.6.0/go.mod h1:4ZOpj8qBUmh8fcBSVzkH2bws2s91JdGvHUqan4GHEuQ= +github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= +github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -703,6 +738,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -766,10 +803,18 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xdg/stringprep v1.0.1-0.20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -854,7 +899,10 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -885,6 +933,7 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= @@ -903,6 +952,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -948,9 +998,12 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1013,10 +1066,15 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20190808205415-ced62fe5104b/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -1133,11 +1191,16 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/postgres/postgres.go b/internal/postgres/postgres.go index 64143f341..207405300 100644 --- a/internal/postgres/postgres.go +++ b/internal/postgres/postgres.go @@ -7,14 +7,12 @@ import ( "fmt" "github.com/absmach/magistrala/pkg/errors" - "github.com/caarlos0/env/v10" _ "github.com/jackc/pgx/v5/stdlib" // required for SQL access "github.com/jmoiron/sqlx" migrate "github.com/rubenv/sql-migrate" ) var ( - errConfig = errors.New("failed to load postgresql configuration") errConnect = errors.New("failed to connect to postgresql server") errMigration = errors.New("failed to apply migrations") ) @@ -35,17 +33,14 @@ type Config struct { // Setup creates a connection to the PostgreSQL instance and applies any // unapplied database migrations. A non-nil error is returned to indicate failure. func Setup(cfg Config, migrations migrate.MemoryMigrationSource) (*sqlx.DB, error) { - if err := env.Parse(&cfg); err != nil { - return nil, errors.Wrap(errConfig, err) - } - db, err := Connect(cfg) if err != nil { return nil, err } - if err := MigrateDB(db, migrations); err != nil { - return nil, err + if _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up); err != nil { + return nil, errors.Wrap(errMigration, err) } + return db, nil } @@ -60,12 +55,3 @@ func Connect(cfg Config) (*sqlx.DB, error) { return db, nil } - -// MigrateDB applies any unapplied database migrations. -func MigrateDB(db *sqlx.DB, migrations migrate.MemoryMigrationSource) error { - if _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up); err != nil { - return errors.Wrap(errMigration, err) - } - - return nil -} diff --git a/postgres/dashboards.go b/postgres/dashboards.go index b8c786a54..2e8fae910 100644 --- a/postgres/dashboards.go +++ b/postgres/dashboards.go @@ -19,14 +19,13 @@ type repo struct { db *sqlx.DB } -func New(db *sqlx.DB) ui.DashboardRepository { +func NewRepository(db *sqlx.DB) ui.DashboardRepository { return &repo{db: db} } // Create a non-existing dashboard for a user. func (r *repo) Create(ctx context.Context, dashboard ui.Dashboard) (ui.Dashboard, error) { - q := ` - INSERT INTO dashboards (id, created_by, name, description, layout, metadata, created_at, updated_at) + q := `INSERT INTO dashboards (id, created_by, name, description, layout, metadata, created_at, updated_at) VALUES (:id, :created_by, :name, :description, :layout, :metadata, :created_at, :updated_at) RETURNING id, created_by, name, description, layout, created_at` @@ -67,12 +66,12 @@ func (r *repo) Retrieve(ctx context.Context, dashboardID, userID string) (ui.Das } defer rows.Close() - dbDs := dbDashboard{} + dbd := dbDashboard{} if rows.Next() { - if err = rows.StructScan(&dbDs); err != nil { + if err = rows.StructScan(&dbd); err != nil { return ui.Dashboard{}, HandleError(err, ErrViewEntity) } - return toDashboard(dbDs) + return toDashboard(dbd) } return ui.Dashboard{}, ErrNotFound @@ -81,10 +80,7 @@ func (r *repo) Retrieve(ctx context.Context, dashboardID, userID string) (ui.Das // Retrieve all dashboards for a user using a user id. func (r *repo) RetrieveAll(ctx context.Context, page ui.DashboardPageMeta) (ui.DashboardPage, error) { q := `SELECT id, created_by, name, description, created_at, updated_at FROM dashboards - WHERE created_by = :created_by - ORDER BY created_at DESC - LIMIT :limit - OFFSET :offset` + WHERE created_by = :created_by ORDER BY created_at DESC LIMIT :limit OFFSET :offset` rows, err := r.db.NamedQueryContext(ctx, q, page) if err != nil { @@ -143,13 +139,17 @@ func (r *repo) Update(ctx context.Context, dashboardID, userID string, dr ui.Das query = append(query, "metadata = :metadata") d.Metadata = dr.Metadata } - if len(query) > 0 { + + switch { + case len(query) == 0: + return ErrMalformedEntity + case len(query) > 0: + query = append(query, "updated_at = :updated_at") + d.UpdatedAt = time.Now() upq = strings.Join(query, ",") } - d.UpdatedAt = time.Now() - - q := fmt.Sprintf(`UPDATE dashboards SET %s, updated_at= :updated_at WHERE id = :id AND created_by = :created_by`, upq) + q := fmt.Sprintf(`UPDATE dashboards SET %s WHERE id = :id AND created_by = :created_by`, upq) dbDs, err := toDBDashboard(d) if err != nil { diff --git a/postgres/dashboards_test.go b/postgres/dashboards_test.go index 6c393992f..55501850b 100644 --- a/postgres/dashboards_test.go +++ b/postgres/dashboards_test.go @@ -2,3 +2,641 @@ // SPDX-License-Identifier: Apache-2.0 package postgres_test + +import ( + "context" + "fmt" + "slices" + "strings" + "testing" + "time" + + "github.com/0x6flab/namegenerator" + "github.com/absmach/magistrala-ui/postgres" + "github.com/absmach/magistrala-ui/ui" + "github.com/absmach/magistrala/pkg/errors" + "github.com/absmach/magistrala/pkg/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var namegen = namegenerator.NewNameGenerator() + +func TestCreate(t *testing.T) { + t.Cleanup(func() { + _, err := db.Exec("DELETE FROM dashboards") + require.Nil(t, err, fmt.Sprintf("clean dashboards unexpected error: %s", err)) + }) + + id := generateUUID(t) + + cases := []struct { + desc string + dashboard ui.Dashboard + err error + }{ + { + desc: "create new dashboard", + dashboard: ui.Dashboard{ + ID: id, + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: nil, + }, + { + desc: "create existing dashboard", + dashboard: ui.Dashboard{ + ID: id, + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrConflict, + }, + { + desc: "create new dashboard with empty id", + dashboard: ui.Dashboard{ + ID: "", + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrCreateEntity, + }, + { + desc: "create new dashboard with empty created by", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: "", + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrCreateEntity, + }, + { + desc: "create new dashboard with empty name", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: "", + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrCreateEntity, + }, + { + desc: "create new dashboard with empty description", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: "", + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: nil, + }, + { + desc: "create new dashboard with empty layout", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: "", + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: nil, + }, + { + desc: "create new dashboard with empty metadata", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: "", + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: nil, + }, + { + desc: "create new dashboard with malformed id", + dashboard: ui.Dashboard{ + ID: strings.Repeat("a", 37), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrMalformedEntity, + }, + { + desc: "create new dashboard with malformed created by", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: strings.Repeat("a", 37), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrMalformedEntity, + }, + { + desc: "create new dashboard with malformed name", + dashboard: ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: strings.Repeat("a", 256), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + }, + err: postgres.ErrMalformedEntity, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + rDashboard, err := repo.Create(context.Background(), tc.dashboard) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error: %s to contain: %s", err, tc.err)) + if err == nil { + tc.dashboard.Metadata = "" + assert.Equal(t, tc.dashboard, rDashboard) + } + }) + } +} + +func TestRetrieve(t *testing.T) { + t.Cleanup(func() { + _, err := db.Exec("DELETE FROM dashboards") + require.Nil(t, err, fmt.Sprintf("clean dashboards unexpected error: %s", err)) + }) + + dashboard := ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + } + _, err := repo.Create(context.Background(), dashboard) + require.Nil(t, err, fmt.Sprintf("create dashboard unexpected error: %s", err)) + + cases := []struct { + desc string + dashboardID string + userID string + err error + }{ + { + desc: "retrieve existing dashboard", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + err: nil, + }, + { + desc: "retrieve non-existing dashboard", + dashboardID: generateUUID(t), + userID: generateUUID(t), + err: postgres.ErrNotFound, + }, + { + desc: "retrieve existing dashboard with malformed id", + dashboardID: strings.Repeat("a", 37), + userID: dashboard.CreatedBy, + err: postgres.ErrNotFound, + }, + { + desc: "retrieve existing dashboard with malformed created by", + dashboardID: dashboard.ID, + userID: strings.Repeat("a", 37), + err: postgres.ErrNotFound, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + dashboard, err := repo.Retrieve(context.Background(), tc.dashboardID, tc.userID) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error: %s to contain: %s", err, tc.err)) + if err == nil { + assert.Equal(t, dashboard.ID, tc.dashboardID) + assert.Equal(t, dashboard.CreatedBy, tc.userID) + } + }) + } +} + +func TestRetrieveAll(t *testing.T) { + t.Cleanup(func() { + _, err := db.Exec("DELETE FROM dashboards") + require.Nil(t, err, fmt.Sprintf("clean dashboards unexpected error: %s", err)) + }) + + createdBy := generateUUID(t) + num := 200 + var items []ui.Dashboard + now := time.Now().UTC().Truncate(time.Millisecond) + for i := 0; i < num; i++ { + dashboard := ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: createdBy, + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: now.Add(time.Duration(i) * time.Second), + } + _, err := repo.Create(context.Background(), dashboard) + require.Nil(t, err, fmt.Sprintf("create dashboard unexpected error: %s", err)) + dashboard.Layout = "" + dashboard.Metadata = "" + items = append(items, dashboard) + } + slices.Reverse(items) + + cases := []struct { + desc string + page ui.DashboardPageMeta + response ui.DashboardPage + err error + }{ + { + desc: "retrieve dashboards", + page: ui.DashboardPageMeta{ + Limit: 10, + Offset: 0, + CreatedBy: createdBy, + }, + response: ui.DashboardPage{ + Offset: 0, + Limit: 10, + Total: uint64(num), + Dashboards: items[:10], + }, + err: nil, + }, + { + desc: "retrieve dashboards with offset", + page: ui.DashboardPageMeta{ + Limit: 10, + Offset: 10, + CreatedBy: createdBy, + }, + response: ui.DashboardPage{ + Offset: 10, + Limit: 10, + Total: uint64(num), + Dashboards: items[10:20], + }, + err: nil, + }, + { + desc: "retrieve dashboards with offset out of range", + page: ui.DashboardPageMeta{ + Limit: 10, + Offset: 1000, + CreatedBy: createdBy, + }, + response: ui.DashboardPage{ + Offset: 1000, + Limit: 10, + Total: uint64(num), + Dashboards: []ui.Dashboard(nil), + }, + err: nil, + }, + { + desc: "retrieve dashboards with limit out of range", + page: ui.DashboardPageMeta{ + Limit: 1000, + Offset: 0, + CreatedBy: createdBy, + }, + response: ui.DashboardPage{ + Offset: 0, + Limit: 1000, + Total: uint64(num), + Dashboards: items, + }, + err: nil, + }, + { + desc: "retrieve dashboards with empty created by", + page: ui.DashboardPageMeta{ + Limit: 10, + Offset: 0, + }, + response: ui.DashboardPage{ + Offset: 0, + Limit: 10, + Total: 0, + Dashboards: []ui.Dashboard(nil), + }, + err: nil, + }, + { + desc: "retrieve dashboards with empty page", + page: ui.DashboardPageMeta{}, + response: ui.DashboardPage{ + Offset: 0, + Limit: 0, + Total: 0, + Dashboards: []ui.Dashboard(nil), + }, + err: nil, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + dashboards, err := repo.RetrieveAll(context.Background(), tc.page) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error: %s to contain: %s", err, tc.err)) + if err == nil { + assert.Equal(t, tc.response, dashboards) + } + }) + } +} + +func TestUpdate(t *testing.T) { + t.Cleanup(func() { + _, err := db.Exec("DELETE FROM dashboards") + require.Nil(t, err, fmt.Sprintf("clean dashboards unexpected error: %s", err)) + }) + + dashboard := ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + } + _, err := repo.Create(context.Background(), dashboard) + require.Nil(t, err, fmt.Sprintf("create dashboard unexpected error: %s", err)) + + cases := []struct { + desc string + dashboardID string + userID string + dashboard ui.DashboardReq + err error + }{ + { + desc: "update existing dashboard", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: nil, + }, + { + desc: "update existing dashboard with empty name", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: "", + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: nil, + }, + { + desc: "update existing dashboard with empty description", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: "", + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: nil, + }, + { + desc: "update existing dashboard with empty layout", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: "", + Metadata: namegen.Generate(), + }, + err: nil, + }, + { + desc: "update existing dashboard with empty metadata", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: "", + }, + err: nil, + }, + { + desc: "update existing dashboard with empty dashboard request", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{}, + err: postgres.ErrMalformedEntity, + }, + { + desc: "update non-existing dashboard", + dashboardID: generateUUID(t), + userID: generateUUID(t), + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: postgres.ErrNotFound, + }, + { + desc: "update existing dashboard with empty id", + dashboardID: "", + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: postgres.ErrNotFound, + }, + { + desc: "update existing dashboard with empty created by", + dashboardID: dashboard.ID, + userID: "", + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: postgres.ErrNotFound, + }, + { + desc: "update existing dashboard with malformed id", + dashboardID: strings.Repeat("a", 37), + userID: dashboard.CreatedBy, + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: postgres.ErrNotFound, + }, + { + desc: "update existing dashboard with malformed created by", + dashboardID: dashboard.ID, + userID: strings.Repeat("a", 37), + dashboard: ui.DashboardReq{ + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + }, + err: postgres.ErrNotFound, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := repo.Update(context.Background(), tc.dashboardID, tc.userID, tc.dashboard) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error: %s to contain: %s", err, tc.err)) + if err == nil { + rDashboard, err := repo.Retrieve(context.Background(), tc.dashboardID, tc.userID) + require.Nil(t, err, fmt.Sprintf("retrieve dashboard unexpected error: %s", err)) + if tc.dashboard.Name != "" { + assert.Equal(t, tc.dashboard.Name, rDashboard.Name) + } + if tc.dashboard.Description != "" { + assert.Equal(t, tc.dashboard.Description, rDashboard.Description) + } + if tc.dashboard.Layout != "" { + assert.Equal(t, tc.dashboard.Layout, rDashboard.Layout) + } + if tc.dashboard.Metadata != "" { + assert.Equal(t, tc.dashboard.Metadata, rDashboard.Metadata) + } + } + }) + } +} + +func TestDelete(t *testing.T) { + t.Cleanup(func() { + _, err := db.Exec("DELETE FROM dashboards") + require.Nil(t, err, fmt.Sprintf("clean dashboards unexpected error: %s", err)) + }) + + dashboard := ui.Dashboard{ + ID: generateUUID(t), + CreatedBy: generateUUID(t), + Name: namegen.Generate(), + Description: namegen.Generate(), + Layout: namegen.Generate(), + Metadata: namegen.Generate(), + CreatedAt: time.Now().UTC().Truncate(time.Millisecond), + } + _, err := repo.Create(context.Background(), dashboard) + require.Nil(t, err, fmt.Sprintf("create dashboard unexpected error: %s", err)) + + cases := []struct { + desc string + dashboardID string + userID string + err error + }{ + { + desc: "delete existing dashboard", + dashboardID: dashboard.ID, + userID: dashboard.CreatedBy, + err: nil, + }, + { + desc: "delete non-existing dashboard", + dashboardID: generateUUID(t), + userID: generateUUID(t), + err: postgres.ErrNotFound, + }, + { + desc: "delete existing dashboard with empty id", + dashboardID: "", + userID: dashboard.CreatedBy, + err: postgres.ErrNotFound, + }, + { + desc: "delete existing dashboard with empty created by", + dashboardID: dashboard.ID, + userID: "", + err: postgres.ErrNotFound, + }, + { + desc: "delete existing dashboard with malformed id", + dashboardID: strings.Repeat("a", 37), + userID: dashboard.CreatedBy, + err: postgres.ErrNotFound, + }, + { + desc: "delete existing dashboard with malformed created by", + dashboardID: dashboard.ID, + userID: strings.Repeat("a", 37), + err: postgres.ErrNotFound, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + err := repo.Delete(context.Background(), tc.dashboardID, tc.userID) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error: %s to contain: %s", err, tc.err)) + }) + } +} + +func generateUUID(t *testing.T) string { + idProvider := uuid.New() + uuid, err := idProvider.ID() + require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err)) + return uuid +} diff --git a/postgres/errors.go b/postgres/errors.go index d06c1fb6f..bb3e6e145 100644 --- a/postgres/errors.go +++ b/postgres/errors.go @@ -4,8 +4,8 @@ package postgres import ( + "github.com/absmach/magistrala/pkg/errors" "github.com/jackc/pgx/v5/pgconn" - "github.com/pkg/errors" ) // Postgres error codes: @@ -34,13 +34,13 @@ func HandleError(err, wrapper error) error { if ok { switch pqErr.Code { case errDuplicate: - return errors.Wrap(err, ErrConflict.Error()) + return errors.Wrap(ErrConflict, err) case errInvalid, errInvalidChar, errTruncation, errUntranslatable: - return errors.Wrap(err, ErrMalformedEntity.Error()) + return errors.Wrap(ErrMalformedEntity, err) case errFK: - return errors.Wrap(err, ErrCreateEntity.Error()) + return errors.Wrap(ErrCreateEntity, err) } } - return errors.Wrap(err, wrapper.Error()) + return errors.Wrap(wrapper, err) } diff --git a/postgres/init.go b/postgres/init.go index 20e130a2d..05db3a606 100644 --- a/postgres/init.go +++ b/postgres/init.go @@ -15,9 +15,9 @@ func Migration() *migrate.MemoryMigrationSource { Id: "dashboard_01", Up: []string{ `CREATE TABLE IF NOT EXISTS dashboards ( - id VARCHAR(36) NOT NULL, - created_by VARCHAR(36) NOT NULL, - name VARCHAR(255) NOT NULL, + id VARCHAR(36) NOT NULL CHECK (id <> ''), + created_by VARCHAR(36) NOT NULL CHECK (created_by <> ''), + name VARCHAR(255) NOT NULL CHECK (name <> ''), description TEXT, layout JSONB, metadata JSONB, diff --git a/postgres/setup_test.go b/postgres/setup_test.go index 6c393992f..72bd8fc47 100644 --- a/postgres/setup_test.go +++ b/postgres/setup_test.go @@ -2,3 +2,89 @@ // SPDX-License-Identifier: Apache-2.0 package postgres_test + +import ( + "database/sql" + "fmt" + "log" + "os" + "testing" + "time" + + "github.com/absmach/magistrala-ui/internal/postgres" + dpostgres "github.com/absmach/magistrala-ui/postgres" + "github.com/absmach/magistrala-ui/ui" + "github.com/jmoiron/sqlx" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" +) + +var ( + db *sqlx.DB + repo ui.DashboardRepository +) + +func TestMain(m *testing.M) { + pool, err := dockertest.NewPool("") + if err != nil { + log.Fatalf("Could not connect to docker: %s", err) + } + + container, err := pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "postgres", + Tag: "16.1-alpine", + Env: []string{ + "POSTGRES_USER=test", + "POSTGRES_PASSWORD=test", + "POSTGRES_DB=test", + "listen_addresses = '*'", + }, + }, func(config *docker.HostConfig) { + config.AutoRemove = true + config.RestartPolicy = docker.RestartPolicy{Name: "no"} + }) + if err != nil { + log.Fatalf("Could not start container: %s", err) + } + + port := container.GetPort("5432/tcp") + + pool.MaxWait = 120 * time.Second + if err := pool.Retry(func() error { + url := fmt.Sprintf("host=localhost port=%s user=test dbname=test password=test sslmode=disable", port) + db, err := sql.Open("pgx", url) + if err != nil { + return err + } + return db.Ping() + }); err != nil { + log.Fatalf("Could not connect to docker: %s", err) + } + + dbConfig := postgres.Config{ + Host: "localhost", + Port: port, + User: "test", + Pass: "test", + Name: "test", + SSLMode: "disable", + SSLCert: "", + SSLKey: "", + SSLRootCert: "", + } + + if db, err = postgres.Setup(dbConfig, *dpostgres.Migration()); err != nil { + log.Fatalf("Could not setup test DB connection: %s", err) + } + + repo = dpostgres.NewRepository(db) + + code := m.Run() + + db.Close() + if err := pool.Purge(container); err != nil { + log.Fatalf("Could not purge container: %s", err) + } + + os.Exit(code) +}