diff --git a/Makefile b/Makefile index 7f0c5321d..a02bdf8dd 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,7 @@ protobuild: @protoc-go-inject-tag -input=./internal/scheduler/job/store/job.pb.go @protoc-go-inject-tag -input=./internal/credential/store/credential.pb.go @protoc-go-inject-tag -input=./internal/credential/vault/store/vault.pb.go + @protoc-go-inject-tag -input=./internal/servers/servers.pb.go # these protos, services and openapi artifacts are purely for testing purposes @protoc-go-inject-tag -input=./internal/gen/testing/event/event.pb.go diff --git a/go.mod b/go.mod index b2353a82f..e62f65e4f 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,10 @@ replace github.com/hashicorp/boundary/api => ./api replace github.com/hashicorp/boundary/sdk => ./sdk +// tmp use of local clone as we understand any required upstream PRs to +// compatibility. +replace gorm.io/gorm => github.com/hashicorp/gorm v0.0.2 + require ( github.com/armon/go-metrics v0.3.9 github.com/bufbuild/buf v0.37.0 @@ -45,10 +49,11 @@ require ( github.com/hashicorp/go-uuid v1.0.2 github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/vault/api v1.1.1 + github.com/hashicorp/vault/sdk v0.2.1 github.com/iancoleman/strcase v0.2.0 + github.com/jackc/pgconn v1.10.0 github.com/jefferai/keyring v1.1.7-0.20210105022822-8749b3d9ce79 - github.com/jinzhu/gorm v1.9.16 - github.com/jinzhu/now v1.1.1 // indirect + github.com/jinzhu/gorm v1.9.12 github.com/json-iterator/go v1.1.10 // indirect github.com/kr/pretty v0.3.0 github.com/kr/text v0.2.0 @@ -81,6 +86,8 @@ require ( google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 // indirect + gorm.io/driver/postgres v1.1.0 + gorm.io/gorm v1.21.14 mvdan.cc/gofumpt v0.1.1 nhooyr.io/websocket v1.8.7 ) diff --git a/go.sum b/go.sum index d145070bd..625890ad7 100644 --- a/go.sum +++ b/go.sum @@ -76,12 +76,14 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -94,7 +96,10 @@ github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61 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/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +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/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -103,9 +108,10 @@ github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2E github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190620160927-9418d7b0cd0f h1:oRD16bhpKNAanfcDDVU+J0NXqsgHIvGbbe/sy+r6Rs0= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190620160927-9418d7b0cd0f/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= @@ -120,11 +126,15 @@ github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.27 h1:9gPjZWVDSoQrBO2AvqrWObS6KAZByfEJxQoCYo4ZfK0= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -141,6 +151,9 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/bufbuild/buf v0.37.0 h1:11zJVA0D4uJVGOC9h+oOVHrKKoBgMYIqJJ0d1Xt6oeQ= github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= @@ -154,13 +167,17 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -182,9 +199,12 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ= github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= @@ -227,7 +247,12 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -245,6 +270,8 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/favadi/protoc-go-inject-tag v1.3.0 h1:JPrmsmc/uBShG85uY5xGZIa5WJ0IaNZn6LZhQR9tIQE= github.com/favadi/protoc-go-inject-tag v1.3.0/go.mod h1:SSkUBgfqw2IJ2p7NPNKWk0Idwxt/qIt2LQgFPUgRGtc= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -261,11 +288,13 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -296,9 +325,12 @@ github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= 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.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= @@ -311,6 +343,7 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2V github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -342,6 +375,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -374,6 +408,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf 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.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -390,12 +425,15 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 h1:rgxjzoDmDXw5q8HONgyHhBas4to0/XWRo/gPpJhsUNQ= @@ -404,7 +442,9 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW github.com/hashicorp/cap v0.1.1 h1:GjO4+9+H0wv/89YoEsxeVc2jIizL19r5v5l2lpaH8Kg= github.com/hashicorp/cap v0.1.1/go.mod h1:VfBvK2ULRyqsuqAnjgZl7HJ7/CGMC7ro4H5eXiZuun8= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/dawdle v0.4.0 h1:nAE+aCoAmVulgCPPPrp6oGOykjPhxEe4VUNms/mTKeA= github.com/hashicorp/dawdle v0.4.0/go.mod h1:gOBY8rFXpW4Rw39up1FIacw/1pG/fO779LfchCY3KUw= github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8 h1:/3iubtqEdLgdXB6ue+WAKvbcpn313jjL5mQvU5ByymE= @@ -496,6 +536,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/gorm v0.0.2 h1:yxEp0og8mswtQVSEnxEsU+d3QIvYDqU+P5ABAm0B9n4= +github.com/hashicorp/gorm v0.0.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -517,6 +559,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huaweicloud/golangsdk v0.0.0-20200304081349-45ec0797f2a4/go.mod h1:WQBcHRNX9shz3928lWEvstQJtAtYI7ks6XlgtRT9Tcw= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -525,30 +568,66 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= github.com/jackc/pgconn v1.3.2/go.mod h1:LvCquS3HbBKwgl7KbX9KyqEIumJAbm1UMcTvGaIf3bM= +github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= +github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= +github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= +github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= +github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs= +github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= +github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= +github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= +github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI= +github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= @@ -563,14 +642,13 @@ github.com/jefferai/keyring v1.1.7-0.20210105022822-8749b3d9ce79 h1:7opZgeTbZEBf github.com/jefferai/keyring v1.1.7-0.20210105022822-8749b3d9ce79/go.mod h1:Y6M+VPkRv4aOcVNvvSWma4aMRLY+xvPhzZX3tDmPoPY= github.com/jhump/protoreflect v1.8.1 h1:z7Ciiz3Bz37zSd485fbiTW8ABafIasyOWZI0N9EUUdo= github.com/jhump/protoreflect v1.8.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= +github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= -github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= -github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= 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/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= +github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= @@ -579,6 +657,8 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -626,10 +706,14 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.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/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -640,17 +724,19 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw= github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -705,19 +791,31 @@ github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ib github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/oligot/go-mod-upgrade v0.6.1 h1:AZnCiEAOxOMxpKZWjFWFNm/i6QjZVBozuKjuB8EzRCk= github.com/oligot/go-mod-upgrade v0.6.1/go.mod h1:5Gyau3jUXqXrGhYxGkGqrxxgR90Lzd1yt/9YQp9sn1w= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 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 v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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= @@ -729,17 +827,29 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +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= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/oracle/oci-go-sdk v12.5.0+incompatible h1:pr08ECoaDKHWO9tnzJB1YqClEs7ZK1CFOez2DQocH14= github.com/oracle/oci-go-sdk v12.5.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ory/dockertest/v3 v3.6.0/go.mod h1:4ZOpj8qBUmh8fcBSVzkH2bws2s91JdGvHUqan4GHEuQ= github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSmsM= github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= +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 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -751,6 +861,7 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -760,25 +871,33 @@ github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXq github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -796,10 +915,13 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -820,19 +942,25 @@ github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4S github.com/snowflakedb/glog v0.0.0-20180824191149-f5055e6f21ce/go.mod h1:EB/w24pR5VKI60ecFnKqXzxX3dOorz1rnVicQTQrGM0= github.com/snowflakedb/gosnowflake v1.3.5/go.mod h1:13Ky+lxzIm3VqNDZJdyvu9MCGy+WgRdYFdXp96UcLZU= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= 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.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -857,6 +985,7 @@ github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchtv/twirp v7.1.0+incompatible h1:3fNSDoSPyq+fTrifIvGue9XM/tptzuhiGY83rxPVNUg= @@ -865,8 +994,10 @@ 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/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5 h1:MCfT24H3f//U5+UCrZp1/riVO3B50BovxtDiNn0XKkk= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= @@ -893,7 +1024,11 @@ github.com/zalando/go-keyring v0.1.1/go.mod h1:OIC+OZ28XbmwFxU/Rp9V7eKzZjamBJwRz github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -904,6 +1039,7 @@ go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -911,12 +1047,14 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -932,17 +1070,22 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -991,6 +1134,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1060,6 +1204,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20190129075346-302c3dd5f1cc/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= @@ -1076,12 +1221,14 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1114,6 +1261,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210916214954-140adaaadfaf h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI= golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1123,9 +1271,11 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1133,6 +1283,7 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1164,6 +1315,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1201,6 +1353,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1220,6 +1373,7 @@ google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1233,6 +1387,7 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1267,10 +1422,14 @@ google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 h1:3V2dxSZpz4zozWWUq36vUxXEKnSYitEH2LdsAx+RUmg= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -1314,9 +1473,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= 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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -1333,6 +1494,7 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1348,10 +1510,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.1.0 h1:afBljg7PtJ5lA6YUWluV2+xovIPhS+YiInuL3kUjrbk= +gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= 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 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +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= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1379,3 +1544,5 @@ nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/internal/auth/db_test.go b/internal/auth/db_test.go index ad20ca967..3a63e1491 100644 --- a/internal/auth/db_test.go +++ b/internal/auth/db_test.go @@ -2,6 +2,7 @@ package auth import ( "context" + "database/sql" "testing" "github.com/hashicorp/boundary/internal/db" @@ -23,7 +24,7 @@ create table if not exists test_auth_method ( insert into test_auth_method (public_id, scope_id) values - ($1, $2); + (@public_id, @scoped_id); ` addTriggers = ` create trigger @@ -33,10 +34,10 @@ insert on test_auth_method for each row execute procedure insert_auth_method_subtype(); ` baseTableQuery = ` -select count(*) from auth_method where public_id = $1; +select count(*) from auth_method where public_id = @public_id ` testTableQuery = ` -select count(*) from test_auth_method where public_id = $1; +select count(*) from test_auth_method where public_id = @public_id ` ) @@ -55,7 +56,7 @@ select count(*) from test_auth_method where public_id = $1; org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) id := "l1Ocw0TpHn800CekIxIXlmQqRDgFDfYl" - inserted, err := rw.Exec(ctx, insert, []interface{}{id, org.GetPublicId()}) + inserted, err := rw.Exec(ctx, insert, []interface{}{sql.Named("public_id", id), sql.Named("scoped_id", org.GetPublicId())}) require.NoError(err) require.Equal(1, inserted) @@ -63,7 +64,7 @@ select count(*) from test_auth_method where public_id = $1; Count int } var count c - rows, err := rw.Query(ctx, baseTableQuery, []interface{}{id}) + rows, err := rw.Query(ctx, baseTableQuery, []interface{}{sql.Named("public_id", id)}) require.NoError(err) defer rows.Close() for rows.Next() { @@ -73,7 +74,7 @@ select count(*) from test_auth_method where public_id = $1; assert.Equal(1, count.Count) count.Count = 0 - rows, err = rw.Query(ctx, testTableQuery, []interface{}{id}) + rows, err = rw.Query(ctx, testTableQuery, []interface{}{sql.Named("public_id", id)}) require.NoError(err) defer rows.Close() for rows.Next() { @@ -96,7 +97,7 @@ create table if not exists test_auth_account ( insert into test_auth_account (public_id, auth_method_id) values - ($1, $2); + (?, ?); ` addTriggers = ` create trigger @@ -106,16 +107,16 @@ insert on test_auth_account for each row execute procedure insert_auth_account_subtype(); ` baseTableQuery = ` -select count(*) from auth_account where public_id = $1; +select count(*) from auth_account where public_id = ?; ` testTableQuery = ` -select count(*) from test_auth_account where public_id = $1; +select count(*) from test_auth_account where public_id = ?; ` insertAuthMethod = ` insert into auth_method (public_id, scope_id) values - ($1, $2); + (?, ?); ` ) diff --git a/internal/auth/oidc/repository_account_test.go b/internal/auth/oidc/repository_account_test.go index 443462d33..11a22ac64 100644 --- a/internal/auth/oidc/repository_account_test.go +++ b/internal/auth/oidc/repository_account_test.go @@ -1160,7 +1160,9 @@ func TestRepository_UpdateAccount(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.AuthMethodId, got.AuthMethodId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/auth/oidc/repository_auth_method.go b/internal/auth/oidc/repository_auth_method.go index 3b3e3e879..da8dbb569 100644 --- a/internal/auth/oidc/repository_auth_method.go +++ b/internal/auth/oidc/repository_auth_method.go @@ -2,6 +2,7 @@ package oidc import ( "context" + "database/sql" "encoding/json" "fmt" "net/url" @@ -73,7 +74,12 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC } columns := []string{"public_id", "auth_method_id", "issuer", "subject"} - values := []interface{}{pubId, am.PublicId, iss, sub} + values := []interface{}{ + sql.Named("1", pubId), + sql.Named("2", am.PublicId), + sql.Named("3", iss), + sql.Named("4", sub), + } var conflictClauses, fieldMasks, nullMasks []string { @@ -81,8 +87,8 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC if err != nil { return nil, errors.Wrap(ctx, err, op) } - columns, values = append(columns, "token_claims"), append(values, string(marshaledTokenClaims)) - conflictClauses = append(conflictClauses, fmt.Sprintf("token_claims = $%d", len(values))) + columns, values = append(columns, "token_claims"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), string(marshaledTokenClaims))) + conflictClauses = append(conflictClauses, fmt.Sprintf("token_claims = @%d", len(values))) fieldMasks = append(fieldMasks, TokenClaimsField) } { @@ -90,8 +96,8 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC if err != nil { return nil, errors.Wrap(ctx, err, op) } - columns, values = append(columns, "userinfo_claims"), append(values, string(marshaledAccessTokenClaims)) - conflictClauses = append(conflictClauses, fmt.Sprintf("userinfo_claims = $%d", len(values))) + columns, values = append(columns, "userinfo_claims"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), string(marshaledAccessTokenClaims))) + conflictClauses = append(conflictClauses, fmt.Sprintf("userinfo_claims = @%d", len(values))) fieldMasks = append(fieldMasks, UserinfoClaimsField) } @@ -108,14 +114,14 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC switch { case AccessTokenClaims[fromName] != nil: foundName = AccessTokenClaims[fromName] - columns, values = append(columns, "full_name"), append(values, foundName) + columns, values = append(columns, "full_name"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), foundName)) case IdTokenClaims[fromName] != nil: foundName = IdTokenClaims[fromName] - columns, values = append(columns, "full_name"), append(values, foundName) + columns, values = append(columns, "full_name"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), foundName)) } if foundName != nil { acctForOplog.FullName = foundName.(string) - conflictClauses = append(conflictClauses, fmt.Sprintf("full_name = $%d", len(values))) + conflictClauses = append(conflictClauses, fmt.Sprintf("full_name = @%d", len(values))) fieldMasks = append(fieldMasks, NameField) } else { conflictClauses = append(conflictClauses, "full_name = NULL") @@ -126,14 +132,14 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC switch { case AccessTokenClaims[fromEmail] != nil: foundEmail = AccessTokenClaims[fromEmail] - columns, values = append(columns, "email"), append(values, foundEmail) + columns, values = append(columns, "email"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), foundEmail)) case IdTokenClaims[fromEmail] != nil: foundEmail = IdTokenClaims[fromEmail] - columns, values = append(columns, "email"), append(values, foundEmail) + columns, values = append(columns, "email"), append(values, sql.Named(fmt.Sprintf("%d", len(values)+1), foundEmail)) } if foundEmail != nil { acctForOplog.Email = foundEmail.(string) - conflictClauses = append(conflictClauses, fmt.Sprintf("email = $%d", len(values))) + conflictClauses = append(conflictClauses, fmt.Sprintf("email = @%d", len(values))) fieldMasks = append(fieldMasks, "Email") } else { conflictClauses = append(conflictClauses, "email = NULL") @@ -142,7 +148,7 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC placeHolders := make([]string, 0, len(columns)) for colNum := range columns { - placeHolders = append(placeHolders, fmt.Sprintf("$%d", colNum+1)) + placeHolders = append(placeHolders, fmt.Sprintf("@%d", colNum+1)) } query := fmt.Sprintf(acctUpsertQuery, strings.Join(columns, ", "), strings.Join(placeHolders, ", "), strings.Join(conflictClauses, ", ")) diff --git a/internal/auth/oidc/repository_managed_group_test.go b/internal/auth/oidc/repository_managed_group_test.go index bf8d88a6b..e7600db3a 100644 --- a/internal/auth/oidc/repository_managed_group_test.go +++ b/internal/auth/oidc/repository_managed_group_test.go @@ -952,7 +952,9 @@ func TestRepository_UpdateManagedGroup(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.AuthMethodId, got.AuthMethodId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/auth/oidc/testing.go b/internal/auth/oidc/testing.go index 2548cc975..4fc07d8fb 100644 --- a/internal/auth/oidc/testing.go +++ b/internal/auth/oidc/testing.go @@ -29,9 +29,9 @@ import ( "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/cap/oidc" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/gorm" ) const TestFakeManagedGroupFilter = `"/foo" == "bar"` diff --git a/internal/auth/password/account.go b/internal/auth/password/account.go index c4ef1ca1d..5aefb08c2 100644 --- a/internal/auth/password/account.go +++ b/internal/auth/password/account.go @@ -14,7 +14,7 @@ type Account struct { // CredentialId is included when Authenticate or ChangePassword is // called. A new CredentialId is generated when a password is changed. - CredentialId string `gorm:"-"` + CredentialId string `gorm:"->"` } func allocAccount() *Account { diff --git a/internal/auth/password/argon2_test.go b/internal/auth/password/argon2_test.go index a970e0345..0a81f2bc5 100644 --- a/internal/auth/password/argon2_test.go +++ b/internal/auth/password/argon2_test.go @@ -8,9 +8,9 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/iam" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestArgon2Configuration_New(t *testing.T) { diff --git a/internal/auth/password/query.go b/internal/auth/password/query.go index 5bfbae9be..737f64b70 100644 --- a/internal/auth/password/query.go +++ b/internal/auth/password/query.go @@ -25,8 +25,8 @@ select acct.name, -- Account.Name auth_password_argon2_conf conf, auth_password_account acct, auth_password_method meth - where acct.auth_method_id = $1 - and acct.login_name = $2 + where acct.auth_method_id = @auth_method_id + and acct.login_name = @login_name and cred.password_conf_id = conf.private_id and cred.password_account_id = acct.public_id and acct.auth_method_id = meth.public_id ; @@ -38,7 +38,7 @@ select * in ( select auth_method_id from auth_password_account - where public_id = $1 + where public_id = @public_id ); ` ) diff --git a/internal/auth/password/repository_account_test.go b/internal/auth/password/repository_account_test.go index 0040cd720..031d5efb3 100644 --- a/internal/auth/password/repository_account_test.go +++ b/internal/auth/password/repository_account_test.go @@ -949,7 +949,9 @@ func TestRepository_UpdateAccount(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.AuthMethodId, got.AuthMethodId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/auth/password/repository_authmethod_test.go b/internal/auth/password/repository_authmethod_test.go index e43a8e9cb..33783b0e6 100644 --- a/internal/auth/password/repository_authmethod_test.go +++ b/internal/auth/password/repository_authmethod_test.go @@ -769,7 +769,9 @@ func TestRepository_UpdateAuthMethod(t *testing.T) { require.NoError(err) assert.Empty(cmp.Diff(updatedAM, foundAuthMethod, protocmp.Transform())) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if amToUpdate.Name == "" && contains(tt.args.fieldMaskPaths, "name") { dbassert.IsNull(foundAuthMethod, "name") } diff --git a/internal/auth/password/repository_configuration.go b/internal/auth/password/repository_configuration.go index 8f79deed5..2cffa5841 100644 --- a/internal/auth/password/repository_configuration.go +++ b/internal/auth/password/repository_configuration.go @@ -2,6 +2,7 @@ package password import ( "context" + "database/sql" "github.com/hashicorp/boundary/internal/auth/password/store" "github.com/hashicorp/boundary/internal/db" @@ -143,7 +144,7 @@ func (r *Repository) currentConfigForAccount(ctx context.Context, accountId stri const op = "password.(Repository).currentConfigForAccount" var confs []currentConfig - rows, err := r.reader.Query(ctx, currentConfigForAccountQuery, []interface{}{accountId}) + rows, err := r.reader.Query(ctx, currentConfigForAccountQuery, []interface{}{sql.Named("public_id", accountId)}) if err != nil { return nil, errors.Wrap(ctx, err, op) } diff --git a/internal/auth/password/repository_password.go b/internal/auth/password/repository_password.go index 69ecfced0..1ebbc18a4 100644 --- a/internal/auth/password/repository_password.go +++ b/internal/auth/password/repository_password.go @@ -3,6 +3,7 @@ package password import ( "context" "crypto/subtle" + "database/sql" "fmt" "github.com/hashicorp/boundary/internal/db" @@ -213,7 +214,8 @@ func (r *Repository) authenticate(ctx context.Context, scopeId, authMethodId, lo const op = "password.(Repository).authenticate" var accts []authAccount - rows, err := r.reader.Query(ctx, authenticateQuery, []interface{}{authMethodId, loginName}) + rows, err := r.reader.Query(ctx, authenticateQuery, []interface{}{sql.Named("auth_method_id", authMethodId), sql.Named("login_name", loginName)}) + if err != nil { return nil, errors.Wrap(ctx, err, op) } diff --git a/internal/auth/password/store/password.pb.go b/internal/auth/password/store/password.pb.go index 992547d7d..7a52921a8 100644 --- a/internal/auth/password/store/password.pb.go +++ b/internal/auth/password/store/password.pb.go @@ -56,8 +56,8 @@ type AuthMethod struct { MinPasswordLength uint32 `protobuf:"varint,10,opt,name=min_password_length,json=minPasswordLength,proto3" json:"min_password_length,omitempty" gorm:"default:null"` // is_primary_auth_method is a read-only output field which indicates if the // auth method is set as the scope's primary auth method. - // @inject_tag: `gorm:"-"` - IsPrimaryAuthMethod bool `protobuf:"varint,20,opt,name=is_primary_auth_method,json=isPrimaryAuthMethod,proto3" json:"is_primary_auth_method,omitempty" gorm:"-"` + // @inject_tag: `gorm:"->"` + IsPrimaryAuthMethod bool `protobuf:"varint,20,opt,name=is_primary_auth_method,json=isPrimaryAuthMethod,proto3" json:"is_primary_auth_method,omitempty" gorm:"->"` } func (x *AuthMethod) Reset() { diff --git a/internal/auth/password/testing.go b/internal/auth/password/testing.go index 8b71bda3f..1f6995403 100644 --- a/internal/auth/password/testing.go +++ b/internal/auth/password/testing.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/hashicorp/boundary/internal/db" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) // TestAuthMethod creates a password auth methods to the provided DB with the diff --git a/internal/authtoken/store/authtoken.pb.go b/internal/authtoken/store/authtoken.pb.go index 8a51ac5c9..53ee69e32 100644 --- a/internal/authtoken/store/authtoken.pb.go +++ b/internal/authtoken/store/authtoken.pb.go @@ -55,14 +55,14 @@ type AuthToken struct { // @inject_tag: `gorm:"default:not_null"` AuthAccountId string `protobuf:"bytes,10,opt,name=auth_account_id,json=authAccountId,proto3" json:"auth_account_id,omitempty" gorm:"default:not_null"` // scope_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" - ScopeId string `protobuf:"bytes,11,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" gorm:"-"` + // @inject_tag: gorm:"->" + ScopeId string `protobuf:"bytes,11,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" gorm:"->"` // auth_method_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" - AuthMethodId string `protobuf:"bytes,12,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty" gorm:"-"` + // @inject_tag: gorm:"->" + AuthMethodId string `protobuf:"bytes,12,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty" gorm:"->"` // iam_user_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" - IamUserId string `protobuf:"bytes,13,opt,name=iam_user_id,json=iamUserId,proto3" json:"iam_user_id,omitempty" gorm:"-"` + // @inject_tag: gorm:"->" + IamUserId string `protobuf:"bytes,13,opt,name=iam_user_id,json=iamUserId,proto3" json:"iam_user_id,omitempty" gorm:"->"` // key_id is the key ID that was used for the encryption operation. It can be // used to identify a specific version of the key needed to decrypt the value, // which is useful for caching purposes. diff --git a/internal/authtoken/testing.go b/internal/authtoken/testing.go index 5f8f5fbb4..2b95e00c4 100644 --- a/internal/authtoken/testing.go +++ b/internal/authtoken/testing.go @@ -8,8 +8,8 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestAuthToken(t *testing.T, conn *gorm.DB, kms *kms.Kms, scopeId string, opt ...Option) *AuthToken { diff --git a/internal/cmd/base/dev.go b/internal/cmd/base/dev.go index 90db26906..5db90e915 100644 --- a/internal/cmd/base/dev.go +++ b/internal/cmd/base/dev.go @@ -20,6 +20,7 @@ import ( "github.com/hashicorp/boundary/testing/dbtest" capoidc "github.com/hashicorp/cap/oidc" "github.com/hashicorp/go-multierror" + "gorm.io/gorm/logger" ) func (b *Server) CreateDevDatabase(ctx context.Context, opt ...Option) error { @@ -100,7 +101,7 @@ func (b *Server) CreateDevDatabase(ctx context.Context, opt ...Option) error { return err } - b.Database.LogMode(true) + b.Database.Config.Logger.LogMode(logger.Info) if err := b.CreateGlobalKmsKeys(ctx); err != nil { if c != nil { diff --git a/internal/cmd/base/servers.go b/internal/cmd/base/servers.go index 9f8309bdf..e9edaf369 100644 --- a/internal/cmd/base/servers.go +++ b/internal/cmd/base/servers.go @@ -37,9 +37,10 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/go-secure-stdlib/reloadutil" "github.com/hashicorp/go-secure-stdlib/strutil" - "github.com/jinzhu/gorm" "github.com/mitchellh/cli" "google.golang.org/grpc/grpclog" + "gorm.io/gorm" + "gorm.io/gorm/logger" ) const ( @@ -548,20 +549,37 @@ func (b *Server) RunShutdownFuncs() error { } func (b *Server) ConnectToDatabase(dialect string) error { - dbase, err := gorm.Open(dialect, b.DatabaseUrl) + dbType, err := db.StringToDbType(dialect) + if err != nil { + return fmt.Errorf("unable to create db object with dialect %s: %w", dialect, err) + } + dbase, err := db.Open(dbType, b.DatabaseUrl) if err != nil { return fmt.Errorf("unable to create db object with dialect %s: %w", dialect, err) } if b.DatabaseMaxOpenConnections == 1 { return fmt.Errorf("unable to create db object with dialect %s: %s", dialect, "max_open_connections must be unlimited by setting 0 or at least 2") } else { - dbase.DB().SetMaxOpenConns(b.DatabaseMaxOpenConnections) + underlyingDB, err := dbase.DB() + if err != nil { + return fmt.Errorf("unable retreive db: %w", err) + } + underlyingDB.SetMaxOpenConns(b.DatabaseMaxOpenConnections) } b.Database = dbase if os.Getenv("BOUNDARY_DISABLE_GORM_FORMATTER") == "" { - gorm.LogFormatter = db.GetGormLogFormatter(b.Logger) - b.Database.SetLogger(db.GetGormLogger(b.Logger)) + newLogger := logger.New( + db.GetGormLogger(b.Logger), + logger.Config{ + LogLevel: logger.Error, // Log level + Colorful: false, // Disable color + }, + ) + dbase = dbase.Session(&gorm.Session{Logger: newLogger}) } + + b.Database = dbase + return nil } @@ -602,7 +620,11 @@ func (b *Server) CreateGlobalKmsKeys(ctx context.Context) error { func (b *Server) DestroyDevDatabase() error { if b.Database != nil { - b.Database.Close() + underlyingDB, err := b.Database.DB() + if err != nil { + return err + } + underlyingDB.Close() } if b.DevDatabaseCleanupFunc != nil { return b.DevDatabaseCleanupFunc() diff --git a/internal/cmd/commands/database/init.go b/internal/cmd/commands/database/init.go index ac5799355..47c40cd48 100644 --- a/internal/cmd/commands/database/init.go +++ b/internal/cmd/commands/database/init.go @@ -493,7 +493,11 @@ func (c *InitCommand) ParseFlagsAndConfig(args []string) int { func (c *InitCommand) verifyOplogIsEmpty() error { const op = "database.(InitCommand).verifyOplogIsEmpty" - r := c.srv.Database.DB().QueryRowContext(c.Context, "select not exists(select 1 from oplog_entry limit 1)") + underlyingDB, err := c.srv.Database.DB() + if err != nil { + return errors.NewDeprecated(errors.Internal, op, "unable to retreive db", errors.WithWrap(err)) + } + r := underlyingDB.QueryRowContext(c.Context, "select not exists(select 1 from oplog_entry limit 1)") if r.Err() != nil { return r.Err() } diff --git a/internal/cmd/commands/server/server.go b/internal/cmd/commands/server/server.go index 1d48c0f1e..1139573a9 100644 --- a/internal/cmd/commands/server/server.go +++ b/internal/cmd/commands/server/server.go @@ -394,7 +394,12 @@ func (c *Command) Run(args []string) int { return base.CommandCliError } - sMan, err := schema.NewManager(c.Context, "postgres", c.Database.DB()) + underlyingDB, err := c.Database.DB() + if err != nil { + c.UI.Error(fmt.Errorf("Can't get db: %w.", err).Error()) + return base.CommandCliError + } + sMan, err := schema.NewManager(c.Context, "postgres", underlyingDB) if err != nil { c.UI.Error(fmt.Errorf("Can't get schema manager: %w.", err).Error()) return base.CommandCliError diff --git a/internal/credential/vault/client_certificate.go b/internal/credential/vault/client_certificate.go index 82f83e515..b368c7d72 100644 --- a/internal/credential/vault/client_certificate.go +++ b/internal/credential/vault/client_certificate.go @@ -5,6 +5,7 @@ import ( "crypto/ed25519" "crypto/hmac" "crypto/sha256" + "database/sql" "github.com/hashicorp/boundary/internal/credential/vault/store" "github.com/hashicorp/boundary/internal/db" @@ -119,11 +120,11 @@ func (c *ClientCertificate) hmacCertificateKey(ctx context.Context, cipher wrapp func (c *ClientCertificate) insertQuery() (query string, queryValues []interface{}) { query = upsertClientCertQuery queryValues = []interface{}{ - c.StoreId, - c.Certificate, - c.CtCertificateKey, - c.CertificateKeyHmac, - c.KeyId, + sql.Named("store_id", c.StoreId), + sql.Named("certificate", c.Certificate), + sql.Named("certificate_key", c.CtCertificateKey), + sql.Named("certificate_key_hmac", c.CertificateKeyHmac), + sql.Named("key_id", c.KeyId), } return } diff --git a/internal/credential/vault/credential.go b/internal/credential/vault/credential.go index 4d4f4b707..a3e9178f7 100644 --- a/internal/credential/vault/credential.go +++ b/internal/credential/vault/credential.go @@ -1,6 +1,7 @@ package vault import ( + "database/sql" "time" "github.com/hashicorp/boundary/internal/credential" @@ -118,31 +119,31 @@ func (c *Credential) oplog(op oplog.OpType) oplog.Metadata { func (c *Credential) insertQuery() (query string, queryValues []interface{}) { queryValues = []interface{}{ - c.PublicId, - c.LibraryId, - c.SessionId, - c.TokenHmac, - c.ExternalId, - c.IsRenewable, - c.Status, - "now()", + sql.Named("public_id", c.PublicId), + sql.Named("library_id", c.LibraryId), + sql.Named("session_id", c.SessionId), + sql.Named("token_hmac", c.TokenHmac), + sql.Named("external_id", c.ExternalId), + sql.Named("is_renewable", c.IsRenewable), + sql.Named("status", c.Status), + sql.Named("last_renewal_time", "now()"), } switch { case c.expiration == 0: query = insertCredentialWithInfiniteExpirationQuery default: query = insertCredentialWithExpirationQuery - queryValues = append(queryValues, int(c.expiration.Round(time.Second).Seconds())) + queryValues = append(queryValues, sql.Named("expiration_time", int(c.expiration.Round(time.Second).Seconds()))) } return } func (c *Credential) updateSessionQuery(purpose credential.Purpose) (query string, queryValues []interface{}) { queryValues = []interface{}{ - c.PublicId, - c.LibraryId, - c.SessionId, - string(purpose), + sql.Named("public_id", c.PublicId), + sql.Named("library_id", c.LibraryId), + sql.Named("session_id", c.SessionId), + sql.Named("purpose", string(purpose)), } query = updateSessionCredentialQuery return diff --git a/internal/credential/vault/credential_test.go b/internal/credential/vault/credential_test.go index 280598dc5..07b6e795b 100644 --- a/internal/credential/vault/credential_test.go +++ b/internal/credential/vault/credential_test.go @@ -132,7 +132,7 @@ func TestCredential_New(t *testing.T) { SessionId: session.GetPublicId(), ExternalId: "some/vault/credential", TokenHmac: token.GetTokenHmac(), - ExpirationTime: timestamp.New(db.PositiveInfinityTS), + ExpirationTime: timestamp.New(timestamp.PositiveInfinityTS), Status: string(ActiveCredential), }, }, diff --git a/internal/credential/vault/jobs_test.go b/internal/credential/vault/jobs_test.go index 3dfc1c24c..35f963c98 100644 --- a/internal/credential/vault/jobs_test.go +++ b/internal/credential/vault/jobs_test.go @@ -2,6 +2,7 @@ package vault import ( "context" + "database/sql" "path" "strings" "testing" @@ -18,9 +19,9 @@ import ( "github.com/hashicorp/boundary/internal/target" wrapping "github.com/hashicorp/go-kms-wrapping" vault "github.com/hashicorp/vault/api" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) const testUpdateTokenStatusExpirationQuery = ` @@ -55,23 +56,23 @@ func testVaultToken(t *testing.T, query := insertTokenQuery queryValues := []interface{}{ - inToken.TokenHmac, - inToken.CtToken, - inToken.StoreId, - inToken.KeyId, - inToken.Status, + sql.Named("1", inToken.TokenHmac), + sql.Named("2", inToken.CtToken), + sql.Named("3", inToken.StoreId), + sql.Named("4", inToken.KeyId), + sql.Named("5", inToken.Status), } expire := int(expiration.Seconds()) if expire < 0 { // last_renewal_time must be before expiration_time, if we are testing a expiration // in the past set last_renewal_time to 1 second before that query = strings.Replace(query, - "$6, -- last_renewal_time", - "wt_add_seconds_to_now($6), -- last_renewal_time", + "@6, -- last_renewal_time", + "wt_add_seconds_to_now(@6), -- last_renewal_time", -1) - queryValues = append(queryValues, expire-1, expire) + queryValues = append(queryValues, expire-1, sql.Named("6", expire)) } else { - queryValues = append(queryValues, "now()", expire) + queryValues = append(queryValues, sql.Named("6", "now()"), sql.Named("7", expire)) } numRows, err := rw.Exec(context.Background(), query, queryValues) @@ -114,25 +115,25 @@ func testVaultCred(t *testing.T, query := insertCredentialWithExpirationQuery queryValues := []interface{}{ - id, - cl.GetPublicId(), - sess.GetPublicId(), - token.GetTokenHmac(), - secret.LeaseID, - true, - status, + sql.Named("public_id", id), + sql.Named("library_id", cl.GetPublicId()), + sql.Named("session_id", sess.GetPublicId()), + sql.Named("token_hmac", token.GetTokenHmac()), + sql.Named("external_id", secret.LeaseID), + sql.Named("is_renewable", true), + sql.Named("status", status), } expire := int(expiration.Seconds()) if expire < 0 { // last_renewal_time must be before expiration_time, if we are testing a expiration // in the past set last_renewal_time to 1 second before that query = strings.Replace(query, - "$8, -- last_renewal_time", - "wt_add_seconds_to_now($8), -- last_renewal_time", + "@last_renewal_time, -- last_renewal_time", + "wt_add_seconds_to_now(@last_renewal_time), -- last_renewal_time", -1) - queryValues = append(queryValues, expire-1, expire) + queryValues = append(queryValues, sql.Named("last_renewal_time", expire-1), sql.Named("expiration_time", expire)) } else { - queryValues = append(queryValues, "now()", expire) + queryValues = append(queryValues, sql.Named("last_renewal_time", "now()"), sql.Named("expiration_time", expire)) } numRows, err := rw.Exec(context.Background(), query, queryValues) diff --git a/internal/credential/vault/private_library.go b/internal/credential/vault/private_library.go index af52c4555..12a27f203 100644 --- a/internal/credential/vault/private_library.go +++ b/internal/credential/vault/private_library.go @@ -2,6 +2,7 @@ package vault import ( "context" + "database/sql" "fmt" "strings" @@ -170,14 +171,17 @@ func (r *Repository) getPrivateLibraries(ctx context.Context, requests []credent } libIds := mapper.libIds() - - inClause := strings.TrimSuffix(strings.Repeat("?,", len(libIds)), ",") + var inClauseSpots []string + for i := 1; i < len(libIds)+1; i++ { + inClauseSpots = append(inClauseSpots, fmt.Sprintf("@%d", i)) + } + inClause := strings.Join(inClauseSpots, ",") query := fmt.Sprintf(selectPrivateLibrariesQuery, inClause) var params []interface{} - for _, v := range libIds { - params = append(params, v) + for idx, v := range libIds { + params = append(params, sql.Named(fmt.Sprintf("%d", idx+1), v)) } rows, err := r.reader.Query(ctx, query, params) if err != nil { diff --git a/internal/credential/vault/query.go b/internal/credential/vault/query.go index 0a783b488..3346a71af 100644 --- a/internal/credential/vault/query.go +++ b/internal/credential/vault/query.go @@ -11,13 +11,13 @@ insert into credential_vault_token ( last_renewal_time, -- $6 expiration_time -- $7 ) values ( - $1, -- token_hmac - $2, -- token - $3, -- store_id - $4, -- key_id - $5, -- status - $6, -- last_renewal_time - wt_add_seconds_to_now($7) -- expiration_time + @1, -- token_hmac + @2, -- token + @3, -- store_id + @4, -- key_id + @5, -- status + @6, -- last_renewal_time + wt_add_seconds_to_now(@7) -- expiration_time ); ` @@ -33,15 +33,15 @@ insert into credential_vault_credential ( last_renewal_time, -- $8 expiration_time -- $9 ) values ( - $1, -- public_id - $2, -- library_id - $3, -- session_id - $4, -- token_hmac - $5, -- external_id - $6, -- is_renewable - $7, -- status - $8, -- last_renewal_time - wt_add_seconds_to_now($9) -- expiration_time + @public_id, -- public_id + @library_id, -- library_id + @session_id, -- session_id + @token_hmac, -- token_hmac + @external_id, -- external_id + @is_renewable, -- is_renewable + @status, -- status + @last_renewal_time, -- last_renewal_time + wt_add_seconds_to_now(@expiration_time) -- expiration_time ); ` @@ -57,14 +57,14 @@ insert into credential_vault_credential ( last_renewal_time, -- $8 expiration_time -- infinity ) values ( - $1, -- public_id - $2, -- library_id - $3, -- session_id - $4, -- token_hmac - $5, -- external_id - $6, -- is_renewable - $7, -- status - $8, -- last_renewal_time + @public_id, -- public_id + @library_id, -- library_id + @session_id, -- session_id + @token_hmac, -- token_hmac + @external_id, -- external_id + @is_renewable, -- is_renewable + @status, -- status + @last_renewal_time, -- last_renewal_time 'infinity' -- expiration_time ); ` @@ -73,7 +73,7 @@ insert into credential_vault_credential ( insert into credential_vault_client_certificate (store_id, certificate, certificate_key, certificate_key_hmac, key_id) values - ($1, $2, $3, $4, $5) + (@store_id, @certificate, @certificate_key, @certificate_key_hmac, @key_id) on conflict (store_id) do update set certificate = excluded.certificate, certificate_key = excluded.certificate_key, @@ -84,7 +84,7 @@ returning *; deleteClientCertQuery = ` delete from credential_vault_client_certificate - where store_id = $1; + where store_id = ?; ` selectPrivateLibrariesQuery = ` @@ -95,10 +95,10 @@ select * updateSessionCredentialQuery = ` update session_credential_dynamic - set credential_id = $1 - where library_id = $2 - and session_id = $3 - and credential_purpose = $4 + set credential_id = @public_id + where library_id = @library_id + and session_id = @session_id + and credential_purpose = @purpose and credential_id is null returning *; ` @@ -129,7 +129,7 @@ select extract(epoch from (last_renewal_time + (expiration_time - last_renewal_t revokeCredentialsQuery = ` update credential_vault_credential set status = 'revoke' - where session_id = $1 + where session_id = ? and status = 'active'; ` @@ -166,7 +166,7 @@ update credential_vault_credential softDeleteStoreQuery = ` update credential_vault_store set delete_time = now() - where public_id = $1 + where public_id = ? and delete_time is null returning *; ` diff --git a/internal/credential/vault/repository_credential_library_test.go b/internal/credential/vault/repository_credential_library_test.go index ba9dbe52f..6a1e9320f 100644 --- a/internal/credential/vault/repository_credential_library_test.go +++ b/internal/credential/vault/repository_credential_library_test.go @@ -795,7 +795,9 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.StoreId, got.StoreId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/credential/vault/repository_credential_store_test.go b/internal/credential/vault/repository_credential_store_test.go index 3ce3530fb..e44b0bde7 100644 --- a/internal/credential/vault/repository_credential_store_test.go +++ b/internal/credential/vault/repository_credential_store_test.go @@ -20,10 +20,10 @@ import ( "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/scheduler" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/testing/protocmp" + "gorm.io/gorm" ) func TestRepository_CreateCredentialStoreResource(t *testing.T) { @@ -234,6 +234,7 @@ func TestRepository_LookupCredentialStore(t *testing.T) { csWithoutClientCert := stores[1] ccert := allocClientCertificate() + ccert.StoreId = csWithoutClientCert.GetPublicId() rows, err := rw.Delete(context.Background(), ccert, db.WithWhere("store_id = ?", csWithoutClientCert.GetPublicId())) require.NoError(t, err) require.Equal(t, 1, rows) @@ -755,7 +756,9 @@ func TestRepository_UpdateCredentialStore_Attributes(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.ScopeId, got.ScopeId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") } else { @@ -884,8 +887,9 @@ func TestRepository_UpdateCredentialStore_Attributes(t *testing.T) { assert.Equal(1, gotCount2, "count of updated records") require.NotNil(got2) assert.Nil(got2.CaCert) - - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) dbassert.IsNull(got2, "CaCert") }) @@ -1306,7 +1310,7 @@ func TestRepository_DeleteCredentialStore(t *testing.T) { const query = ` update credential_vault_token set status = 'revoked' - where store_id = $1 + where store_id = ? and status = 'current'; ` t.Helper() @@ -1328,7 +1332,7 @@ update credential_vault_token const query = ` update credential_vault_token set status = 'expired' - where store_id = $1 + where store_id = ? and status = 'current'; ` t.Helper() diff --git a/internal/credential/vault/testing.go b/internal/credential/vault/testing.go index 858e1b6ac..bc9bb2741 100644 --- a/internal/credential/vault/testing.go +++ b/internal/credential/vault/testing.go @@ -26,10 +26,9 @@ import ( "github.com/hashicorp/boundary/internal/scheduler" wrapping "github.com/hashicorp/go-kms-wrapping" vault "github.com/hashicorp/vault/api" - "github.com/jinzhu/gorm" - _ "github.com/lib/pq" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) // TestCredentialStore creates a vault credential store in the provided DB with diff --git a/internal/credential/vault/vault_token.go b/internal/credential/vault/vault_token.go index 8836f3b98..5e7321f65 100644 --- a/internal/credential/vault/vault_token.go +++ b/internal/credential/vault/vault_token.go @@ -4,6 +4,7 @@ import ( "context" "crypto/hmac" "crypto/sha256" + "database/sql" "time" "github.com/hashicorp/boundary/internal/credential/vault/store" @@ -139,13 +140,13 @@ func (t *Token) insertQuery() (query string, queryValues []interface{}) { exp := int(t.expiration.Round(time.Second).Seconds()) queryValues = []interface{}{ - t.TokenHmac, - t.CtToken, - t.StoreId, - t.KeyId, - t.Status, - "now()", - exp, + sql.Named("1", t.TokenHmac), + sql.Named("2", t.CtToken), + sql.Named("3", t.StoreId), + sql.Named("4", t.KeyId), + sql.Named("5", t.Status), + sql.Named("6", "now()"), + sql.Named("7", exp), } return } diff --git a/internal/db/README.md b/internal/db/README.md index f29d1d272..120bcc162 100644 --- a/internal/db/README.md +++ b/internal/db/README.md @@ -4,7 +4,12 @@ Just some high-level usage highlights to get you started. Read the godocs for a complete list of capabilities and their documentation. ```go - conn, _ := gorm.Open("postgres", url) + dialect = postgres.New(postgres.Config{ + DSN: connectionUrl}, + ) + conn, _ := gorm.Open(dialect, &gorm.Config{ + ConvertNullToZeroValues: true, + }) // Db implements both the Reader and Writer interfaces rw := Db{Tx: conn} diff --git a/internal/db/assert/asserts_test.go b/internal/db/assert/asserts_test.go index 3e37ba93e..fff28927f 100644 --- a/internal/db/assert/asserts_test.go +++ b/internal/db/assert/asserts_test.go @@ -3,11 +3,14 @@ package dbassert import ( "testing" + "github.com/hashicorp/boundary/internal/db" dbassert "github.com/hashicorp/dbassert" gormAssert "github.com/hashicorp/dbassert/gorm" + "github.com/hashicorp/vault/sdk/helper/base62" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func Test_FieldDomain(t *testing.T) { @@ -56,23 +59,18 @@ func Test_FieldNullable(t *testing.T) { func Test_FieldIsNull(t *testing.T) { t.Parallel() - cleanup, conn, _ := dbassert.TestSetup(t, "postgres") - defer func() { - if err := cleanup(); err != nil { - t.Error(err) - } - if err := conn.Close(); err != nil { - t.Error(err) - } - }() assert := assert.New(t) - gormDb, err := gorm.Open("postgres", conn) + conn, _ := db.TestSetup(t, "postgres") + initStore(t, conn) + require := require.New(t) + underlyingDB, err := conn.DB() + require.NoError(err) assert.NoError(err) mockery := new(dbassert.MockTesting) - dbassert := New(mockery, conn) + dbassert := New(mockery, underlyingDB) v := 1 - m := gormAssert.CreateTestModel(t, gormDb, nil, &v) + m := createTestModel(t, conn, nil, &v) dbassert.IsNull(&m, "Nullable") mockery.AssertNoError(t) @@ -84,23 +82,16 @@ func Test_FieldIsNull(t *testing.T) { func Test_FieldNotNull(t *testing.T) { t.Parallel() - cleanup, conn, _ := dbassert.TestSetup(t, "postgres") - defer func() { - if err := cleanup(); err != nil { - t.Error(err) - } - if err := conn.Close(); err != nil { - t.Error(err) - } - }() - assert := assert.New(t) - gormDb, err := gorm.Open("postgres", conn) - assert.NoError(err) + conn, _ := db.TestSetup(t, "postgres") + initStore(t, conn) + require := require.New(t) + underlyingDB, err := conn.DB() + require.NoError(err) mockery := new(dbassert.MockTesting) - dbassert := New(mockery, conn) + dbassert := New(mockery, underlyingDB) v := 1 - m := gormAssert.CreateTestModel(t, gormDb, nil, &v) + m := createTestModel(t, conn, nil, &v) dbassert.NotNull(&m, "Nullable") mockery.AssertError(t) @@ -109,3 +100,54 @@ func Test_FieldNotNull(t *testing.T) { dbassert.NotNull(&m, "typeint") mockery.AssertNoError(t) } + +type testModel struct { + Id int `gorm:"primary_key"` + PublicId string + Nullable *string + TypeInt *int +} + +// TableName is required by Gorm to define the model's table name when it +// doesn't match the model's Go type name. +func (*testModel) TableName() string { return "test_table_dbasserts" } + +// CreateTestModel is a helper that creates a testModel in the DB. +func createTestModel(t dbassert.TestingT, db *gorm.DB, nullable *string, typeInt *int) *testModel { + publicId, err := base62.Random(12) + assert.NoError(t, err) + m := testModel{ + PublicId: publicId, + Nullable: nullable, + TypeInt: typeInt, + } + err = db.Create(&m).Error + assert.NoError(t, err) + return &m +} + +func initStore(t *testing.T, db *gorm.DB) { + t.Helper() + const ( + createDomainType = ` +create domain dbasserts_public_id as text +check( + length(trim(value)) > 10 +); +comment on domain dbasserts_public_id is +'dbasserts test domain type'; +` + createTable = ` +create table if not exists test_table_dbasserts ( + id bigint generated always as identity primary key, + public_id dbasserts_public_id not null, + nullable text, + type_int int +); +comment on table test_table_dbasserts is +'dbasserts test table' +` + ) + require.NoError(t, db.Exec(createDomainType).Error) + require.NoError(t, db.Exec(createTable).Error) +} diff --git a/internal/db/common/update.go b/internal/db/common/update.go index fd40ee2ac..71b11e3fd 100644 --- a/internal/db/common/update.go +++ b/internal/db/common/update.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/hashicorp/boundary/internal/errors" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) // UpdateFields will create a map[string]interface of the update values to be diff --git a/internal/db/common/update_test.go b/internal/db/common/update_test.go index 41d41b3c7..4da3a16c6 100644 --- a/internal/db/common/update_test.go +++ b/internal/db/common/update_test.go @@ -6,8 +6,8 @@ import ( "github.com/hashicorp/boundary/internal/db/db_test" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" + "gorm.io/gorm" ) func Test_intersection(t *testing.T) { diff --git a/internal/db/db.go b/internal/db/db.go index f506c9845..6331a08dd 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -4,24 +4,14 @@ import ( "context" stderrors "errors" "fmt" - "math" - "time" "github.com/hashicorp/boundary/internal/observability/event" "github.com/hashicorp/go-hclog" - "github.com/jinzhu/gorm" - "github.com/lib/pq" + "github.com/jackc/pgconn" + "gorm.io/driver/postgres" + "gorm.io/gorm" ) -var ( - NegativeInfinityTS = time.Date(math.MinInt32, time.January, 1, 0, 0, 0, 0, time.UTC) - PositiveInfinityTS = time.Date(math.MaxInt32, time.December, 31, 23, 59, 59, 1e9-1, time.UTC) -) - -func init() { - pq.EnableInfinityTs(NegativeInfinityTS, PositiveInfinityTS) -} - type DbType int const ( @@ -35,11 +25,30 @@ func (db DbType) String() string { "postgres", }[db] } +func StringToDbType(dialect string) (DbType, error) { + switch dialect { + case "postgres": + return Postgres, nil + default: + return UnknownDB, fmt.Errorf("%s is an unknown dialect", dialect) + } +} // Open a database connection which is long-lived. // You need to call Close() on the returned gorm.DB func Open(dbType DbType, connectionUrl string) (*gorm.DB, error) { - db, err := gorm.Open(dbType.String(), connectionUrl) + var dialect gorm.Dialector + switch dbType { + case Postgres: + dialect = postgres.New(postgres.Config{ + DSN: connectionUrl}, + ) + default: + return nil, fmt.Errorf("unable to open %s database type", dbType) + } + db, err := gorm.Open(dialect, &gorm.Config{ + ConvertNullToZeroValues: true, + }) if err != nil { return nil, fmt.Errorf("unable to open database: %w", err) } @@ -52,7 +61,7 @@ func GetGormLogFormatter(log hclog.Logger) func(values ...interface{}) (messages return func(values ...interface{}) (messages []interface{}) { if len(values) > 2 && values[0].(string) == "log" { switch values[2].(type) { - case *pq.Error: + case *pgconn.PgError: if log.IsTrace() { event.WriteError(ctx, op, stderrors.New("error from database adapter"), event.WithInfo("error", values[2], "location", values[1])) } @@ -67,14 +76,13 @@ type gormLogger struct { logger hclog.Logger } -func (g gormLogger) Print(values ...interface{}) { - formatted := gorm.LogFormatter(values...) - if formatted == nil { - return +func (g gormLogger) Printf(msg string, values ...interface{}) { + if len(values) > 1 { + switch values[1].(type) { + case *pgconn.PgError: + g.logger.Trace("error from database adapter", "location", values[0], "error", values[1]) + } } - // Our formatter should elide anything we don't want so this should never - // happen, panic if so so we catch/fix - panic("unhandled error case") } func GetGormLogger(log hclog.Logger) gormLogger { diff --git a/internal/db/db_test.go b/internal/db/db_test.go index 7329ceb17..915da9e26 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -4,8 +4,7 @@ import ( "testing" "github.com/hashicorp/boundary/testing/dbtest" - "github.com/lib/pq" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestOpen(t *testing.T) { @@ -49,7 +48,10 @@ func TestOpen(t *testing.T) { got, err := Open(tt.args.dbType, tt.args.connectionUrl) defer func() { if err == nil { - got.Close() + sqlDB, err := got.DB() + require.NoError(t, err) + err = sqlDB.Close() + require.NoError(t, err) } }() if (err != nil) != tt.wantErr { @@ -62,9 +64,3 @@ func TestOpen(t *testing.T) { }) } } - -func TestPostgresInfinity(t *testing.T) { - assert.Panics(t, func() { - pq.EnableInfinityTs(NegativeInfinityTS, PositiveInfinityTS) - }) -} diff --git a/internal/db/domains_test.go b/internal/db/domains_test.go index be5b5b6a5..bd99618da 100644 --- a/internal/db/domains_test.go +++ b/internal/db/domains_test.go @@ -26,7 +26,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) for _, typ := range []string{"public", "private", "role", "scope"} { createTable := strings.Replace(createTableBase, "{{rep}}", typ, -1) @@ -108,7 +109,8 @@ values ($1); ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -179,7 +181,8 @@ values ($1); ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -254,7 +257,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) } @@ -320,8 +324,9 @@ set update_time = null; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() - _, err := db.Exec(createTable) + db, err := conn.DB() + require.NoError(t, err) + _, err = db.Exec(createTable) assert.NoError(err) _, err = db.Exec(addTriggers) @@ -392,8 +397,10 @@ returning public_id; conn, _ := TestSetup(t, "postgres") assert, require := assert.New(t), require.New(t) - db := conn.DB() - _, err := db.Exec(createTable) + db, err := conn.DB() + require.NoError(err) + + _, err = db.Exec(createTable) require.NoError(err) _, err = db.Exec(addTrigger) @@ -451,8 +458,10 @@ returning private_id; conn, _ := TestSetup(t, "postgres") assert, require := assert.New(t), require.New(t) - db := conn.DB() - _, err := db.Exec(createTable) + db, err := conn.DB() + require.NoError(err) + + _, err = db.Exec(createTable) require.NoError(err) _, err = db.Exec(addTrigger) @@ -483,8 +492,8 @@ returning private_id; func TestDomain_DefaultUsersExist(t *testing.T) { conn, _ := TestSetup(t, "postgres") - db := conn.DB() - + db, err := conn.DB() + require.NoError(t, err) for _, val := range []string{"u_anon", "u_auth"} { rows, err := db.Query(`select from iam_user where public_id = $1`, val) require.NoError(t, err) @@ -572,8 +581,9 @@ set id = null; } conn, _ := TestSetup(t, "postgres") - db := conn.DB() - _, err := db.Exec(createTable) + db, err := conn.DB() + require.NoError(t, err) + _, err = db.Exec(createTable) assert.NoError(t, err) _, err = db.Exec(addTriggers) @@ -658,7 +668,7 @@ set id = null; _, err = db.Exec(update_updatable) require.Error(err) - assert.Containsf(err.Error(), `pq: column "bad_column_name" not found`, "unexpected error msg: %s", err.Error()) + assert.Containsf(err.Error(), `SQLSTATE 42703`, "unexpected error msg: %s", err.Error()) var found rowData err = db.QueryRow(query, id).Scan(&found.Id, &found.Name, &found.CreateTime, &found.Updatable) @@ -685,7 +695,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -732,7 +743,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -778,7 +790,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -824,7 +837,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -870,7 +884,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -916,7 +931,8 @@ returning id; ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) if _, err := db.Exec(createTable); err != nil { t.Fatalf("query: \n%s\n error: %s", createTable, err) @@ -966,7 +982,8 @@ select wt_is_sentinel($1); ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() + db, err := conn.DB() + require.NoError(t, err) tests := []struct { name string @@ -1028,8 +1045,10 @@ insert on test_not_null_columns ) conn, _ := TestSetup(t, "postgres") - db := conn.DB() - _, err := db.Exec(createTable) + db, err := conn.DB() + assert.NoError(t, err) + + _, err = db.Exec(createTable) assert.NoError(t, err) tests := []struct { diff --git a/internal/db/read_writer.go b/internal/db/read_writer.go index 087962e43..f6946017b 100644 --- a/internal/db/read_writer.go +++ b/internal/db/read_writer.go @@ -13,8 +13,8 @@ import ( "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/oplog/store" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "google.golang.org/protobuf/proto" + "gorm.io/gorm" ) const ( @@ -438,16 +438,26 @@ func (rw *Db) Update(ctx context.Context, i interface{}, fieldMaskPaths []string return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("no fields matched using fieldMaskPaths %s", fieldMaskPaths)) } - // This is not a boundary scope, but rather a gorm Scope: - // https://godoc.org/github.com/jinzhu/gorm#DB.NewScope - scope := rw.underlying.NewScope(i) - if scope.PrimaryKeyZero() { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "primary key is not set") + names, isZero, err := rw.primaryFieldsAreZero(ctx, i) + if err != nil { + return NoRowsAffected, errors.Wrap(ctx, err, op) + } + if isZero { + return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("primary key is not set for: %s", names), errors.WithoutEvent()) } - for _, f := range scope.PrimaryFields() { - if contains(fieldMaskPaths, f.Name) { - return NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, fmt.Sprintf("not allowed on primary key field %s", f.Name)) + mDb := rw.underlying.Model(i) + err = mDb.Statement.Parse(i) + if err != nil || mDb.Statement.Schema == nil { + return NoRowsAffected, errors.New(ctx, errors.Unknown, op, "internal error: unable to parse stmt", errors.WithWrap(err)) + } + reflectValue := reflect.Indirect(reflect.ValueOf(i)) + for _, pf := range mDb.Statement.Schema.PrimaryFields { + if _, isZero := pf.ValueOf(reflectValue); isZero { + return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("primary key %s is not set", pf.Name)) + } + if contains(fieldMaskPaths, pf.Name) { + return NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, fmt.Sprintf("not allowed on primary key field %s", pf.Name)) } } @@ -482,8 +492,14 @@ func (rw *Db) Update(ctx context.Context, i interface{}, fieldMaskPaths []string if *opts.WithVersion == 0 { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "with version option is zero") } - if _, ok := scope.FieldByName("version"); !ok { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s does not have a version field", scope.TableName())) + mDb := rw.underlying.Model(i) + err = mDb.Statement.Parse(i) + if err != nil && mDb.Statement.Schema == nil { + return NoRowsAffected, errors.New(ctx, errors.Unknown, op, "internal error: unable to parse stmt", errors.WithWrap(err)) + } + if !contains(mDb.Statement.Schema.DBNames, "version") { + // if _, ok := stmt.Schema.FieldsByName["version"]; !ok { + return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s does not have a version field", mDb.Statement.Schema.Table)) } where, args = append(where, "version = ?"), append(args, opts.WithVersion) } @@ -554,14 +570,19 @@ func (rw *Db) Delete(ctx context.Context, i interface{}, opt ...Option) (int, er if withOplog && opts.newOplogMsg != nil { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsg options have been specified") } - // This is not a boundary scope, but rather a gorm Scope: - // https://godoc.org/github.com/jinzhu/gorm#DB.NewScope - scope := rw.underlying.NewScope(i) - if opts.withWhereClause == "" { - if scope.PrimaryKeyZero() { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "primary key is not set") + + mDb := rw.underlying.Model(i) + err := mDb.Statement.Parse(i) + if err == nil && mDb.Statement.Schema == nil { + return NoRowsAffected, errors.New(ctx, errors.Unknown, op, "internal error: unable to parse stmt", errors.WithWrap(err)) + } + reflectValue := reflect.Indirect(reflect.ValueOf(i)) + for _, pf := range mDb.Statement.Schema.PrimaryFields { + if _, isZero := pf.ValueOf(reflectValue); isZero { + return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("primary key %s is not set", pf.Name)) } } + if withOplog { _, err := validateOplogArgs(ctx, i, opts) if err != nil { @@ -923,7 +944,8 @@ func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, Handler Tx } // step one of this, start a transaction... - newTx := w.underlying.BeginTx(ctx, nil) + newTx := w.underlying.WithContext(ctx) + newTx = newTx.Begin() rw := &Db{newTx} if err := Handler(rw, rw); err != nil { @@ -1036,8 +1058,10 @@ func (rw *Db) SearchWhere(ctx context.Context, resources interface{}, where stri return errors.New(ctx, errors.InvalidParameter, op, "interface parameter must to be a pointer") } var err error - db := rw.underlying.Order(opts.withOrder) - + db := rw.underlying.WithContext(ctx) + if opts.withOrder != "" { + db = db.Order(opts.withOrder) + } // Perform limiting switch { case opts.WithLimit < 0: // any negative number signals unlimited results @@ -1060,6 +1084,23 @@ func (rw *Db) SearchWhere(ctx context.Context, resources interface{}, where stri return nil } +func (rw *Db) primaryFieldsAreZero(ctx context.Context, i interface{}) ([]string, bool, error) { + const op = "db.primaryFieldsAreZero" + var fieldNames []string + tx := rw.underlying.Model(i) + if err := tx.Statement.Parse(i); err != nil { + return nil, false, errors.Wrap(ctx, err, op, errors.WithoutEvent()) + } + for _, f := range tx.Statement.Schema.PrimaryFields { + if f.PrimaryKey { + if _, isZero := f.ValueOf(reflect.ValueOf(i)); isZero { + fieldNames = append(fieldNames, f.Name) + } + } + } + return fieldNames, len(fieldNames) > 0, nil +} + // filterPaths will filter out non-updatable fields func filterPaths(paths []string) []string { if len(paths) == 0 { diff --git a/internal/db/read_writer_test.go b/internal/db/read_writer_test.go index 8f7a615ae..9efedb326 100644 --- a/internal/db/read_writer_test.go +++ b/internal/db/read_writer_test.go @@ -18,11 +18,11 @@ import ( wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/gorm" ) func TestDb_UpdateUnsetField(t *testing.T) { @@ -44,7 +44,7 @@ func TestDb_UpdateUnsetField(t *testing.T) { cnt, err := rw.Update(context.Background(), updatedTu, []string{"Name"}, nil) require.NoError(t, err) assert.Equal(t, 1, cnt) - assert.Equal(t, "ignore", updatedTu.Email) + assert.Equal(t, "", updatedTu.Email) assert.Equal(t, "updated", updatedTu.Name) } @@ -1463,7 +1463,7 @@ func TestDb_ScanRows(t *testing.T) { err = w.Create(context.Background(), user) require.NoError(err) assert.NotEmpty(user.Id) - where := "select * from db_test_user where name in ($1, $2)" + where := "select * from db_test_user where name in (?, ?)" rows, err := w.Query(context.Background(), where, []interface{}{"alice", "bob"}) require.NoError(err) defer func() { err := rows.Close(); assert.NoError(err) }() @@ -1493,7 +1493,7 @@ func TestDb_Query(t *testing.T) { assert.NotEmpty(user.Id) assert.Equal("alice", user.Name) - where := "select * from db_test_user where name in ($1, $2)" + where := "select * from db_test_user where name in (?, ?)" rows, err := rw.Query(context.Background(), where, []interface{}{"alice", "bob"}) require.NoError(err) defer func() { err := rows.Close(); assert.NoError(err) }() diff --git a/internal/db/schema/migrations/postgres/14/warehouse_user_dim_test.go b/internal/db/schema/migrations/postgres/14/warehouse_user_dim_test.go index 1b40812f2..9b82f9eb8 100644 --- a/internal/db/schema/migrations/postgres/14/warehouse_user_dim_test.go +++ b/internal/db/schema/migrations/postgres/14/warehouse_user_dim_test.go @@ -16,9 +16,9 @@ import ( "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/testing/dbtest" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestMigrations_UserDimension(t *testing.T) { @@ -55,7 +55,9 @@ func TestMigrations_UserDimension(t *testing.T) { assert.False(state.Dirty) // okay, now we can seed the database with test data - conn, err := gorm.Open(dialect, u) + dbType, err := db.StringToDbType(dialect) + require.NoError(err) + conn, err := db.Open(dbType, u) require.NoError(err) rw := db.New(conn) diff --git a/internal/db/schema/migrations/postgres/16/warehouse_credential_dim_test.go b/internal/db/schema/migrations/postgres/16/warehouse_credential_dim_test.go index ef20f7fad..cb51f4856 100644 --- a/internal/db/schema/migrations/postgres/16/warehouse_credential_dim_test.go +++ b/internal/db/schema/migrations/postgres/16/warehouse_credential_dim_test.go @@ -18,9 +18,9 @@ import ( "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/testing/dbtest" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestMigrations_CredentialDimension(t *testing.T) { @@ -56,8 +56,11 @@ func TestMigrations_CredentialDimension(t *testing.T) { assert.Equal(priorMigration, state.DatabaseSchemaVersion) assert.False(state.Dirty) + dbType, err := db.StringToDbType(dialect) + require.NoError(err) + // okay, now we can seed the database with test data - conn, err := gorm.Open(dialect, u) + conn, err := db.Open(dbType, u) require.NoError(err) rw := db.New(conn) diff --git a/internal/db/schema/migrations/postgres/2/07_iam_test.go b/internal/db/schema/migrations/postgres/2/07_iam_test.go index e24549b33..c52be8e2a 100644 --- a/internal/db/schema/migrations/postgres/2/07_iam_test.go +++ b/internal/db/schema/migrations/postgres/2/07_iam_test.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/boundary/internal/db/schema" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/testing/dbtest" - "github.com/jinzhu/gorm" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -56,7 +56,9 @@ func Test_PrimaryAuthMethodChanges(t *testing.T) { assert.False(state.Dirty) // okay, now we can seed the database with test data - conn, err := gorm.Open(dialect, u) + dbType, err := db.StringToDbType(dialect) + require.NoError(err) + conn, err := db.Open(dbType, u) require.NoError(err) rootWrapper := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, rootWrapper) diff --git a/internal/db/schema/migrations/postgres/8/08_connection_test.go b/internal/db/schema/migrations/postgres/8/08_connection_test.go index 35367ce9f..0556c8de5 100644 --- a/internal/db/schema/migrations/postgres/8/08_connection_test.go +++ b/internal/db/schema/migrations/postgres/8/08_connection_test.go @@ -39,8 +39,9 @@ func TestMigration(t *testing.T) { ) conn, _ := db.TestSetup(t, "postgres", db.WithTemplate("template1")) - db := conn.DB() - _, err := db.Exec(createTables) + db, err := conn.DB() + require.NoError(err) + _, err = db.Exec(createTables) require.NoError(err) tests := []struct { diff --git a/internal/db/schema/migrations/postgres/9/managed_group_test.go b/internal/db/schema/migrations/postgres/9/managed_group_test.go index b6060519a..d39cc1d14 100644 --- a/internal/db/schema/migrations/postgres/9/managed_group_test.go +++ b/internal/db/schema/migrations/postgres/9/managed_group_test.go @@ -1,10 +1,13 @@ package migration import ( + "context" + "database/sql" "fmt" "testing" "time" + "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/servers/controller" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -15,8 +18,7 @@ func Test_ManagedGroupTable(t *testing.T) { tc := controller.NewTestController(t, nil) defer tc.Shutdown() - db := tc.DbConn().DB() - var err error + rw := db.New(tc.DbConn()) managedGroupId := "a_bcdefghijk" defaultPasswordAuthMethodId := "ampw_1234567890" @@ -44,9 +46,12 @@ func Test_ManagedGroupTable(t *testing.T) { for _, tt := range insertTests { t.Run("insert: "+tt.testName, func(t *testing.T) { require := require.New(t) - _, err = db.Exec("insert into auth_managed_group values ($1, $2)", - tt.publicId, - tt.authMethodId) + + _, err := rw.Exec(context.Background(), "insert into auth_managed_group values (@public_id, @auth_method_id)", + []interface{}{ + sql.Named("public_id", tt.publicId), + sql.Named("auth_method_id", tt.authMethodId), + }) require.True(tt.wantErr == (err != nil)) }) } @@ -76,7 +81,11 @@ func Test_ManagedGroupTable(t *testing.T) { for _, tt := range updateTests { t.Run("update: "+tt.testName, func(t *testing.T) { assert := assert.New(t) - _, err = db.Exec(fmt.Sprintf("update auth_managed_group set %s = $1 where public_id = $2", tt.column), tt.value, tt.publicId) + _, err := rw.Exec(context.Background(), fmt.Sprintf("update auth_managed_group set %s = @value where public_id = @public_id", tt.column), + []interface{}{ + sql.Named("value", tt.value), + sql.Named("public_id", tt.publicId), + }) assert.True(tt.wantErr == (err != nil)) }) } @@ -87,8 +96,8 @@ func Test_OidcManagedGroupTable(t *testing.T) { tc := controller.NewTestController(t, nil) defer tc.Shutdown() - db := tc.DbConn().DB() - var err error + ctx := context.Background() + rw := db.New(tc.DbConn()) managedGroupId := "a_bcdefghijk" defaultPasswordAuthMethodId := "ampw_1234567890" @@ -150,18 +159,20 @@ func Test_OidcManagedGroupTable(t *testing.T) { for _, tt := range insertTests { t.Run("insert: "+tt.testName, func(t *testing.T) { require := require.New(t) - _, err = db.Exec("insert into auth_oidc_managed_group (public_id, auth_method_id, name, filter) values ($1, $2, $3, $4)", - tt.publicId, - tt.authMethodId, - tt.name, - tt.filter) + _, err := rw.Exec(ctx, "insert into auth_oidc_managed_group (public_id, auth_method_id, name, filter) values (@public_id, @auth_method_id, @name, @filter)", + []interface{}{ + sql.Named("public_id", tt.publicId), + sql.Named("auth_method_id", tt.authMethodId), + sql.Named("name", tt.name), + sql.Named("filter", tt.filter), + }) require.True(tt.wantErr == (err != nil)) }) } } // Read some values to validate that things were set automatically - rows, err := db.Query("select create_time, update_time, version from auth_oidc_managed_group") + rows, err := rw.Query(ctx, "select create_time, update_time, version from auth_oidc_managed_group", nil) require.NoError(t, err) require.True(t, rows.Next()) var create_time, update_time time.Time @@ -207,14 +218,17 @@ func Test_OidcManagedGroupTable(t *testing.T) { for _, tt := range updateTests { t.Run("update: "+tt.testName, func(t *testing.T) { require := require.New(t) - _, err = db.Exec(fmt.Sprintf("update auth_oidc_managed_group set %s = $1 where public_id = $2", tt.column), tt.value, managedGroupId) + _, err = rw.Exec(ctx, fmt.Sprintf("update auth_oidc_managed_group set %s = @value where public_id = @public_id", tt.column), + []interface{}{ + sql.Named("value", tt.value), sql.Named("public_id", managedGroupId), + }) require.True(tt.wantErr == (err != nil)) }) } } // Read values again to validate that things were updated automatically - rows, err = db.Query("select create_time, update_time, version from auth_oidc_managed_group") + rows, err = rw.Query(ctx, "select create_time, update_time, version from auth_oidc_managed_group", nil) require.NoError(t, err) require.True(t, rows.Next()) var updated_create_time, updated_update_time time.Time @@ -224,7 +238,7 @@ func Test_OidcManagedGroupTable(t *testing.T) { assert.Equal(t, 2, version) // Read values from auth_managed_group to ensure it was populated automatically - rows, err = db.Query("select public_id, auth_method_id from auth_managed_group") + rows, err = rw.Query(ctx, "select public_id, auth_method_id from auth_managed_group", nil) require.NoError(t, err) require.True(t, rows.Next()) var public_id, auth_method_id string @@ -233,14 +247,11 @@ func Test_OidcManagedGroupTable(t *testing.T) { assert.Equal(t, defaultOidcAuthMethodId, auth_method_id) // Delete the value from the subtype table - res, err := db.Exec("delete from auth_oidc_managed_group where public_id = $1", managedGroupId) - require.NoError(t, err) - affected, err := res.RowsAffected() - require.NoError(t, err) + affected, err := rw.Exec(ctx, "delete from auth_oidc_managed_group where public_id = @public_id", []interface{}{sql.Named("public_id", managedGroupId)}) require.EqualValues(t, 1, affected) // It should no longer be in the base table - rows, err = db.Query("select public_id, auth_method_id from auth_managed_group") + rows, err = rw.Query(ctx, "select public_id, auth_method_id from auth_managed_group", nil) require.NoError(t, err) require.False(t, rows.Next()) } @@ -250,8 +261,8 @@ func Test_AuthManagedOidcGroupMemberAccountTable(t *testing.T) { tc := controller.NewTestController(t, nil) defer tc.Shutdown() - db := tc.DbConn().DB() - var err error + ctx := context.Background() + rw := db.New(tc.DbConn()) managedGroupId := "a_bcdefghijk" defaultOidcAuthMethodId := "amoidc_1234567890" @@ -259,15 +270,17 @@ func Test_AuthManagedOidcGroupMemberAccountTable(t *testing.T) { filter := "this is a filter" // Insert valid data in auth_oidc_managed_group to use for the following tests - _, err = db.Exec("insert into auth_oidc_managed_group (public_id, auth_method_id, name, filter) values ($1, $2, $3, $4)", - managedGroupId, - defaultOidcAuthMethodId, - name, - filter) + _, err := rw.Exec(ctx, "insert into auth_oidc_managed_group (public_id, auth_method_id, name, filter) values (@public_id, @auth_method_id, @name, @filter)", + []interface{}{ + sql.Named("public_id", managedGroupId), + sql.Named("auth_method_id", defaultOidcAuthMethodId), + sql.Named("name", name), + sql.Named("filter", filter), + }) require.NoError(t, err) // Fetch a valid (oidc) account ID to use in insertion - rows, err := db.Query("select public_id from auth_oidc_account limit 1") + rows, err := rw.Query(ctx, "select public_id from auth_oidc_account limit 1", nil) require.NoError(t, err) require.True(t, rows.Next()) var accountId string @@ -310,16 +323,18 @@ func Test_AuthManagedOidcGroupMemberAccountTable(t *testing.T) { for _, tt := range insertTests { t.Run("insert: "+tt.testName, func(t *testing.T) { assert := assert.New(t) - _, err = db.Exec("insert into auth_oidc_managed_group_member_account (managed_group_id, member_id) values ($1, $2)", - tt.managedGroupId, - tt.memberId) + _, err = rw.Exec(ctx, "insert into auth_oidc_managed_group_member_account (managed_group_id, member_id) values (@group_id, @member_id)", + []interface{}{ + sql.Named("group_id", tt.managedGroupId), + sql.Named("member_id", tt.memberId), + }) assert.True(tt.wantErr == (err != nil)) }) } } // Read some values to validate that things were set automatically - rows, err = db.Query("select create_time, managed_group_id, member_id from auth_oidc_managed_group_member_account") + rows, err = rw.Query(ctx, "select create_time, managed_group_id, member_id from auth_oidc_managed_group_member_account", nil) require.NoError(t, err) require.True(t, rows.Next()) var create_time time.Time @@ -357,14 +372,18 @@ func Test_AuthManagedOidcGroupMemberAccountTable(t *testing.T) { for _, tt := range updateTests { t.Run("update: "+tt.testName, func(t *testing.T) { assert := assert.New(t) - _, err = db.Exec(fmt.Sprintf("update auth_managed_group_member_account set %s = $1 where managed_group_id = $2 and member_id = $3", tt.column), managedGroupId, accountId) + _, err = rw.Exec(ctx, fmt.Sprintf("update auth_managed_group_member_account set %s = ? where managed_group_id = @group_id and member_id = @member_id", tt.column), + []interface{}{ + sql.Named("group_id", managedGroupId), + sql.Named("member_id", accountId), + }) assert.True(tt.wantErr == (err != nil)) }) } } // Read from the view to ensure we see it there - rows, err = db.Query("select create_time, managed_group_id, member_id from auth_managed_group_member_account") + rows, err = rw.Query(ctx, "select create_time, managed_group_id, member_id from auth_managed_group_member_account", nil) require.NoError(t, err) require.True(t, rows.Next()) var view_create_time time.Time diff --git a/internal/db/testing.go b/internal/db/testing.go index 915695103..f95b3694c 100644 --- a/internal/db/testing.go +++ b/internal/db/testing.go @@ -16,8 +16,9 @@ import ( "github.com/hashicorp/boundary/testing/dbtest" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" + "gorm.io/gorm" + "gorm.io/gorm/logger" ) // setup the tests (initialize the database one-time and intialized testDatabaseURL). Do not close the returned db. @@ -46,13 +47,19 @@ func TestSetup(t *testing.T, dialect string, opt ...TestOption) (*gorm.DB, strin if err != nil { t.Fatalf("Couldn't init store on existing db: %v", err) } - - db, err := gorm.Open(dialect, url) + dbType, err := StringToDbType(dialect) if err != nil { t.Fatal(err) } + db, err := Open(dbType, url) + if err != nil { + t.Fatal(err) + } + db.Logger.LogMode(logger.Error) t.Cleanup(func() { - assert.NoError(t, db.Close(), "Got error closing gorm db.") + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, sqlDB.Close(), "Got error closing gorm db.") }) return db, url } diff --git a/internal/db/timestamp/scanners.go b/internal/db/timestamp/scanners.go index 8f7674dc4..0cf43129a 100644 --- a/internal/db/timestamp/scanners.go +++ b/internal/db/timestamp/scanners.go @@ -3,16 +3,29 @@ package timestamp import ( "database/sql/driver" "errors" + "math" "time" "google.golang.org/protobuf/types/known/timestamppb" ) +var ( + NegativeInfinityTS = time.Date(math.MinInt32, time.January, 1, 0, 0, 0, 0, time.UTC) + PositiveInfinityTS = time.Date(math.MaxInt32, time.December, 31, 23, 59, 59, 1e9-1, time.UTC) +) + // Scan implements sql.Scanner for protobuf Timestamp. func (ts *Timestamp) Scan(value interface{}) error { switch t := value.(type) { case time.Time: ts.Timestamp = timestamppb.New(t) // google proto version + case string: + switch value { + case "-infinity": + ts.Timestamp = timestamppb.New(NegativeInfinityTS) + case "infinity": + ts.Timestamp = timestamppb.New(PositiveInfinityTS) + } default: return errors.New("Not a protobuf Timestamp") } @@ -26,3 +39,8 @@ func (ts *Timestamp) Value() (driver.Value, error) { } return ts.Timestamp.AsTime(), nil } + +// GormDataType gorm common data type (required) +func (ts *Timestamp) GormDataType() string { + return "timestamp" +} diff --git a/internal/errors/error.go b/internal/errors/error.go index 73f0f396a..c729f9e80 100644 --- a/internal/errors/error.go +++ b/internal/errors/error.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/hashicorp/boundary/internal/observability/event" - "github.com/lib/pq" + "github.com/jackc/pgconn" ) // Op represents an operation (package.function). @@ -192,29 +192,29 @@ func Convert(e error) *Err { if err, ok := e.(*Err); ok { return err } - var pqError *pq.Error - if As(e, &pqError) { - if pqError.Code.Class() == "23" { // class of integrity constraint violations - switch pqError.Code { + var pgxError *pgconn.PgError + if As(e, &pgxError) { + if pgxError.Code[0:2] == "23" { // class of integrity constraint violations + switch pgxError.Code { case "23505": // unique_violation - return E(ctx, WithoutEvent(), WithMsg(pqError.Message), WithWrap(E(ctx, WithoutEvent(), WithCode(NotUnique), WithMsg("unique constraint violation")))).(*Err) + return E(ctx, WithoutEvent(), WithMsg(pgxError.Message), WithWrap(E(ctx, WithoutEvent(), WithCode(NotUnique), WithMsg("unique constraint violation")))).(*Err) case "23502": // not_null_violation - msg := fmt.Sprintf("%s must not be empty", pqError.Column) + msg := fmt.Sprintf("%s must not be empty", pgxError.ColumnName) return E(ctx, WithoutEvent(), WithMsg(msg), WithWrap(E(ctx, WithoutEvent(), WithCode(NotNull), WithMsg("not null constraint violated")))).(*Err) case "23514": // check_violation - msg := fmt.Sprintf("%s constraint failed", pqError.Constraint) + msg := fmt.Sprintf("%s constraint failed", pgxError.ConstraintName) return E(ctx, WithoutEvent(), WithMsg(msg), WithWrap(E(ctx, WithoutEvent(), WithCode(CheckConstraint), WithMsg("check constraint violated")))).(*Err) default: - return E(ctx, WithoutEvent(), WithCode(NotSpecificIntegrity), WithMsg(pqError.Message)).(*Err) + return E(ctx, WithoutEvent(), WithCode(NotSpecificIntegrity), WithMsg(pgxError.Message)).(*Err) } } - switch pqError.Code { + switch pgxError.Code { case "42P01": - return E(ctx, WithoutEvent(), WithCode(MissingTable), WithMsg(pqError.Message)).(*Err) + return E(ctx, WithoutEvent(), WithCode(MissingTable), WithMsg(pgxError.Message)).(*Err) case "42703": - return E(ctx, WithoutEvent(), WithCode(ColumnNotFound), WithMsg(pqError.Message)).(*Err) + return E(ctx, WithoutEvent(), WithCode(ColumnNotFound), WithMsg(pgxError.Message)).(*Err) case "P0001": - return E(ctx, WithoutEvent(), WithCode(Exception), WithMsg(pqError.Message)).(*Err) + return E(ctx, WithoutEvent(), WithCode(Exception), WithMsg(pgxError.Message)).(*Err) } } // unfortunately, we can't help. diff --git a/internal/errors/error_test.go b/internal/errors/error_test.go index 138ca8256..91101bfef 100644 --- a/internal/errors/error_test.go +++ b/internal/errors/error_test.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/lib/pq" + "github.com/jackc/pgconn" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -254,8 +254,8 @@ func Test_WrapError(t *testing.T) { }, { name: "NotSpecificIntegrity", - err: &pq.Error{ - Code: pq.ErrorCode("23001"), + err: &pgconn.PgError{ + Code: "23001", Message: "test msg", }, want: &errors.Err{ @@ -449,8 +449,8 @@ func TestConvertError(t *testing.T) { }, { name: "NotSpecificIntegrity", - e: &pq.Error{ - Code: pq.ErrorCode("23001"), + e: &pgconn.PgError{ + Code: "23001", }, wantErr: errors.EDeprecated(errors.WithCode(errors.NotSpecificIntegrity)), }, diff --git a/internal/errors/is.go b/internal/errors/is.go index 1bad741a1..01bc22f22 100644 --- a/internal/errors/is.go +++ b/internal/errors/is.go @@ -3,7 +3,7 @@ package errors import ( "errors" - "github.com/lib/pq" + "github.com/jackc/pgconn" ) // IsUniqueError returns a boolean indicating whether the error is known to @@ -17,9 +17,9 @@ func IsUniqueError(err error) bool { return true } - var pqError *pq.Error - if errors.As(err, &pqError) { - if pqError.Code == "23505" { // unique_violation + var pgxError *pgconn.PgError + if errors.As(err, &pgxError) { + if pgxError.Code == "23505" { // unique_violation return true } } @@ -38,9 +38,9 @@ func IsCheckConstraintError(err error) bool { return true } - var pqError *pq.Error - if errors.As(err, &pqError) { - if pqError.Code == "23514" { // check_violation + var pgxError *pgconn.PgError + if errors.As(err, &pgxError) { + if pgxError.Code == "23514" { // check_violation return true } } @@ -59,9 +59,9 @@ func IsNotNullError(err error) bool { return true } - var pqError *pq.Error - if errors.As(err, &pqError) { - if pqError.Code == "23502" { // not_null_violation + var pgxError *pgconn.PgError + if errors.As(err, &pgxError) { + if pgxError.Code == "23502" { // not_null_violation return true } } @@ -72,9 +72,9 @@ func IsNotNullError(err error) bool { // IsMissingTableError returns a boolean indicating whether the error is known // to report a undefined/missing table violation. func IsMissingTableError(err error) bool { - var pqError *pq.Error - if errors.As(err, &pqError) { - if pqError.Code == "42P01" { + var pgxError *pgconn.PgError + if errors.As(err, &pgxError) { + if pgxError.Code == "42P01" { return true } } diff --git a/internal/errors/is_test.go b/internal/errors/is_test.go index ad76af9a9..f142b7210 100644 --- a/internal/errors/is_test.go +++ b/internal/errors/is_test.go @@ -7,7 +7,7 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/lib/pq" + "github.com/jackc/pgconn" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -26,15 +26,15 @@ func TestError_IsUnique(t *testing.T) { }, { name: "postgres-not-unique", - in: &pq.Error{ - Code: pq.ErrorCode("23503"), + in: &pgconn.PgError{ + Code: "23503", }, want: false, }, { name: "postgres-is-unique2", - in: &pq.Error{ - Code: pq.ErrorCode("23505"), + in: &pgconn.PgError{ + Code: "23505", }, want: true, }, @@ -47,8 +47,8 @@ func TestError_IsUnique(t *testing.T) { name: "wrapped-pq-is-unique", in: errors.E( context.TODO(), - errors.WithWrap(&pq.Error{ - Code: pq.ErrorCode("23505"), + errors.WithWrap(&pgconn.PgError{ + Code: "23505", }), ), want: true, @@ -89,15 +89,15 @@ func TestError_IsCheckConstraint(t *testing.T) { }, { name: "postgres-not-check-constraint", - in: &pq.Error{ - Code: pq.ErrorCode("23505"), + in: &pgconn.PgError{ + Code: "23505", }, want: false, }, { name: "postgres-is-check-constraint", - in: &pq.Error{ - Code: pq.ErrorCode("23514"), + in: &pgconn.PgError{ + Code: "23514", }, want: true, }, @@ -109,8 +109,8 @@ func TestError_IsCheckConstraint(t *testing.T) { { name: "wrapped-pq-is-check-constraint", in: errors.E(context.TODO(), errors.WithCode(errors.CheckConstraint), - errors.WithWrap(&pq.Error{ - Code: pq.ErrorCode("23514"), + errors.WithWrap(&pgconn.PgError{ + Code: "23514", }), ), want: true, @@ -151,22 +151,22 @@ func TestError_IsNotNullError(t *testing.T) { }, { name: "postgres-is-unique-not-not-null", - in: &pq.Error{ - Code: pq.ErrorCode("23505"), + in: &pgconn.PgError{ + Code: "23505", }, want: false, }, { name: "postgres-is-check-constraint-not-not-null", - in: &pq.Error{ - Code: pq.ErrorCode("23514"), + in: &pgconn.PgError{ + Code: "23514", }, want: false, }, { name: "postgres-is-not-null", - in: &pq.Error{ - Code: pq.ErrorCode("23502"), + in: &pgconn.PgError{ + Code: "23502", }, want: true, }, @@ -178,8 +178,8 @@ func TestError_IsNotNullError(t *testing.T) { { name: "wrapped-pq-is-not-null", in: errors.E(context.TODO(), errors.WithCode(errors.NotNull), - errors.WithWrap(&pq.Error{ - Code: pq.ErrorCode("23502"), + errors.WithWrap(&pgconn.PgError{ + Code: "23502", }), ), want: true, @@ -219,22 +219,22 @@ func TestError_IsMissingTableError(t *testing.T) { }, { name: "postgres-is-unique-not-not-null", - in: &pq.Error{ - Code: pq.ErrorCode("23505"), + in: &pgconn.PgError{ + Code: "23505", }, want: false, }, { name: "postgres-is-check-constraint-not-not-null", - in: &pq.Error{ - Code: pq.ErrorCode("23514"), + in: &pgconn.PgError{ + Code: "23514", }, want: false, }, { name: "postgres-is-missing-table", - in: &pq.Error{ - Code: pq.ErrorCode("42P01"), + in: &pgconn.PgError{ + Code: "42P01", }, want: true, }, diff --git a/internal/host/static/host_catalog_test.go b/internal/host/static/host_catalog_test.go index f44992bd8..292020d2d 100644 --- a/internal/host/static/host_catalog_test.go +++ b/internal/host/static/host_catalog_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/host/static/store" diff --git a/internal/host/static/host_set_test.go b/internal/host/static/host_set_test.go index e0c746805..d52fbd484 100644 --- a/internal/host/static/host_set_test.go +++ b/internal/host/static/host_set_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/boundary/internal/iam" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm/logger" ) func TestHostSet_New(t *testing.T) { @@ -16,8 +17,7 @@ func TestHostSet_New(t *testing.T) { wrapper := db.TestWrapper(t) _, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) cat := testCatalog(t, conn, prj.PublicId) - - conn.LogMode(false) + conn.Logger.LogMode(logger.Silent) type args struct { catalogId string opts []Option diff --git a/internal/host/static/host_test.go b/internal/host/static/host_test.go index c3a437382..4176f506b 100644 --- a/internal/host/static/host_test.go +++ b/internal/host/static/host_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/boundary/internal/iam" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm/logger" ) func TestHost_New(t *testing.T) { @@ -17,7 +18,7 @@ func TestHost_New(t *testing.T) { _, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) cat := testCatalog(t, conn, prj.PublicId) - conn.LogMode(false) + conn.Logger.LogMode(logger.Silent) type args struct { catalogId string opts []Option diff --git a/internal/host/static/query.go b/internal/host/static/query.go index 0aca0a882..3618d4b75 100644 --- a/internal/host/static/query.go +++ b/internal/host/static/query.go @@ -13,7 +13,7 @@ current_hosts (host_id) as ( -- returns the current list select host_id from static_host_set_member - where set_id = $1 + where set_id = @1 -- this trailing space is needed by gorm ), keep_hosts (host_id) as ( -- returns the KEEP list diff --git a/internal/host/static/repository_host_catalog_test.go b/internal/host/static/repository_host_catalog_test.go index 96a999ae2..4af721d32 100644 --- a/internal/host/static/repository_host_catalog_test.go +++ b/internal/host/static/repository_host_catalog_test.go @@ -461,7 +461,9 @@ func TestRepository_UpdateCatalog(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.ScopeId, got.ScopeId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(t, err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/host/static/repository_host_set_member.go b/internal/host/static/repository_host_set_member.go index a7dae0527..dead39500 100644 --- a/internal/host/static/repository_host_set_member.go +++ b/internal/host/static/repository_host_set_member.go @@ -2,6 +2,7 @@ package static import ( "context" + "database/sql" "fmt" "strings" @@ -121,14 +122,14 @@ func getHosts(ctx context.Context, reader db.Reader, setId string, limit int) ([ const whereNoLimit = `public_id in ( select host_id from static_host_set_member - where set_id = $1 + where set_id = ? )` const whereLimit = `public_id in ( select host_id from static_host_set_member - where set_id = $1 - limit $2 + where set_id = ? + limit ? )` params := []interface{}{setId} @@ -328,9 +329,9 @@ type change struct { func (r *Repository) changes(ctx context.Context, setId string, hostIds []string) ([]*change, error) { const op = "static.(Repository).changes" var inClauseSpots []string - // starts at 2 because there is already a $1 in the query + // starts at 2 because there is already a @1 in the query for i := 2; i < len(hostIds)+2; i++ { - inClauseSpots = append(inClauseSpots, fmt.Sprintf("$%d", i)) + inClauseSpots = append(inClauseSpots, fmt.Sprintf("@%d", i)) } inClause := strings.Join(inClauseSpots, ",") if inClause == "" { @@ -339,9 +340,9 @@ func (r *Repository) changes(ctx context.Context, setId string, hostIds []string query := fmt.Sprintf(setChangesQuery, inClause) var params []interface{} - params = append(params, setId) - for _, v := range hostIds { - params = append(params, v) + params = append(params, sql.Named("1", setId)) + for idx, v := range hostIds { + params = append(params, sql.Named(fmt.Sprintf("%d", idx+2), v)) } rows, err := r.reader.Query(ctx, query, params) if err != nil { diff --git a/internal/host/static/repository_host_set_test.go b/internal/host/static/repository_host_set_test.go index 894636d52..3e118cbf9 100644 --- a/internal/host/static/repository_host_set_test.go +++ b/internal/host/static/repository_host_set_test.go @@ -493,7 +493,9 @@ func TestRepository_UpdateSet(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.CatalogId, got.CatalogId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/host/static/repository_host_test.go b/internal/host/static/repository_host_test.go index ff8212b72..0f699375c 100644 --- a/internal/host/static/repository_host_test.go +++ b/internal/host/static/repository_host_test.go @@ -620,7 +620,9 @@ func TestRepository_UpdateHost(t *testing.T) { assert.Equal(tt.wantCount, gotCount, "row count") assert.NotSame(tt.orig, got) assert.Equal(tt.orig.CatalogId, got.CatalogId) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.want.Name == "" { dbassert.IsNull(got, "name") return diff --git a/internal/host/static/testing.go b/internal/host/static/testing.go index 1cc0c6847..3d3a94d3a 100644 --- a/internal/host/static/testing.go +++ b/internal/host/static/testing.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/hashicorp/boundary/internal/db" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" + "gorm.io/gorm" ) // TestCatalogs creates count number of static host catalogs to the provided DB diff --git a/internal/iam/account_test.go b/internal/iam/account_test.go index 973acbd51..c6ac60eac 100644 --- a/internal/iam/account_test.go +++ b/internal/iam/account_test.go @@ -83,7 +83,9 @@ func TestAccount_Clone(t *testing.T) { authMethodPublicId := testAuthMethod(t, conn, org.PublicId) acct := testAccount(t, conn, org.PublicId, authMethodPublicId, u.PublicId) acct2 := testAccount(t, conn, org.PublicId, authMethodPublicId, "") - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(t, err) + dbassert := dbassert.New(t, underlyingDB) dbassert.IsNull(acct2, "IamUserId") cp := acct.Clone() assert.True(!proto.Equal(cp.(*authAccount).Account, acct2.Account)) diff --git a/internal/iam/group_test.go b/internal/iam/group_test.go index 50228616d..be6720d95 100644 --- a/internal/iam/group_test.go +++ b/internal/iam/group_test.go @@ -351,7 +351,9 @@ func Test_GroupUpdate(t *testing.T) { require.NoError(err) assert.True(proto.Equal(updateGrp, foundGrp)) if len(tt.args.nullPaths) != 0 { - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) for _, f := range tt.args.nullPaths { dbassert.IsNull(&foundGrp, f) } diff --git a/internal/iam/immutable_fields_test.go b/internal/iam/immutable_fields_test.go index 2284ae3e3..cecfb4e38 100644 --- a/internal/iam/immutable_fields_test.go +++ b/internal/iam/immutable_fields_test.go @@ -95,8 +95,8 @@ func TestConcreteScope_ImmutableFields(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) repo := TestRepo(t, conn, wrapper) - db := conn.DB() - + db, err := conn.DB() + require.NoError(t, err) org, proj := TestScopes(t, repo) tests := []struct { diff --git a/internal/iam/query.go b/internal/iam/query.go index 665c9d907..4a06c6cc7 100644 --- a/internal/iam/query.go +++ b/internal/iam/query.go @@ -12,15 +12,15 @@ const ( on iam_user_acct_info.public_id = auth_account.iam_user_id where iam_user_acct_info.scope_id = auth_account.scope_id and - auth_account.public_id = $1` + auth_account.public_id = ?` // whereValidAuthMethod - determine if an auth method public_id within a scope_id // is valid by returning a count of matching rows. - whereValidAuthMethod = `select count(*) from auth_method where public_id = $1 and scope_id = $2` + whereValidAuthMethod = `select count(*) from auth_method where public_id = $1 and scope_id = $2` // raw query // insertAuthMethod - insert a row directly into auth_method (TODO - this // should be replaced with calls to the auth method repo). - insertAuthMethod = `insert into auth_method (public_id, scope_id) values ($1, $2)` + insertAuthMethod = `insert into auth_method (public_id, scope_id) values (?, ?)` accountChangesQuery = ` with @@ -34,7 +34,7 @@ const ( -- returns the current list select public_id from auth_account - where iam_user_id = $1 + where iam_user_id = ? ), keep_accounts (account_id) as ( -- returns the KEEP list @@ -78,7 +78,7 @@ const ( -- returns the current list select member_id from iam_group_member - where group_id = $1 + where group_id = ? ), keep_members (member_id) as ( -- returns the KEEP list diff --git a/internal/iam/repository_group.go b/internal/iam/repository_group.go index e14b7e3d7..44ca3e1e9 100644 --- a/internal/iam/repository_group.go +++ b/internal/iam/repository_group.go @@ -497,9 +497,9 @@ func (r *Repository) SetGroupMembers(ctx context.Context, groupId string, groupV func groupMemberChanges(ctx context.Context, reader db.Reader, groupId string, userIds []string) ([]interface{}, []interface{}, error) { const op = "iam.groupMemberChanges" var inClauseSpots []string - // starts at 2 because there is already a $1 in the query + // starts at 2 because there is already a ? in the query for i := 2; i < len(userIds)+2; i++ { - inClauseSpots = append(inClauseSpots, fmt.Sprintf("$%d", i)) + inClauseSpots = append(inClauseSpots, "?") } inClause := strings.Join(inClauseSpots, ",") if inClause == "" { @@ -508,10 +508,11 @@ func groupMemberChanges(ctx context.Context, reader db.Reader, groupId string, u query := fmt.Sprintf(grpMemberChangesQuery, inClause) var params []interface{} - params = append(params, groupId) for _, v := range userIds { params = append(params, v) } + params = append(params, groupId) + rows, err := reader.Query(ctx, query, params) if err != nil { return nil, nil, errors.Wrap(ctx, err, op) diff --git a/internal/iam/repository_group_test.go b/internal/iam/repository_group_test.go index 7b5d0dd44..4c5d1bb44 100644 --- a/internal/iam/repository_group_test.go +++ b/internal/iam/repository_group_test.go @@ -450,7 +450,9 @@ func TestRepository_UpdateGroup(t *testing.T) { foundGrp, _, err := repo.LookupGroup(context.Background(), u.PublicId) require.NoError(err) assert.True(proto.Equal(groupAfterUpdate, foundGrp)) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.args.name == "" { dbassert.IsNull(foundGrp, "name") } diff --git a/internal/iam/repository_role_grant.go b/internal/iam/repository_role_grant.go index 923cce7de..0bb39d82f 100644 --- a/internal/iam/repository_role_grant.go +++ b/internal/iam/repository_role_grant.go @@ -392,8 +392,8 @@ func (r *Repository) GrantsForUser(ctx context.Context, userId string, _ ...Opti } const ( - anonUser = `where public_id in ($1)` - authUser = `where public_id in ('u_anon', 'u_auth', $1)` + anonUser = `where public_id in (?)` + authUser = `where public_id in ('u_anon', 'u_auth', ?)` grantsQuery = ` with users (id) as ( diff --git a/internal/iam/repository_role_test.go b/internal/iam/repository_role_test.go index f2344c270..da1ebec39 100644 --- a/internal/iam/repository_role_test.go +++ b/internal/iam/repository_role_test.go @@ -447,7 +447,9 @@ func TestRepository_UpdateRole(t *testing.T) { foundRole, _, _, err := repo.LookupRole(context.Background(), r.PublicId) assert.NoError(err) assert.True(proto.Equal(roleAfterUpdate, foundRole)) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.args.name == "" { assert.Equal(foundRole.Name, "") dbassert.IsNull(foundRole, "name") diff --git a/internal/iam/repository_scope.go b/internal/iam/repository_scope.go index ddfc149f3..b5b89c3bc 100644 --- a/internal/iam/repository_scope.go +++ b/internal/iam/repository_scope.go @@ -394,7 +394,7 @@ func (r *Repository) UpdateScope(ctx context.Context, scope *Scope, version uint map[string]interface{}{ "name": scope.Name, "description": scope.Description, - "primaryAuthMethodId": scope.PrimaryAuthMethodId, + "PrimaryAuthMethodId": scope.PrimaryAuthMethodId, // gorm: it's important that the field start with a capital letter. }, fieldMaskPaths, nil, diff --git a/internal/iam/repository_user.go b/internal/iam/repository_user.go index 6ed4dc2ef..f22e87758 100644 --- a/internal/iam/repository_user.go +++ b/internal/iam/repository_user.go @@ -782,10 +782,12 @@ func dissociateUserFromAccounts(ctx context.Context, repoKms *kms.Kms, reader db // associationChanges returns two slices: accounts to associate and disassociate func associationChanges(ctx context.Context, reader db.Reader, userId string, accountIds []string) ([]string, []string, error) { const op = "iam.associationChanges" + var inClauseSpots []string - // starts at 2 because there is already a $1 in the query + // starts at 2 because there is already a ? in the query for i := 2; i < len(accountIds)+2; i++ { - inClauseSpots = append(inClauseSpots, fmt.Sprintf("$%d", i)) + // inClauseSpots = append(inClauseSpots, fmt.Sprintf("$%d", i)) + inClauseSpots = append(inClauseSpots, "?") } inClause := strings.Join(inClauseSpots, ",") if inClause == "" { @@ -794,10 +796,11 @@ func associationChanges(ctx context.Context, reader db.Reader, userId string, ac query := fmt.Sprintf(accountChangesQuery, inClause) var params []interface{} - params = append(params, userId) for _, v := range accountIds { params = append(params, v) } + params = append(params, userId) + rows, err := reader.Query(ctx, query, params) if err != nil { return nil, nil, errors.Wrap(ctx, err, op) diff --git a/internal/iam/repository_user_iam_pkg_test.go b/internal/iam/repository_user_iam_pkg_test.go index 3abb3c562..f537db9af 100644 --- a/internal/iam/repository_user_iam_pkg_test.go +++ b/internal/iam/repository_user_iam_pkg_test.go @@ -309,8 +309,10 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - dbassert := dbassert.New(t, conn.DB()) - err := dissociateUserFromAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) + err = dissociateUserFromAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...) if tt.wantErr { require.Error(err) assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err) diff --git a/internal/iam/repository_user_test.go b/internal/iam/repository_user_test.go index 052610fc8..da777bfc5 100644 --- a/internal/iam/repository_user_test.go +++ b/internal/iam/repository_user_test.go @@ -475,8 +475,9 @@ func TestRepository_UpdateUser(t *testing.T) { assert.True(proto.Equal(userAfterUpdate, foundUser)) sort.Strings(foundAccountIds) assert.Equal(accountIds, foundAccountIds) - - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.args.name == "" { dbassert.IsNull(foundUser, "name") } @@ -846,8 +847,9 @@ func TestRepository_LookupUserWithLogin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - dbassert := dbassert.New(t, conn.DB()) - + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) got, err := repo.LookupUserWithLogin(context.Background(), tt.args.withAccountId, tt.args.opt...) if tt.wantErr { require.Error(err) diff --git a/internal/iam/role_grant_test.go b/internal/iam/role_grant_test.go index ca8bbddc2..7e24eee99 100644 --- a/internal/iam/role_grant_test.go +++ b/internal/iam/role_grant_test.go @@ -2,7 +2,6 @@ package iam import ( "context" - "strings" "testing" "github.com/hashicorp/boundary/internal/db" @@ -162,7 +161,7 @@ func TestRoleGrant_Delete(t *testing.T) { grant: "id=*;type=*;actions=*", }, wantErr: true, - wantsErrStr: "primary key is not set", + wantsErrStr: "is not set", }, { name: "nil-grant", @@ -170,9 +169,8 @@ func TestRoleGrant_Delete(t *testing.T) { roleId: projRole.PublicId, grant: "", }, - // Note: Gorm's primary key checking is only for what it considers - // the main primary key field, hence this doesn't error as the above - // case does + wantErr: true, + wantsErrStr: "is not set", }, { name: "invalid", @@ -211,7 +209,7 @@ func TestRoleGrant_Delete(t *testing.T) { deleted, err := rw.Delete(context.Background(), rg) if tt.wantErr { require.Error(err) - assert.True(strings.Contains(err.Error(), tt.wantsErrStr)) + assert.Contains(err.Error(), tt.wantsErrStr) return } require.NoError(err) diff --git a/internal/iam/role_test.go b/internal/iam/role_test.go index 0c6cbca94..9af79e7c6 100644 --- a/internal/iam/role_test.go +++ b/internal/iam/role_test.go @@ -440,7 +440,9 @@ func Test_RoleUpdate(t *testing.T) { } assert.True(proto.Equal(updateRole, foundRole)) if len(tt.args.nullPaths) != 0 { - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) for _, f := range tt.args.nullPaths { dbassert.IsNull(&foundRole, f) } diff --git a/internal/iam/store/user.pb.go b/internal/iam/store/user.pb.go index 62c31dae8..16370e7e0 100644 --- a/internal/iam/store/user.pb.go +++ b/internal/iam/store/user.pb.go @@ -51,20 +51,20 @@ type User struct { Version uint32 `protobuf:"varint,70,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"` // Output only. login_name is a string that maps to the user's account "login // name" from the scope's primary auth method - // @inject_tag: `gorm:"-"` - LoginName string `protobuf:"bytes,90,opt,name=login_name,proto3" json:"login_name,omitempty" gorm:"-"` + // @inject_tag: `gorm:"->"` + LoginName string `protobuf:"bytes,90,opt,name=login_name,proto3" json:"login_name,omitempty" gorm:"->"` // Output only. full_name is a string that maps to the user's account name // from the scope's primary auth method - // @inject_tag: `gorm:"-"` - FullName string `protobuf:"bytes,100,opt,name=full_name,proto3" json:"full_name,omitempty" gorm:"-"` + // @inject_tag: `gorm:"->"` + FullName string `protobuf:"bytes,100,opt,name=full_name,proto3" json:"full_name,omitempty" gorm:"->"` // Output only. email is a string that maps to the user's account email from // the scope's primary auth method - // @inject_tag: `gorm:"-"` - Email string `protobuf:"bytes,110,opt,name=email,proto3" json:"email,omitempty" gorm:"-"` + // @inject_tag: `gorm:"->"` + Email string `protobuf:"bytes,110,opt,name=email,proto3" json:"email,omitempty" gorm:"->"` // Output only. primary_account_id is a string that maps to the user's account // public_id from the scope's primary auth method - // @inject_tag: `gorm:"-"` - PrimaryAccountId string `protobuf:"bytes,120,opt,name=primary_account_id,proto3" json:"primary_account_id,omitempty" gorm:"-"` + // @inject_tag: `gorm:"->"` + PrimaryAccountId string `protobuf:"bytes,120,opt,name=primary_account_id,proto3" json:"primary_account_id,omitempty" gorm:"->"` } func (x *User) Reset() { diff --git a/internal/iam/testing.go b/internal/iam/testing.go index 68babe53d..a0f7197be 100644 --- a/internal/iam/testing.go +++ b/internal/iam/testing.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/boundary/internal/types/scope" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) // TestRepo creates a repo that can be used for various purposes. Crucially, it @@ -277,7 +277,9 @@ func testAccount(t *testing.T, conn *gorm.DB, scopeId, authMethodId, userId stri } var count int - err := conn.DB().QueryRow(whereValidAuthMethod, authMethodId, scopeId).Scan(&count) + underlyingDB, err := conn.DB() + require.NoError(err) + err = underlyingDB.QueryRow(whereValidAuthMethod, authMethodId, scopeId).Scan(&count) require.NoError(err) require.Equal(1, count) @@ -297,7 +299,9 @@ func testAccount(t *testing.T, conn *gorm.DB, scopeId, authMethodId, userId stri require.NotEmpty(acct.PublicId) if userId == "" { - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) dbassert.IsNull(acct, "IamUserId") } return acct @@ -316,7 +320,8 @@ func testAuthMethod(t *testing.T, conn *gorm.DB, scopeId string) string { id, err := db.NewPublicId(authMethodPrefix) require.NoError(err) - _, err = conn.DB().Exec(insertAuthMethod, id, scopeId) + rw := db.New(conn) + _, err = rw.Exec(context.Background(), insertAuthMethod, []interface{}{id, scopeId}) require.NoError(err) return id } diff --git a/internal/iam/testing_test.go b/internal/iam/testing_test.go index 5d6ca27d8..57a771164 100644 --- a/internal/iam/testing_test.go +++ b/internal/iam/testing_test.go @@ -216,3 +216,14 @@ func Test_TestGroupMember(t *testing.T) { require.Equal(pg.PublicId, gm.GroupId) require.Equal(u.PublicId, gm.MemberId) } + +func Test_testAccount(t *testing.T) { + require := require.New(t) + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + repo := TestRepo(t, conn, wrapper) + org, _ := TestScopes(t, repo) + authMethodId := testAuthMethod(t, conn, org.PublicId) + acct := testAccount(t, conn, org.PublicId, authMethodId, "") + require.Equal(acct.ScopeId, org.PublicId) +} diff --git a/internal/kms/testing.go b/internal/kms/testing.go index f949622d6..e05759772 100644 --- a/internal/kms/testing.go +++ b/internal/kms/testing.go @@ -7,8 +7,8 @@ import ( "github.com/hashicorp/boundary/internal/db" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestRootKey(t *testing.T, conn *gorm.DB, scopeId string) *RootKey { diff --git a/internal/oplog/oplog.go b/internal/oplog/oplog.go index 2236d5820..aa6c0a2a1 100644 --- a/internal/oplog/oplog.go +++ b/internal/oplog/oplog.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/boundary/internal/oplog/store" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/structwrapping" - _ "github.com/lib/pq" "google.golang.org/protobuf/proto" ) @@ -29,8 +28,8 @@ type Message struct { // Entry represents an oplog entry type Entry struct { *store.Entry - Cipherer wrapping.Wrapper `sql:"-"` - Ticketer Ticketer `sql:"-"` + Cipherer wrapping.Wrapper `gorm:"-"` + Ticketer Ticketer `gorm:"-"` } // Metadata provides meta information about the Entry diff --git a/internal/oplog/oplog_test.go b/internal/oplog/oplog_test.go index 0c28c00fc..c7fc4c8a1 100644 --- a/internal/oplog/oplog_test.go +++ b/internal/oplog/oplog_test.go @@ -8,9 +8,10 @@ import ( dbassert "github.com/hashicorp/dbassert/gorm" "github.com/hashicorp/boundary/internal/oplog/oplog_test" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/driver/postgres" + "gorm.io/gorm" _ "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file" @@ -22,12 +23,38 @@ func setup(t *testing.T) (func() error, *gorm.DB) { require := require.New(t) cleanup, url, err := testInitDbInDocker(t) require.NoError(err) - db, err := gorm.Open("postgres", url) + db, err := testOpen("postgres", url) + require.NoError(err) + oplog_test.Init(db) + t.Cleanup(func() { + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, sqlDB.Close(), "Got error closing gorm db.") + }) require.NoError(err) oplog_test.Init(db) return cleanup, db } +func testOpen(dbType string, connectionUrl string) (*gorm.DB, error) { + var dialect gorm.Dialector + switch dbType { + case "postgres": + dialect = postgres.New(postgres.Config{ + DSN: connectionUrl}, + ) + default: + return nil, fmt.Errorf("unable to open %s database type", dbType) + } + db, err := gorm.Open(dialect, &gorm.Config{ + ConvertNullToZeroValues: true, + }) + if err != nil { + return nil, fmt.Errorf("unable to open database: %w", err) + } + return db, nil +} + // Test_BasicOplog provides some basic unit tests for oplogs func Test_BasicOplog(t *testing.T) { cleanup, db := setup(t) @@ -228,6 +255,7 @@ func Test_UnmarshalData(t *testing.T) { // now let's us optimistic locking via a ticketing system for a serialized oplog ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + require.NoError(t, err) types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) require.NoError(t, err) @@ -390,7 +418,9 @@ func Test_Replay(t *testing.T) { } err = tx.Model(&userUpdate).Updates(map[string]interface{}{"PhoneNumber": "867-5309", "Name": gorm.Expr("NULL")}).Error require.NoError(err) - dbassert := dbassert.New(t, tx.DB(), "postgres") + underlyingDB, err := tx.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB, tx.Dialector.Name()) dbassert.IsNull(&userUpdate, "Name") foundCreateUser := testFindUser(t, tx, userCreate.Id) diff --git a/internal/oplog/oplog_test/db.go b/internal/oplog/oplog_test/db.go index 7fad2f8e2..f3a6ea4b6 100644 --- a/internal/oplog/oplog_test/db.go +++ b/internal/oplog/oplog_test/db.go @@ -1,7 +1,7 @@ // Package oplog_test provides some gorm helper funcs for testing oplog database integrations package oplog_test -import "github.com/jinzhu/gorm" +import "gorm.io/gorm" const ( defaultTestUserTableName = "oplog_test_user" @@ -18,9 +18,10 @@ func Init(db *gorm.DB) { // Reinit will use gorm to drop then init tables for test models func Reinit(db *gorm.DB) { - db.DropTableIfExists(&TestUser{}) - db.DropTableIfExists(&TestCar{}) - db.DropTableIfExists(&TestRental{}) + // Migrator.DropTable is actually "drop table if exists" + _ = db.Migrator().DropTable(&TestUser{}) + _ = db.Migrator().DropTable(&TestCar{}) + _ = db.Migrator().DropTable(&TestRental{}) Init(db) } diff --git a/internal/oplog/testing.go b/internal/oplog/testing.go index 5476b6b91..f8d7bdc17 100644 --- a/internal/oplog/testing.go +++ b/internal/oplog/testing.go @@ -12,16 +12,18 @@ import ( wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func testCleanup(t *testing.T, cleanupFunc func() error, db *gorm.DB) { t.Helper() err := cleanupFunc() assert.NoError(t, err) - err = db.Close() + sqlDB, err := db.DB() + assert.NoError(t, err) + err = sqlDB.Close() assert.NoError(t, err) } diff --git a/internal/oplog/ticketer.go b/internal/oplog/ticketer.go index 3fb19cb6a..744096a91 100644 --- a/internal/oplog/ticketer.go +++ b/internal/oplog/ticketer.go @@ -3,7 +3,7 @@ package oplog import ( "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog/store" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) const DefaultAggregateName = "global" @@ -53,7 +53,7 @@ func (ticketer *GormTicketer) GetTicket(aggregateName string) (*store.Ticket, er } ticket := store.Ticket{} if err := ticketer.tx.First(&ticket, store.Ticket{Name: name}).Error; err != nil { - if gorm.IsRecordNotFoundError(err) { + if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.NewDeprecated(errors.TicketNotFound, op, "ticket not found") } return nil, errors.WrapDeprecated(err, op, errors.WithMsg("error retrieving ticket from storage")) diff --git a/internal/oplog/writer.go b/internal/oplog/writer.go index 4fbb5d00a..d175ce7f6 100644 --- a/internal/oplog/writer.go +++ b/internal/oplog/writer.go @@ -4,8 +4,10 @@ import ( "fmt" "github.com/hashicorp/boundary/internal/db/common" + "github.com/hashicorp/boundary/internal/errors" - "github.com/jinzhu/gorm" + "gorm.io/gorm" + "gorm.io/gorm/schema" ) // Writer interface for Entries @@ -47,8 +49,15 @@ func (w *GormWriter) Create(i interface{}) error { if i == nil { return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") } - if err := w.Tx.Create(i).Error; err != nil { - return errors.WrapDeprecated(err, op) + + if tabler, ok := i.(schema.Tabler); ok { + if err := w.Tx.Table(tabler.TableName()).Create(i).Error; err != nil { + return errors.WrapDeprecated(err, op) + } + } else { + if err := w.Tx.Create(i).Error; err != nil { + return errors.WrapDeprecated(err, op) + } } return nil } @@ -73,8 +82,15 @@ func (w *GormWriter) Update(i interface{}, fieldMaskPaths, setToNullPaths []stri if err != nil { return errors.WrapDeprecated(err, op, errors.WithMsg("unable to build update fields")) } - if err := w.Tx.Model(i).Updates(updateFields).Error; err != nil { - return errors.WrapDeprecated(err, op) + + if tabler, ok := i.(schema.Tabler); ok { + if err := w.Tx.Table(tabler.TableName()).Model(i).Updates(updateFields).Error; err != nil { + return errors.WrapDeprecated(err, op) + } + } else { + if err := w.Tx.Model(i).Updates(updateFields).Error; err != nil { + return errors.WrapDeprecated(err, op) + } } return nil } @@ -88,8 +104,14 @@ func (w *GormWriter) Delete(i interface{}) error { if i == nil { return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") } - if err := w.Tx.Delete(i).Error; err != nil { - return errors.WrapDeprecated(err, op) + if tabler, ok := i.(schema.Tabler); ok { + if err := w.Tx.Table(tabler.TableName()).Delete(i).Error; err != nil { + return errors.WrapDeprecated(err, op) + } + } else { + if err := w.Tx.Delete(i).Error; err != nil { + return errors.WrapDeprecated(err, op) + } } return nil } @@ -99,7 +121,7 @@ func (w *GormWriter) hasTable(tableName string) bool { if tableName == "" { return false } - return w.Tx.Dialect().HasTable(tableName) + return w.Tx.Migrator().HasTable(tableName) } // CreateTableLike will create a newTableName like the model's table @@ -112,10 +134,11 @@ func (w *GormWriter) createTableLike(existingTableName string, newTableName stri if newTableName == "" { return errors.NewDeprecated(errors.InvalidParameter, op, "missing new table name") } - existingTableName = w.Tx.Dialect().Quote(existingTableName) - newTableName = w.Tx.Dialect().Quote(newTableName) + + existingTableName = w.Tx.Statement.Quote(existingTableName) + newTableName = w.Tx.Statement.Quote(newTableName) var sql string - switch w.Tx.Dialect().GetName() { + switch w.Tx.Dialector.Name() { case "postgres": sql = fmt.Sprintf( `CREATE TABLE %s ( LIKE %s INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES );`, @@ -143,7 +166,8 @@ func (w *GormWriter) dropTableIfExists(tableName string) error { if tableName == "" { return errors.NewDeprecated(errors.InvalidParameter, op, "missing table name") } - err := w.Tx.DropTableIfExists(tableName).Error + // Migrator.DropTable uses an "if exists" clause + err := w.Tx.Migrator().DropTable(tableName) if err != nil { return errors.WrapDeprecated(err, op) } diff --git a/internal/oplog/writer_test.go b/internal/oplog/writer_test.go index 72c482243..f3930d722 100644 --- a/internal/oplog/writer_test.go +++ b/internal/oplog/writer_test.go @@ -5,9 +5,10 @@ import ( "github.com/hashicorp/boundary/internal/oplog/oplog_test" dbassert "github.com/hashicorp/dbassert/gorm" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + _ "gorm.io/driver/postgres" + "gorm.io/gorm" ) // Test_GormWriterCreate provides unit tests for GormWriter Create @@ -290,7 +291,10 @@ func TestGormWriter_Update(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert, require, dbassert := assert.New(t), require.New(t), dbassert.New(t, db.DB(), "postgres") + assert, require := assert.New(t), require.New(t) + underlyingDB, err := db.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB, db.Dialector.Name()) w := &GormWriter{ Tx: tt.Tx, @@ -299,7 +303,7 @@ func TestGormWriter_Update(t *testing.T) { u.Name = tt.args.user.Name u.Email = tt.args.user.Email u.PhoneNumber = tt.args.user.PhoneNumber - err := w.Update(tt.args.user, tt.args.fieldMaskPaths, tt.args.setToNullPaths) + err = w.Update(u, tt.args.fieldMaskPaths, tt.args.setToNullPaths) if tt.wantErr { require.Error(err) return diff --git a/internal/proto/local/controller/servers/v1/servers.proto b/internal/proto/local/controller/servers/v1/servers.proto index cc02349f3..7adf4bbb3 100644 --- a/internal/proto/local/controller/servers/v1/servers.proto +++ b/internal/proto/local/controller/servers/v1/servers.proto @@ -32,6 +32,7 @@ message Server { storage.timestamp.v1.Timestamp update_time = 70; // Tags for workers + // @inject_tag: `gorm:"-"` map tags = 80; } diff --git a/internal/proto/local/controller/storage/auth/password/store/v1/password.proto b/internal/proto/local/controller/storage/auth/password/store/v1/password.proto index 5d1e1e0f1..25adc39cc 100644 --- a/internal/proto/local/controller/storage/auth/password/store/v1/password.proto +++ b/internal/proto/local/controller/storage/auth/password/store/v1/password.proto @@ -45,7 +45,7 @@ message AuthMethod { // is_primary_auth_method is a read-only output field which indicates if the // auth method is set as the scope's primary auth method. - // @inject_tag: `gorm:"-"` + // @inject_tag: `gorm:"->"` bool is_primary_auth_method = 20; } diff --git a/internal/proto/local/controller/storage/authtoken/store/v1/authtoken.proto b/internal/proto/local/controller/storage/authtoken/store/v1/authtoken.proto index 412748994..d4ab6982b 100644 --- a/internal/proto/local/controller/storage/authtoken/store/v1/authtoken.proto +++ b/internal/proto/local/controller/storage/authtoken/store/v1/authtoken.proto @@ -43,15 +43,15 @@ message AuthToken { string auth_account_id = 10; // scope_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" + // @inject_tag: gorm:"->" string scope_id = 11; // auth_method_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" + // @inject_tag: gorm:"->" string auth_method_id = 12; // iam_user_id is not stored in the backing DB but it derived from the linked to auth account. - // @inject_tag: gorm:"-" + // @inject_tag: gorm:"->" string iam_user_id = 13; // key_id is the key ID that was used for the encryption operation. It can be diff --git a/internal/proto/local/controller/storage/iam/store/v1/user.proto b/internal/proto/local/controller/storage/iam/store/v1/user.proto index 8b454ad8b..e85f0ccca 100644 --- a/internal/proto/local/controller/storage/iam/store/v1/user.proto +++ b/internal/proto/local/controller/storage/iam/store/v1/user.proto @@ -38,21 +38,21 @@ message User { // Output only. login_name is a string that maps to the user's account "login // name" from the scope's primary auth method - // @inject_tag: `gorm:"-"` + // @inject_tag: `gorm:"->"` string login_name = 90 [json_name = "login_name"]; // Output only. full_name is a string that maps to the user's account name // from the scope's primary auth method - // @inject_tag: `gorm:"-"` + // @inject_tag: `gorm:"->"` string full_name = 100 [json_name = "full_name"]; // Output only. email is a string that maps to the user's account email from // the scope's primary auth method - // @inject_tag: `gorm:"-"` + // @inject_tag: `gorm:"->"` string email = 110 [json_name = "email"]; // Output only. primary_account_id is a string that maps to the user's account // public_id from the scope's primary auth method - // @inject_tag: `gorm:"-"` + // @inject_tag: `gorm:"->"` string primary_account_id = 120 [json_name = "primary_account_id"]; } \ No newline at end of file diff --git a/internal/proto/local/controller/storage/job/store/v1/job.proto b/internal/proto/local/controller/storage/job/store/v1/job.proto index ee110bf06..7adcfee31 100644 --- a/internal/proto/local/controller/storage/job/store/v1/job.proto +++ b/internal/proto/local/controller/storage/job/store/v1/job.proto @@ -26,7 +26,7 @@ message Job { message JobRun { // private_id is used to access the job run but not intended to be available via the API - // @inject_tag: `gorm:"primary_key"` + // @inject_tag: `gorm:"primary_key;default:null"` string private_id = 1; // The job_plugin_id is the id of the plugin that owns the job. diff --git a/internal/scheduler/job/additional_verification_test.go b/internal/scheduler/job/additional_verification_test.go index 420ff74f0..7d5474e4a 100644 --- a/internal/scheduler/job/additional_verification_test.go +++ b/internal/scheduler/job/additional_verification_test.go @@ -2,6 +2,7 @@ package job import ( "context" + "database/sql" "testing" "time" @@ -100,24 +101,24 @@ func TestPlugin(t *testing.T) { rw := db.New(conn) rows, err := rw.Query(context.Background(), createJobQuery, []interface{}{ - defaultPluginId, - "same-job-name", - "description", - 0, + sql.Named("plugin_id", defaultPluginId), + sql.Named("name", "same-job-name"), + sql.Named("description", "description"), + sql.Named("next_scheduled_run", 0), }) require.NoError(err) _ = rows.Close() // Creating a job with same name and pluginId should return a unique constraint error rows, err = rw.Query(context.Background(), createJobQuery, []interface{}{ - defaultPluginId, - "same-job-name", - "description", - 0, + sql.Named("plugin_id", defaultPluginId), + sql.Named("name", "same-job-name"), + sql.Named("description", "description"), + sql.Named("next_scheduled_run", 0), }) require.Error(err) assert.Nil(rows) - assert.Equal("pq: duplicate key value violates unique constraint \"job_pkey\"", err.Error()) + assert.Contains(err.Error(), "duplicate key value violates unique constraint \"job_pkey\"") // Create test plugin id testPluginId := "pi_test1234" @@ -127,24 +128,24 @@ func TestPlugin(t *testing.T) { // Creating the a job with the same name and different pluginId should succeed rows, err = rw.Query(context.Background(), createJobQuery, []interface{}{ - testPluginId, - "same-job-name", - "description", - 0, + sql.Named("plugin_id", testPluginId), + sql.Named("name", "same-job-name"), + sql.Named("description", "description"), + sql.Named("next_scheduled_run", 0), }) assert.NoError(err) _ = rows.Close() // Creating a job with same name and pluginId should again return a unique constraint error rows, err = rw.Query(context.Background(), createJobQuery, []interface{}{ - testPluginId, - "same-job-name", - "description", - 0, + sql.Named("plugin_id", testPluginId), + sql.Named("name", "same-job-name"), + sql.Named("description", "description"), + sql.Named("next_scheduled_run", 0), }) require.Error(err) assert.Nil(rows) - assert.Equal("pq: duplicate key value violates unique constraint \"job_pkey\"", err.Error()) + assert.Contains(err.Error(), "duplicate key value violates unique constraint \"job_pkey\"") }) t.Run("plugin-id-immutable", func(t *testing.T) { assert, require := assert.New(t), require.New(t) diff --git a/internal/scheduler/job/query.go b/internal/scheduler/job/query.go index fc057d4c3..7a20a70ad 100644 --- a/internal/scheduler/job/query.go +++ b/internal/scheduler/job/query.go @@ -14,15 +14,15 @@ const runJobsQuery = ` const createJobQuery = ` insert into job ( - plugin_id, -- $1 - name, -- $2 - description, -- $3 - next_scheduled_run -- $4 + plugin_id, + name, + description, + next_scheduled_run ) values ( - $1, -- plugin_id - $2, -- name - $3, -- description - wt_add_seconds_to_now($4) -- next_scheduled_run + @plugin_id, -- plugin_id + @name, -- name + @description, -- description + wt_add_seconds_to_now(@next_scheduled_run) -- next_scheduled_run ) returning *; ` @@ -101,3 +101,10 @@ const interruptRunsQuery = ` %s returning *; ` + +const deleteJobByName = ` + delete + from job + where + name = ? +` diff --git a/internal/scheduler/job/repository_job.go b/internal/scheduler/job/repository_job.go index 73aceb2f8..8ef11d117 100644 --- a/internal/scheduler/job/repository_job.go +++ b/internal/scheduler/job/repository_job.go @@ -2,6 +2,7 @@ package job import ( "context" + "database/sql" "fmt" "strings" "time" @@ -28,14 +29,16 @@ func (r *Repository) CreateJob(ctx context.Context, name, description string, op opts := getOpts(opt...) + defaultId := defaultPluginId + j := allocJob() _, err := r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error { rows, err := r.Query(ctx, createJobQuery, []interface{}{ - defaultPluginId, - name, - description, - int(opts.withNextRunIn.Round(time.Second).Seconds()), + sql.Named("plugin_id", defaultId), + sql.Named("name", name), + sql.Named("description", description), + sql.Named("next_scheduled_run", int(opts.withNextRunIn.Round(time.Second).Seconds())), }) if err != nil { return errors.Wrap(ctx, err, op, errors.WithoutEvent()) @@ -171,12 +174,11 @@ func (r *Repository) deleteJob(ctx context.Context, name string, _ ...Option) (i return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing name") } - j := allocJob() var rowsDeleted int _, err := r.writer.DoTx( ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) (err error) { - rowsDeleted, err = w.Delete(ctx, j, db.WithWhere("name = ?", []interface{}{name})) + rowsDeleted, err = w.Exec(ctx, deleteJobByName, []interface{}{name}) if err != nil { return errors.Wrap(ctx, err, op) } diff --git a/internal/scheduler/job/repository_run_test.go b/internal/scheduler/job/repository_run_test.go index 879963630..8cd810298 100644 --- a/internal/scheduler/job/repository_run_test.go +++ b/internal/scheduler/job/repository_run_test.go @@ -542,7 +542,7 @@ func TestRepository_CompleteRun(t *testing.T) { var privateId string if tt.orig != nil { err = rw.Create(context.Background(), tt.orig) - assert.NoError(err) + require.NoError(err) assert.Empty(tt.orig.EndTime) privateId = tt.orig.PrivateId } @@ -1112,7 +1112,7 @@ func TestRepository_DuplicateJobRun(t *testing.T) { run, err = testRun(conn, job1.PluginId, job1.Name, server.PrivateId) require.Error(err) require.Nil(run) - assert.Equal("pq: duplicate key value violates unique constraint \"job_run_status_constraint\"", err.Error()) + assert.Contains(err.Error(), "duplicate key value violates unique constraint \"job_run_status_constraint\"") // Creating a new job with a different name, the associated run should not conflict with the previous run job2 := testJob(t, conn, "job2", "description", wrapper) diff --git a/internal/scheduler/job/store/job.pb.go b/internal/scheduler/job/store/job.pb.go index 087eb8df3..a4b84ba81 100644 --- a/internal/scheduler/job/store/job.pb.go +++ b/internal/scheduler/job/store/job.pb.go @@ -108,8 +108,8 @@ type JobRun struct { unknownFields protoimpl.UnknownFields // private_id is used to access the job run but not intended to be available via the API - // @inject_tag: `gorm:"primary_key"` - PrivateId string `protobuf:"bytes,1,opt,name=private_id,json=privateId,proto3" json:"private_id,omitempty" gorm:"primary_key"` + // @inject_tag: `gorm:"primary_key;default:null"` + PrivateId string `protobuf:"bytes,1,opt,name=private_id,json=privateId,proto3" json:"private_id,omitempty" gorm:"primary_key;default:null"` // The job_plugin_id is the id of the plugin that owns the job. // @inject_tag: `gorm:"not_null"` JobPluginId string `protobuf:"bytes,2,opt,name=job_plugin_id,json=jobPluginId,proto3" json:"job_plugin_id,omitempty" gorm:"not_null"` diff --git a/internal/scheduler/job/testing.go b/internal/scheduler/job/testing.go index e63d60c25..69552c4b3 100644 --- a/internal/scheduler/job/testing.go +++ b/internal/scheduler/job/testing.go @@ -11,8 +11,8 @@ import ( "github.com/hashicorp/boundary/internal/servers" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func testJob(t *testing.T, conn *gorm.DB, name, description string, wrapper wrapping.Wrapper, opt ...Option) *Job { diff --git a/internal/scheduler/testing.go b/internal/scheduler/testing.go index 8de49b3ce..d28e556ba 100644 --- a/internal/scheduler/testing.go +++ b/internal/scheduler/testing.go @@ -13,8 +13,8 @@ import ( "github.com/hashicorp/boundary/internal/servers" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) // TestScheduler creates a mock controller and a new Scheduler attached to that controller id. diff --git a/internal/servers/controller/handlers/authmethods/oidc_test.go b/internal/servers/controller/handlers/authmethods/oidc_test.go index 16648390f..2f6ed2ca4 100644 --- a/internal/servers/controller/handlers/authmethods/oidc_test.go +++ b/internal/servers/controller/handlers/authmethods/oidc_test.go @@ -32,7 +32,6 @@ import ( scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" capoidc "github.com/hashicorp/cap/oidc" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/genproto/protobuf/field_mask" @@ -42,6 +41,7 @@ import ( "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" + "gorm.io/gorm" ) type setup struct { diff --git a/internal/servers/controller/handlers/host_sets/host_set_service_test.go b/internal/servers/controller/handlers/host_sets/host_set_service_test.go index 298a54e17..c08efc732 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service_test.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "sort" "strings" "testing" @@ -827,6 +828,17 @@ func TestUpdate(t *testing.T) { if tc.res != nil { tc.res.Item.Version = version + 1 } + if tc.res != nil { + sort.Slice(tc.res.GetItem().HostIds, func(i, j int) bool { + return tc.res.GetItem().HostIds[i] < tc.res.GetItem().HostIds[j] + }) + } + if got != nil && got.Item != nil { + sort.Slice(got.GetItem().HostIds, func(i, j int) bool { + return got.GetItem().HostIds[i] < got.GetItem().HostIds[j] + }) + } + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateHostSet(%q) got response %q, wanted %q", req, got, tc.res) }) } diff --git a/internal/servers/controller/handlers/targets/target_service_test.go b/internal/servers/controller/handlers/targets/target_service_test.go index 19f9ac908..777a815db 100644 --- a/internal/servers/controller/handlers/targets/target_service_test.go +++ b/internal/servers/controller/handlers/targets/target_service_test.go @@ -37,7 +37,6 @@ import ( "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/genproto/protobuf/field_mask" @@ -48,6 +47,7 @@ import ( "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" + "gorm.io/gorm" ) var testAuthorizedActions = []string{ diff --git a/internal/servers/controller/testing.go b/internal/servers/controller/testing.go index 79bfa0ed1..f458efcac 100644 --- a/internal/servers/controller/testing.go +++ b/internal/servers/controller/testing.go @@ -26,7 +26,7 @@ import ( wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-secure-stdlib/strutil" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) const ( diff --git a/internal/servers/query.go b/internal/servers/query.go index afc44040f..1e814a853 100644 --- a/internal/servers/query.go +++ b/internal/servers/query.go @@ -5,14 +5,14 @@ const ( insert into server (private_id, type, description, address, update_time) values - ($1, $2, $3, $4, now()) + (@private_id, @type, @description, @address, now()) on conflict on constraint server_pkey do update set - type = $2, - description = $3, - address = $4, + type = @type, + description = @description, + address = @address, update_time = now(); ` - deleteWhereCreateTimeSql = `create_time < $1` - deleteTagsSql = `server_id = $1` + deleteWhereCreateTimeSql = `create_time < ?` + deleteTagsSql = `server_id = ?` ) diff --git a/internal/servers/repository.go b/internal/servers/repository.go index 3ca3784d7..2634e87a7 100644 --- a/internal/servers/repository.go +++ b/internal/servers/repository.go @@ -2,6 +2,7 @@ package servers import ( "context" + "database/sql" "fmt" "time" @@ -80,9 +81,9 @@ func (r *Repository) listServersWithReader(ctx context.Context, reader db.Reader var where string if liveness > 0 { - where = fmt.Sprintf("type = $1 and update_time > now() - interval '%d seconds'", uint32(liveness.Seconds())) + where = fmt.Sprintf("type = ? and update_time > now() - interval '%d seconds'", uint32(liveness.Seconds())) } else { - where = "type = $1" + where = "type = ?" } var servers []*Server @@ -148,10 +149,10 @@ func (r *Repository) UpsertServer(ctx context.Context, server *Server, opt ...Op rowsUpdated, err = w.Exec(ctx, serverUpsertQuery, []interface{}{ - server.PrivateId, - server.Type, - server.Description, - server.Address, + sql.Named("private_id", server.PrivateId), + sql.Named("type", server.Type), + sql.Named("description", server.Description), + sql.Named("address", server.Address), }) if err != nil { return errors.Wrap(ctx, err, op+":Upsert") diff --git a/internal/servers/repository_test.go b/internal/servers/repository_test.go index 8dda2a7bb..30ed1c8ed 100644 --- a/internal/servers/repository_test.go +++ b/internal/servers/repository_test.go @@ -102,6 +102,7 @@ func TestTagUpdatingListing(t *testing.T) { }, }, } + _, _, err := repo.UpsertServer(tc.Context(), srv, servers.WithUpdateTags(true)) require.NoError(err) diff --git a/internal/servers/servers.pb.go b/internal/servers/servers.pb.go index cb1012f11..b5fad0c29 100644 --- a/internal/servers/servers.pb.go +++ b/internal/servers/servers.pb.go @@ -47,7 +47,8 @@ type Server struct { // Last time there was an update UpdateTime *timestamp.Timestamp `protobuf:"bytes,70,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` // Tags for workers - Tags map[string]*TagValues `protobuf:"bytes,80,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // @inject_tag: `gorm:"-"` + Tags map[string]*TagValues `protobuf:"bytes,80,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" gorm:"-"` } func (x *Server) Reset() { diff --git a/internal/session/query.go b/internal/session/query.go index 476bd0e2d..8218e43f5 100644 --- a/internal/session/query.go +++ b/internal/session/query.go @@ -16,9 +16,9 @@ with not_active as ( where s.public_id = ss.session_id and ss.state = 'pending' and - ss.session_id = $1 and - s.version = $2 and - s.public_id not in(select session_id from session_state where session_id = $1 and state = 'active') + ss.session_id = @session_id and + s.version = @version and + s.public_id not in(select session_id from session_state where session_id = @session_id and state = 'active') ) select * from not_active; ` @@ -29,11 +29,11 @@ select * from not_active; updateSessionState = ` insert into session_state(session_id, state) select - $1::text, $2 + @session_id, @status from session s where - s.public_id = $1::text and + s.public_id = @session_id and s.public_id not in ( select session_id @@ -42,8 +42,8 @@ where where -- already in the updated state ( - session_id = $1::text and - state = $2 + session_id = @session_id and + state = @status ) or -- already terminated session_id in ( @@ -52,7 +52,7 @@ where from session_state where - session_id = $1::text and + session_id = @session_id and state = 'terminated' ) ) @@ -65,7 +65,7 @@ with terminated as ( from session s where - s.version = $2 and + s.version = @version and s.public_id in ( -- sessions without any connections select s.public_id @@ -74,7 +74,7 @@ with terminated as ( left join session_connection sc on sc.session_id = s.public_id where sc.session_id is null - and s.public_id = $1 + and s.public_id = @session_id union -- sessions where all connections are closed select s.public_id @@ -86,7 +86,7 @@ with terminated as ( s.public_id = c.session_id and c.public_id = cs.connection_id and cs.state = 'closed' and - s.public_id = $1 + s.public_id = @session_id ) ) select * from terminated; @@ -99,9 +99,9 @@ insert into session_connection ( ) with active_session as ( select - $1 as session_id, - $2 as public_id, - $3 as server_id + @session_id as session_id, + @public_id as public_id, + @worker_id as server_id from session s where @@ -111,7 +111,7 @@ with active_session as ( ( s.connection_limit = -1 or - s.connection_limit > (select count(*) from session_connection sc where sc.session_id = $1) + s.connection_limit > (select count(*) from session_connection sc where sc.session_id = @session_id) ) and -- check that there's a state of active s.public_id in ( @@ -120,7 +120,7 @@ with active_session as ( from session_state ss where - ss.session_id = $1 and + ss.session_id = @session_id and ss.state = 'active' and -- if there's no end_time, then this is the current state. ss.end_time is null @@ -136,7 +136,7 @@ session_connection_count(current_connection_count) as ( from session_connection sc where - sc.session_id = $1 + sc.session_id = @session_id ), session_connection_limit(expiration_time, connection_limit) as ( select @@ -145,7 +145,7 @@ session_connection_limit(expiration_time, connection_limit) as ( from session s where - s.public_id = $1 + s.public_id = @session_id ) select expiration_time, connection_limit, current_connection_count from @@ -269,7 +269,7 @@ with from session_connection where -- Related to the worker that just reported to us - server_id = $1 + server_id = ? and -- These are connection IDs that just got reported to us by the given -- worker, so they should not be considered closed. @@ -302,7 +302,7 @@ with dead_servers (server_id, last_update_time) as ( select private_id, update_time from server - where update_time < wt_sub_seconds_from_now($1) + where update_time < wt_sub_seconds_from_now(?) ), closed_connections (connection_id, server_id) as ( update session_connection diff --git a/internal/session/repository_connection.go b/internal/session/repository_connection.go index 8ea77e728..c86d6297e 100644 --- a/internal/session/repository_connection.go +++ b/internal/session/repository_connection.go @@ -2,6 +2,7 @@ package session import ( "context" + "database/sql" "fmt" "strings" "time" @@ -128,8 +129,8 @@ func (r *Repository) CloseDeadConnectionsForWorker(ctx context.Context, serverId publicIdStr = `public_id not in (%s) and` params := make([]string, len(foundConns)) for i, connId := range foundConns { - params[i] = fmt.Sprintf("$%d", i+2) // Add one for server ID, and offsets start at 1 - args = append(args, connId) + params[i] = fmt.Sprintf("@%d", i+2) // Add one for server ID, and offsets start at 1 + args = append(args, sql.Named(fmt.Sprintf("%d", i+2), connId)) } publicIdStr = fmt.Sprintf(publicIdStr, strings.Join(params, ",")) } @@ -224,8 +225,8 @@ func (r *Repository) ShouldCloseConnectionsOnWorker(ctx context.Context, foundCo // foundConns first connsParams := make([]string, len(foundConns)) for i, connId := range foundConns { - connsParams[i] = fmt.Sprintf("$%d", i+1) - args = append(args, connId) + connsParams[i] = fmt.Sprintf("@%d", i+1) + args = append(args, sql.Named(fmt.Sprintf("%d", i+1), connId)) } connsStr := strings.Join(connsParams, ",") @@ -235,8 +236,8 @@ func (r *Repository) ShouldCloseConnectionsOnWorker(ctx context.Context, foundCo offset := len(foundConns) + 1 sessionsParams := make([]string, len(filterSessions)) for i, sessionId := range filterSessions { - sessionsParams[i] = fmt.Sprintf("$%d", i+offset) - args = append(args, sessionId) + sessionsParams[i] = fmt.Sprintf("@%d", i+offset) + args = append(args, sql.Named(fmt.Sprintf("%d", i+offset), sessionId)) } const sessionIdFmtStr = `and session_id not in (%s)` diff --git a/internal/session/repository_connection_test.go b/internal/session/repository_connection_test.go index 106ab50b3..7e51ba65f 100644 --- a/internal/session/repository_connection_test.go +++ b/internal/session/repository_connection_test.go @@ -503,9 +503,9 @@ func TestRepository_CloseConnectionsForDeadWorkers(t *testing.T) { // CloseConnectionsForDeadWorkersResult. timestampPbAsUTC := func(t *testing.T, tm time.Time) time.Time { t.Helper() - utcLoc, err := time.LoadLocation("Etc/UTC") - require.NoError(err) - return tm.In(utcLoc) + // utcLoc, err := time.LoadLocation("Etc/UTC") + // require.NoError(err) + return tm.In(time.Local) } // Now try some scenarios. diff --git a/internal/session/repository_session.go b/internal/session/repository_session.go index 7eaf0da80..f324be3b6 100644 --- a/internal/session/repository_session.go +++ b/internal/session/repository_session.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ed25519" "crypto/subtle" + "database/sql" "fmt" "strings" @@ -206,31 +207,31 @@ func (r *Repository) ListSessions(ctx context.Context, opt ...Option) ([]*Sessio switch len(opts.withScopeIds) { case 1: inClauseCnt += 1 - where, args = append(where, fmt.Sprintf("scope_id = $%d", inClauseCnt)), append(args, opts.withScopeIds[0]) + where, args = append(where, fmt.Sprintf("scope_id = @%d", inClauseCnt)), append(args, sql.Named("1", opts.withScopeIds[0])) default: idsInClause := make([]string, 0, len(opts.withScopeIds)) for _, id := range opts.withScopeIds { inClauseCnt += 1 - idsInClause, args = append(idsInClause, fmt.Sprintf("$%d", inClauseCnt)), append(args, id) + idsInClause, args = append(idsInClause, fmt.Sprintf("@%d", inClauseCnt)), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), id)) } where = append(where, fmt.Sprintf("scope_id in (%s)", strings.Join(idsInClause, ","))) } } if opts.withUserId != "" { inClauseCnt += 1 - where, args = append(where, fmt.Sprintf("user_id = $%d", inClauseCnt)), append(args, opts.withUserId) + where, args = append(where, fmt.Sprintf("user_id = @%d", inClauseCnt)), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), opts.withUserId)) } if len(opts.withSessionIds) > 0 { idsInClause := make([]string, 0, len(opts.withSessionIds)) for _, id := range opts.withSessionIds { inClauseCnt += 1 - idsInClause, args = append(idsInClause, fmt.Sprintf("$%d", inClauseCnt)), append(args, id) + idsInClause, args = append(idsInClause, fmt.Sprintf("@%d", inClauseCnt)), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), id)) } where = append(where, fmt.Sprintf("s.public_id in (%s)", strings.Join(idsInClause, ","))) } if opts.withServerId != "" { inClauseCnt += 1 - where, args = append(where, fmt.Sprintf("server_id = $%d", inClauseCnt)), append(args, opts.withServerId) + where, args = append(where, fmt.Sprintf("server_id = @%d", inClauseCnt)), append(args, sql.Named(fmt.Sprintf("%d", inClauseCnt), opts.withServerId)) } var limit string @@ -360,7 +361,10 @@ func (r *Repository) TerminateSession(ctx context.Context, sessionId string, ses db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { - rowsAffected, err := w.Exec(ctx, terminateSessionCte, []interface{}{sessionId, sessionVersion}) + rowsAffected, err := w.Exec(ctx, terminateSessionCte, []interface{}{ + sql.Named("version", sessionVersion), + sql.Named("session_id", sessionId), + }) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to terminate session %s", sessionId))) } @@ -441,7 +445,11 @@ func (r *Repository) AuthorizeConnection(ctx context.Context, sessionId, workerI db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { - rowsAffected, err := w.Exec(ctx, authorizeConnectionCte, []interface{}{sessionId, connectionId, workerId}) + rowsAffected, err := w.Exec(ctx, authorizeConnectionCte, []interface{}{ + sql.Named("session_id", sessionId), + sql.Named("public_id", connectionId), + sql.Named("worker_id", workerId), + }) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to authorize connection %s", sessionId))) } @@ -476,7 +484,7 @@ type ConnectionAuthzSummary struct { func (r *Repository) sessionAuthzSummary(ctx context.Context, sessionId string) (*ConnectionAuthzSummary, error) { const op = "session.(Repository).sessionAuthzSummary" - rows, err := r.reader.Query(ctx, remainingConnectionsCte, []interface{}{sessionId}) + rows, err := r.reader.Query(ctx, remainingConnectionsCte, []interface{}{sql.Named("session_id", sessionId)}) if err != nil { return nil, errors.Wrap(ctx, err, op) } @@ -645,7 +653,10 @@ func (r *Repository) ActivateSession(ctx context.Context, sessionId string, sess db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { - rowsAffected, err := w.Exec(ctx, activateStateCte, []interface{}{sessionId, sessionVersion}) + rowsAffected, err := w.Exec(ctx, activateStateCte, []interface{}{ + sql.Named("session_id", sessionId), + sql.Named("version", sessionVersion), + }) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to activate session %s", sessionId))) } @@ -742,7 +753,10 @@ func (r *Repository) updateState(ctx context.Context, sessionId string, sessionV updatedSession.CtTofuToken = nil } - rowsAffected, err = w.Exec(ctx, updateSessionState, []interface{}{sessionId, s.String()}) + rowsAffected, err = w.Exec(ctx, updateSessionState, []interface{}{ + sql.Named("session_id", sessionId), + sql.Named("status", s.String()), + }) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to update session %s state to %s", sessionId, s.String()))) } diff --git a/internal/session/repository_session_test.go b/internal/session/repository_session_test.go index 1ccae8c59..9ea29d3d4 100644 --- a/internal/session/repository_session_test.go +++ b/internal/session/repository_session_test.go @@ -17,9 +17,9 @@ import ( "github.com/hashicorp/boundary/internal/target" targetStore "github.com/hashicorp/boundary/internal/target/store" wrapping "github.com/hashicorp/go-kms-wrapping" - "github.com/jinzhu/gorm" - "github.com/lib/pq" + "github.com/jackc/pgconn" "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/gorm" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/iam" @@ -1408,13 +1408,13 @@ func TestRepository_CancelSessionViaFKNull(t *testing.T) { rowsDeleted, err := rw.Delete(context.Background(), tt.cancelFk.fkType) if err != nil { - var pqError *pq.Error + var pqError *pgconn.PgError if errors.As(err, &pqError) { t.Log(pqError.Message) t.Log(pqError.Detail) t.Log(pqError.Where) - t.Log(pqError.Constraint) - t.Log(pqError.Table) + t.Log(pqError.ConstraintName) + t.Log(pqError.TableName) } } require.NoError(err) diff --git a/internal/session/testing.go b/internal/session/testing.go index 8a67e19e4..445ff499e 100644 --- a/internal/session/testing.go +++ b/internal/session/testing.go @@ -18,9 +18,9 @@ import ( wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/gorm" ) // TestConnection creates a test connection for the sessionId in the repository. diff --git a/internal/target/query.go b/internal/target/query.go index afc3b4d81..7dc5c09a4 100644 --- a/internal/target/query.go +++ b/internal/target/query.go @@ -13,7 +13,7 @@ current_libraries (library_id) as ( -- returns the current list select credential_library_id from target_credential_library - where target_id = $1 + where target_id = @target_id ), keep_libraries (library_id) as ( -- returns the KEEP list diff --git a/internal/target/repository_credential_source.go b/internal/target/repository_credential_source.go index d4f0a7ca0..2ebb5449f 100644 --- a/internal/target/repository_credential_source.go +++ b/internal/target/repository_credential_source.go @@ -2,6 +2,7 @@ package target import ( "context" + "database/sql" "fmt" "strings" @@ -353,9 +354,9 @@ type change struct { func (r *Repository) changes(ctx context.Context, targetId string, clIds []string) ([]*change, error) { const op = "target.(Repository).changes" var inClauseSpots []string - // starts at 2 because there is already a $1 in the query + // starts at 2 because there is already a @1 in the query for i := 2; i < len(clIds)+2; i++ { - inClauseSpots = append(inClauseSpots, fmt.Sprintf("$%d", i)) + inClauseSpots = append(inClauseSpots, fmt.Sprintf("@%d", i)) } inClause := strings.Join(inClauseSpots, ",") if inClause == "" { @@ -364,9 +365,9 @@ func (r *Repository) changes(ctx context.Context, targetId string, clIds []strin query := fmt.Sprintf(setChangesQuery, inClause) var params []interface{} - params = append(params, targetId) - for _, id := range clIds { - params = append(params, id) + params = append(params, sql.Named("target_id", targetId)) + for idx, id := range clIds { + params = append(params, sql.Named(fmt.Sprintf("%d", idx+2), id)) } rows, err := r.reader.Query(ctx, query, params) if err != nil { diff --git a/internal/target/repository_tcp_target_test.go b/internal/target/repository_tcp_target_test.go index 36274d029..02b3bfd65 100644 --- a/internal/target/repository_tcp_target_test.go +++ b/internal/target/repository_tcp_target_test.go @@ -491,7 +491,9 @@ func TestRepository_UpdateTcpTarget(t *testing.T) { foundTarget, _, _, err := repo.LookupTarget(context.Background(), target.PublicId) assert.NoError(err) assert.True(proto.Equal(targetAfterUpdate.((*TcpTarget)), foundTarget.((*TcpTarget)))) - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) if tt.args.description == "" { assert.Equal(foundTarget.GetDescription(), "") dbassert.IsNull(foundTarget, "description") diff --git a/internal/target/tcp_target_test.go b/internal/target/tcp_target_test.go index 1b2d4964a..e0890e55e 100644 --- a/internal/target/tcp_target_test.go +++ b/internal/target/tcp_target_test.go @@ -279,7 +279,9 @@ func TestTcpTarget_Update(t *testing.T) { require.NoError(err) assert.True(proto.Equal(updateTarget, foundTarget)) if len(tt.args.nullPaths) != 0 { - dbassert := dbassert.New(t, conn.DB()) + underlyingDB, err := conn.DB() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB) for _, f := range tt.args.nullPaths { dbassert.IsNull(&foundTarget, f) } diff --git a/internal/target/testing.go b/internal/target/testing.go index 6be140c5f..38b35d6e8 100644 --- a/internal/target/testing.go +++ b/internal/target/testing.go @@ -7,8 +7,8 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/go-uuid" - "github.com/jinzhu/gorm" "github.com/stretchr/testify/require" + "gorm.io/gorm" ) func TestTcpTarget(t *testing.T, conn *gorm.DB, scopeId, name string, opt ...Option) *TcpTarget {