diff --git a/go.mod b/go.mod index e07037ca3..d15ef2a0f 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ replace github.com/hashicorp/boundary/sdk => ./sdk require ( github.com/armon/go-metrics v0.3.9 - github.com/bufbuild/buf v0.37.0 + github.com/bufbuild/buf v0.56.0 github.com/fatih/color v1.13.0 github.com/fatih/structs v1.1.0 github.com/favadi/protoc-go-inject-tag v1.3.0 @@ -28,7 +28,7 @@ require ( github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239 github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/go-cleanhttp v0.5.2 - github.com/hashicorp/go-hclog v0.16.2 + github.com/hashicorp/go-hclog v1.0.0 github.com/hashicorp/go-kms-wrapping v0.6.6 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.0 @@ -73,24 +73,26 @@ require ( go.uber.org/atomic v1.9.0 golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/term v0.0.0-20210916214954-140adaaadfaf - golang.org/x/tools v0.1.6 + golang.org/x/tools v0.1.8-0.20211102182255-bb4add04ddef google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 - google.golang.org/grpc v1.40.0 + google.golang.org/grpc v1.41.0-dev.0.20210907181116-2f3355d2244e google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 google.golang.org/protobuf v1.27.1 gorm.io/driver/postgres v1.2.2 gorm.io/gorm v1.22.3 - mvdan.cc/gofumpt v0.1.1 + mvdan.cc/gofumpt v0.2.0 nhooyr.io/websocket v1.8.7 ) +require github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff // this is a branch and should be updated before merging + require ( github.com/hashicorp/go-sockaddr v1.0.2 - golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 + golang.org/x/sys v0.0.0-20211210111614-af8b64212486 ) require ( - cloud.google.com/go v0.65.0 // indirect + cloud.google.com/go v0.81.0 // indirect github.com/AlecAivazis/survey/v2 v2.2.9 // indirect github.com/Azure/azure-sdk-for-go v58.0.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect @@ -132,7 +134,7 @@ require ( github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/form3tech-oss/jwt-go v3.2.2+incompatible // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/gofrs/flock v0.8.0 // indirect + github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect @@ -159,18 +161,19 @@ require ( github.com/jackc/pgtype v1.9.0 // indirect github.com/jefferai/go-libsecret v0.0.0-20210105015933-d08a58b018bc // indirect github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f // indirect - github.com/jhump/protoreflect v1.8.1 // indirect + github.com/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e // indirect github.com/jinzhu/gorm v1.9.12 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/json-iterator/go v1.1.10 // indirect + github.com/json-iterator/go v1.1.11 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect - github.com/klauspost/compress v1.11.7 // indirect + github.com/klauspost/compress v1.13.5 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/lib/pq v1.10.2 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect @@ -186,32 +189,36 @@ require ( github.com/opencontainers/runc v1.0.0-rc9 // indirect github.com/oracle/oci-go-sdk v12.5.0+incompatible // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect - github.com/pkg/profile v1.5.0 // indirect + github.com/pkg/profile v1.6.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.6.2 // indirect + github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/sirupsen/logrus v1.7.0 // indirect - github.com/spf13/cobra v1.1.1 // indirect + github.com/spf13/cobra v1.2.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/twitchtv/twirp v7.1.0+incompatible // indirect + github.com/twitchtv/twirp v8.1.0+incompatible // indirect github.com/urfave/cli/v2 v2.3.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.opencensus.io v0.22.6 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.16.0 // indirect - golang.org/x/mod v0.4.2 // indirect + github.com/xo/dburl v0.9.0 // indirect + go.opencensus.io v0.23.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.0 // indirect + golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.30.0 // indirect + google.golang.org/api v0.44.0 // indirect google.golang.org/appengine v1.6.7 // indirect - gopkg.in/ini.v1 v1.51.0 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + gorm.io/driver/sqlite v1.2.4 // indirect + gotest.tools/v3 v3.0.3 // indirect ) diff --git a/go.sum b/go.sum index 0841662b2..ac35c0580 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,13 @@ cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.63.0/go.mod h1:GmezbQc7T2snqkEXWfZ0sy0VfkB/ivI2DdtJL2DEmlg= cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4= -cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -88,7 +93,6 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= @@ -145,6 +149,8 @@ github.com/aws/aws-sdk-go v1.40.55 h1:l5xNBmafEAfdJIIe32QbTLG3j/JscH8fzZqYyMlntu github.com/aws/aws-sdk-go v1.40.55/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= 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/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -154,10 +160,10 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bufbuild/buf v0.37.0 h1:11zJVA0D4uJVGOC9h+oOVHrKKoBgMYIqJJ0d1Xt6oeQ= -github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= +github.com/bufbuild/buf v0.56.0 h1:oBx0OPMc62HE73dXLQWu6AH+WzA0h0p8/TyA1JeVhks= +github.com/bufbuild/buf v0.56.0/go.mod h1:IGK996ntty37odzh5iWRUrK7G16Y8GYE8484mhXZxak= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= 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= @@ -175,8 +181,10 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp 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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 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/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/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= @@ -197,14 +205,12 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -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.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 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-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -223,7 +229,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xb github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec h1:NfhRXXFDPxcF5Cwo06DzeIaE7uuJtAUhsDwH3LNsjos= github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dhui/dktest v0.3.3/go.mod h1:EML9sP4sqJELHn4jV7B0TY8oF6077nk83/tz7M56jcQ= github.com/dhui/dktest v0.3.4 h1:VbUEcaSP+U2/yUr9d2JhSThXYEnDlGabRSHe2rIE46E= github.com/dhui/dktest v0.3.4/go.mod h1:4m4n6lmXlmVfESth7mzdcv8nBI5mOb5UROPqjM02csU= @@ -250,8 +255,11 @@ github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt 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= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= @@ -267,9 +275,11 @@ github.com/favadi/protoc-go-inject-tag v1.3.0 h1:JPrmsmc/uBShG85uY5xGZIa5WJ0IaNZ github.com/favadi/protoc-go-inject-tag v1.3.0/go.mod h1:SSkUBgfqw2IJ2p7NPNKWk0Idwxt/qIt2LQgFPUgRGtc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -319,8 +329,8 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/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/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 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/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -336,7 +346,6 @@ 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-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= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= @@ -348,6 +357,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -364,6 +374,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= 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= @@ -379,6 +390,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -389,6 +401,7 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -396,6 +409,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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= @@ -416,14 +433,10 @@ 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 v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= 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.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -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.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= @@ -451,14 +464,17 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff h1:jUa73mulKrSJaWD5AVpsvhWgoCCQy5NeGJdZrXggga8= +github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff/go.mod h1:oh0okaxgqjJMPBSav3mSYPmyEbW7bVWQvRvkwJaQiIg= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0 h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc= github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -557,6 +573,7 @@ github.com/huaweicloud/golangsdk v0.0.0-20200304081349-45ec0797f2a4/go.mod h1:WQ 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= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -628,8 +645,8 @@ github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f h1:E87tDTVS5W github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f/go.mod h1:3J2qVK16Lq8V+wfiL2lPeDZ7UWMxk5LemerHa1p6N00= github.com/jefferai/keyring v1.1.7-0.20210105022822-8749b3d9ce79 h1:7opZgeTbZEBfZSK6OXO6HSnWIDUBn6wlxBuG13pSuEM= 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/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e h1:Yb4fEGk+GtBSNuvy5rs0ZJt/jtopc/z9azQaj3xbies= +github.com/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e/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/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -645,13 +662,13 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 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.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= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -669,13 +686,14 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= -github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -701,7 +719,7 @@ 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.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -724,6 +742,7 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 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.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 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= @@ -783,7 +802,6 @@ github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1: github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= 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/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= @@ -813,20 +831,23 @@ github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQ 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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 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= github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug= -github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM= +github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -834,33 +855,28 @@ 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/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 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-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.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.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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-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/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= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w= +github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -895,20 +911,18 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= 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/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/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/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/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/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/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= 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= @@ -933,10 +947,9 @@ 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-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= -github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= +github.com/twitchtv/twirp v8.1.0+incompatible h1:KGXanpa9LXdVE/V5P/tA27rkKFmXRGCtSNT7zdeeVOY= +github.com/twitchtv/twirp v8.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= 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= @@ -954,7 +967,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/dburl v0.9.0 h1:ME8QfRqZz/YDwf+VVEe9sq4wgEZCAOdYcUTeuAf+wQQ= +github.com/xo/dburl v0.9.0/go.mod h1:7Uupe87dIDxNrbKFRrpw6bAf2l3/rqU42iwlpq1nyjY= github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13/go.mod h1:LEdAMqa1v/7KYe4b13ALLkonuDxLph57ibUb50ctvJk= github.com/yhat/scrape v0.0.0-20161128144610-24b7890b0945/go.mod h1:4vRFPPNYllgCacoj+0FoKOjTW68rUhEfqPLiEJaK2w8= @@ -963,20 +977,24 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zalando/go-keyring v0.1.1 h1:w2V9lcx/Uj4l+dzAf1m9s+DJ1O8ROkEHnynonHjTcYE= github.com/zalando/go-keyring v0.1.1/go.mod h1:OIC+OZ28XbmwFxU/Rp9V7eKzZjamBJwRzC8UFJH9+L8= 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/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= 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= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.6 h1:BdkrbWrzDlV9dnbzoP7sfN+dHheJ4J9JOaYxcUDL+ok= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/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= @@ -985,19 +1003,22 @@ 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= 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/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/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/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= 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= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1051,6 +1072,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -1062,8 +1084,10 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1072,7 +1096,6 @@ golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1109,13 +1132,17 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210907225631-ff17edfbf26d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1125,7 +1152,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1137,6 +1170,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1144,7 +1179,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1164,6 +1198,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/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-20191005200804-aed5e4c7ecf9/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= @@ -1187,21 +1222,34 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210908143011-c212e7322662/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/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-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1279,12 +1327,19 @@ golang.org/x/tools v0.0.0-20200814230902-9882f1d1823d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200818005847-188abfa75333/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4= -golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8-0.20211102182255-bb4add04ddef h1:/DaKawnTFFxdq/mJT3pM+OkeJlq5gc3ZhkbGVYbqOCw= +golang.org/x/tools v0.1.8-0.20211102182255-bb4add04ddef/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1307,8 +1362,14 @@ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1354,10 +1415,20 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 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= @@ -1375,14 +1446,18 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.35.0-dev.0.20201218190559-666aea1fb34c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0-dev.0.20210907181116-2f3355d2244e h1:HKKXKZmOaf1UtYn+/ga7+QSLvK7l6K5Mppj9yGgXYCo= +google.golang.org/grpc v1.41.0-dev.0.20210907181116-2f3355d2244e/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1396,7 +1471,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.25.1-0.20201208041424-160c7477e0e8/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= @@ -1415,19 +1489,18 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW 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= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 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/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= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1444,20 +1517,22 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.2.2 h1:Ka9W6feOU+rPM9m007eYLMD4QoZuYGBnQ3Jp0faGSwg= gorm.io/driver/postgres v1.2.2/go.mod h1:Ik3tK+a3FMp8ORZl29v4b3M0RsgXsaeMXh9s9eVMXco= +gorm.io/driver/sqlite v1.2.4 h1:jx16ESo1WzNjgBJNSbhEDoMKJnlhkU8BuBR2C0GC7D8= +gorm.io/driver/sqlite v1.2.4/go.mod h1:n8/CTEIEmo7lKrehQI4pd+rz6O514tMkBeCAR5UTXLs= gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.3 h1:/JS6z+GStEQvJNW3t1FTwJwG/gZ+A7crFdRqtvG5ehA= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= 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= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= 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= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= @@ -1471,8 +1546,9 @@ modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= -mvdan.cc/gofumpt v0.1.1 h1:bi/1aS/5W00E2ny5q65w9SnKpWEF/UIOqDYBILpo9rA= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= +mvdan.cc/gofumpt v0.2.0 h1:AInyCTHfhp4bFrP2VYC5kR2wPwgWj7eGSb+7437zn7I= +mvdan.cc/gofumpt v0.2.0/go.mod h1:TiGmrf914DAuT6+hDIxOqoDb4QXIzAuEUSXqEf9hGKY= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= 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= diff --git a/internal/auth/db_test.go b/internal/auth/db_test.go index 3a63e1491..38306bbbf 100644 --- a/internal/auth/db_test.go +++ b/internal/auth/db_test.go @@ -68,7 +68,7 @@ select count(*) from test_auth_method where public_id = @public_id require.NoError(err) defer rows.Close() for rows.Next() { - err := rw.ScanRows(rows, &count) + err := rw.ScanRows(ctx, rows, &count) require.NoError(err) } assert.Equal(1, count.Count) @@ -78,7 +78,7 @@ select count(*) from test_auth_method where public_id = @public_id require.NoError(err) defer rows.Close() for rows.Next() { - err := rw.ScanRows(rows, &count) + err := rw.ScanRows(ctx, rows, &count) require.NoError(err) } assert.Equal(1, count.Count) @@ -150,7 +150,7 @@ values require.NoError(err) defer rows.Close() for rows.Next() { - err := rw.ScanRows(rows, &count) + err := rw.ScanRows(ctx, rows, &count) require.NoError(err) } assert.Equal(1, count.Count) @@ -160,7 +160,7 @@ values require.NoError(err) defer rows.Close() for rows.Next() { - err := rw.ScanRows(rows, &count) + err := rw.ScanRows(ctx, rows, &count) require.NoError(err) } assert.Equal(1, count.Count) diff --git a/internal/auth/oidc/account_claim_map_test.go b/internal/auth/oidc/account_claim_map_test.go index 68923539f..ac9c1f3c7 100644 --- a/internal/auth/oidc/account_claim_map_test.go +++ b/internal/auth/oidc/account_claim_map_test.go @@ -127,7 +127,7 @@ func TestAccountClaimMap_Create(t *testing.T) { assert.NoError(err) } found := AllocAccountClaimMap() - require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and to_claim = ?", tt.args.authMethodId, tt.args.to)) + require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and to_claim = ?", []interface{}{tt.args.authMethodId, tt.args.to})) assert.Equal(got, &found) } }) @@ -145,9 +145,8 @@ func TestAccountClaimMap_Delete(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - testAuthMethod := - TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", - WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows + testAuthMethod := TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", + WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows testResource := func(authMethodId string, fromClaim string, toClaim AccountToClaim) *AccountClaimMap { c, err := NewAccountClaimMap(context.TODO(), authMethodId, fromClaim, toClaim) @@ -209,7 +208,7 @@ func TestAccountClaimMap_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := AllocAccountClaimMap() - err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and to_claim = ?", tt.AccountClaimMap.OidcMethodId, tt.AccountClaimMap.ToClaim) + err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and to_claim = ?", []interface{}{tt.AccountClaimMap.OidcMethodId, tt.AccountClaimMap.ToClaim}) assert.True(errors.IsNotFoundError(err)) }) } diff --git a/internal/auth/oidc/account_test.go b/internal/auth/oidc/account_test.go index e03db7be8..787cc2030 100644 --- a/internal/auth/oidc/account_test.go +++ b/internal/auth/oidc/account_test.go @@ -229,17 +229,16 @@ func TestAccount_Delete(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - testAuthMethod := - TestAuthMethod( - t, - conn, - databaseWrapper, - org.PublicId, - InactiveState, - "alice_rp", - "my-dogs-name", - WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), - WithIssuer(TestConvertToUrls(t, "https://alice.com")[0])) + testAuthMethod := TestAuthMethod( + t, + conn, + databaseWrapper, + org.PublicId, + InactiveState, + "alice_rp", + "my-dogs-name", + WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), + WithIssuer(TestConvertToUrls(t, "https://alice.com")[0])) testResource := func(authMethodId string, subject string) *Account { u, err := url.Parse(testAuthMethod.GetIssuer()) diff --git a/internal/auth/oidc/aud_claim_test.go b/internal/auth/oidc/aud_claim_test.go index 548e55229..5589e9829 100644 --- a/internal/auth/oidc/aud_claim_test.go +++ b/internal/auth/oidc/aud_claim_test.go @@ -113,7 +113,7 @@ func TestAudClaim_Create(t *testing.T) { assert.NoError(err) } found := AllocAudClaim() - require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and aud_claim = ?", tt.args.authMethodId, tt.args.aud)) + require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and aud_claim = ?", []interface{}{tt.args.authMethodId, tt.args.aud})) assert.Equal(got, &found) } }) @@ -132,9 +132,8 @@ func TestAudClaim_Delete(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - testAuthMethod := - TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", - WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows + testAuthMethod := TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", + WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows testResource := func(authMethodId string, AudClaim string) *AudClaim { c, err := NewAudClaim(ctx, authMethodId, AudClaim) @@ -192,7 +191,7 @@ func TestAudClaim_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := AllocAudClaim() - err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and aud_claim = ?", tt.AudClaim.OidcMethodId, tt.AudClaim.Aud) + err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and aud_claim = ?", []interface{}{tt.AudClaim.OidcMethodId, tt.AudClaim.Aud}) assert.True(errors.IsNotFoundError(err)) }) } diff --git a/internal/auth/oidc/certificate_test.go b/internal/auth/oidc/certificate_test.go index 72a86cd50..93fe70ee6 100644 --- a/internal/auth/oidc/certificate_test.go +++ b/internal/auth/oidc/certificate_test.go @@ -112,7 +112,7 @@ func TestCertificate_Create(t *testing.T) { assert.NoError(err) } found := AllocCertificate() - require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and certificate = ?", tt.args.authMethodId, tt.args.certificate)) + require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and certificate = ?", []interface{}{tt.args.authMethodId, tt.args.certificate})) assert.Equal(got, &found) } }) @@ -133,8 +133,7 @@ func TestCertificate_Delete(t *testing.T) { cert, _ := testGenerateCA(t, "localhost") - testAuthMethod := - TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", WithApiUrl(TestConvertToUrls(t, "https://apiurl.com")[0]), WithCertificates(cert)) // seed an extra callback url to just make sure the delete only gets the right num of rows + testAuthMethod := TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", WithApiUrl(TestConvertToUrls(t, "https://apiurl.com")[0]), WithCertificates(cert)) // seed an extra callback url to just make sure the delete only gets the right num of rows // make another test cert _, pem2 := testGenerateCA(t, "localhost") @@ -197,7 +196,7 @@ func TestCertificate_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := AllocCertificate() - err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and certificate = ?", tt.Certificate.OidcMethodId, tt.Certificate.Cert) + err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and certificate = ?", []interface{}{tt.Certificate.OidcMethodId, tt.Certificate.Cert}) assert.True(errors.IsNotFoundError(err)) }) } diff --git a/internal/auth/oidc/claims_scope_test.go b/internal/auth/oidc/claims_scope_test.go index efdc6a676..a1e31c5c0 100644 --- a/internal/auth/oidc/claims_scope_test.go +++ b/internal/auth/oidc/claims_scope_test.go @@ -115,7 +115,7 @@ func TestClaimsScope_Create(t *testing.T) { } assert.NoError(err) found := AllocClaimsScope() - require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and scope = ?", tt.args.authMethodId, tt.args.claimsScope)) + require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and scope = ?", []interface{}{tt.args.authMethodId, tt.args.claimsScope})) } }) } @@ -133,9 +133,8 @@ func TestClaimsScope_Delete(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - testAuthMethod := - TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", - WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows + testAuthMethod := TestAuthMethod(t, conn, databaseWrapper, org.PublicId, InactiveState, "alice_rp", "my-dogs-name", + WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) // seed an extra callback url to just make sure the delete only gets the right num of rows testResource := func(authMethodId string, claimsScope string) *ClaimsScope { c, err := NewClaimsScope(ctx, authMethodId, claimsScope) @@ -193,7 +192,7 @@ func TestClaimsScope_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := AllocClaimsScope() - err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and scope = ?", tt.claimsScope.OidcMethodId, tt.claimsScope.Scope) + err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and scope = ?", []interface{}{tt.claimsScope.OidcMethodId, tt.claimsScope.Scope}) assert.True(errors.IsNotFoundError(err)) }) } diff --git a/internal/auth/oidc/immutable_fields_test.go b/internal/auth/oidc/immutable_fields_test.go index 4b57f676a..145c6f71c 100644 --- a/internal/auth/oidc/immutable_fields_test.go +++ b/internal/auth/oidc/immutable_fields_test.go @@ -105,7 +105,7 @@ func TestAudClaim_ImmutableFields(t *testing.T) { WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithAudClaims("alice.com")) new := AllocAudClaim() - require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", am.PublicId, "alice.com")) + require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", []interface{}{am.PublicId, "alice.com"})) tests := []struct { name string @@ -147,7 +147,7 @@ func TestAudClaim_ImmutableFields(t *testing.T) { orig := new.Clone() orig.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", orig.OidcMethodId, orig.Aud)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", []interface{}{orig.OidcMethodId, orig.Aud})) require.NoError(err) @@ -158,7 +158,7 @@ func TestAudClaim_ImmutableFields(t *testing.T) { after := new.Clone() after.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", after.OidcMethodId, after.Aud)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and aud_claim = ?", []interface{}{after.OidcMethodId, after.Aud})) assert.True(proto.Equal(orig, after)) }) @@ -186,7 +186,7 @@ func TestCertificate_ImmutableFields(t *testing.T) { WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithCertificates(x509)) new := AllocCertificate() - require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", am.PublicId, pem)) + require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", []interface{}{am.PublicId, pem})) tests := []struct { name string @@ -228,7 +228,7 @@ func TestCertificate_ImmutableFields(t *testing.T) { orig := new.Clone() orig.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", orig.OidcMethodId, orig.Cert)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", []interface{}{orig.OidcMethodId, orig.Cert})) require.NoError(err) @@ -239,7 +239,7 @@ func TestCertificate_ImmutableFields(t *testing.T) { after := new.Clone() after.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", after.OidcMethodId, after.Cert)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and certificate = ?", []interface{}{after.OidcMethodId, after.Cert})) assert.True(proto.Equal(orig, after)) }) @@ -263,7 +263,7 @@ func TestSigningAlg_ImmutableFields(t *testing.T) { WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), WithSigningAlgs(RS256)) new := AllocSigningAlg() - require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", am.PublicId, RS256)) + require.NoError(t, rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", []interface{}{am.PublicId, RS256})) tests := []struct { name string @@ -305,7 +305,7 @@ func TestSigningAlg_ImmutableFields(t *testing.T) { orig := new.Clone() orig.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", orig.OidcMethodId, orig.Alg)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", []interface{}{orig.OidcMethodId, orig.Alg})) require.NoError(err) @@ -316,7 +316,7 @@ func TestSigningAlg_ImmutableFields(t *testing.T) { after := new.Clone() after.SetTableName(defaultAuthMethodTableName) - require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", after.OidcMethodId, after.Alg)) + require.NoError(rw.LookupWhere(ctx, &new, "oidc_method_id = ? and signing_alg_name = ?", []interface{}{after.OidcMethodId, after.Alg})) assert.True(proto.Equal(orig, after)) }) diff --git a/internal/auth/oidc/repository_account_test.go b/internal/auth/oidc/repository_account_test.go index 62dc111da..72301c63d 100644 --- a/internal/auth/oidc/repository_account_test.go +++ b/internal/auth/oidc/repository_account_test.go @@ -947,7 +947,7 @@ func TestRepository_UpdateAccount(t *testing.T) { chgFn: combine(nonExistentPublicId(), changeName("updating-non-existent-Account-test-update-name-repo")), masks: []string{NameField}, wantIsErr: errors.RecordNotFound, - wantErrMsg: "oidc.(Repository).UpdateAccount: abcd_OOOOOOOOOO: db.DoTx: oidc.(Repository).UpdateAccount: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "oidc.(Repository).UpdateAccount: abcd_OOOOOOOOOO: db.DoTx: oidc.(Repository).UpdateAccount: db.Update: record not found, search issue: error #1100: dbw.Update: dbw.lookupAfterWrite: dbw.LookupById: record not found", }, { name: "empty-field-mask", diff --git a/internal/auth/oidc/repository_auth_method.go b/internal/auth/oidc/repository_auth_method.go index da8dbb569..a477fb15e 100644 --- a/internal/auth/oidc/repository_auth_method.go +++ b/internal/auth/oidc/repository_auth_method.go @@ -176,7 +176,7 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC var rowCnt int for rows.Next() { rowCnt += 1 - err = r.reader.ScanRows(rows, &result) + err = r.reader.ScanRows(ctx, rows, &result) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for account")) } @@ -184,7 +184,7 @@ func (r *Repository) upsertAccount(ctx context.Context, am *AuthMethod, IdTokenC if rowCnt > 1 { return errors.New(ctx, errors.MultipleRecords, op, fmt.Sprintf("expected 1 row but got: %d", rowCnt)) } - if err := reader.LookupWhere(ctx, &updatedAcct, "auth_method_id = ? and issuer = ? and subject = ?", am.PublicId, iss, sub); err != nil { + if err := reader.LookupWhere(ctx, &updatedAcct, "auth_method_id = ? and issuer = ? and subject = ?", []interface{}{am.PublicId, iss, sub}); err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to look up auth oidc account for: %s / %s / %s", am.PublicId, iss, sub))) } // include the version incase of predictable account public ids based on a calculation using authmethod id and subject @@ -238,7 +238,7 @@ func upsertOplog(ctx context.Context, w db.Writer, oplogWrapper wrapping.Wrapper if operation == oplog.OpType_OP_TYPE_UPDATE && len(fieldMasks) == 0 && len(nullMasks) == 0 { return errors.New(ctx, errors.InvalidParameter, op, "update operations must specify field masks and/or null masks") } - ticket, err := w.GetTicket(acct) + ticket, err := w.GetTicket(ctx, acct) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/auth/oidc/repository_auth_method_create.go b/internal/auth/oidc/repository_auth_method_create.go index 67ba95de4..b2615b6c9 100644 --- a/internal/auth/oidc/repository_auth_method_create.go +++ b/internal/auth/oidc/repository_auth_method_create.go @@ -72,7 +72,7 @@ func (r *Repository) CreateAuthMethod(ctx context.Context, am *AuthMethod, opt . db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 5) - ticket, err := w.GetTicket(am) + ticket, err := w.GetTicket(ctx, am) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/auth/oidc/repository_auth_method_update.go b/internal/auth/oidc/repository_auth_method_update.go index e7891388d..032262474 100644 --- a/internal/auth/oidc/repository_auth_method_update.go +++ b/internal/auth/oidc/repository_auth_method_update.go @@ -256,7 +256,7 @@ func (r *Repository) UpdateAuthMethod(ctx context.Context, am *AuthMethod, versi db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 7) // AuthMethod, Algs*2, Certs*2, Audiences*2 - ticket, err := w.GetTicket(am) + ticket, err := w.GetTicket(ctx, am) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/auth/oidc/repository_managed_group_members.go b/internal/auth/oidc/repository_managed_group_members.go index 2758aaf36..91931122f 100644 --- a/internal/auth/oidc/repository_managed_group_members.go +++ b/internal/auth/oidc/repository_managed_group_members.go @@ -78,7 +78,7 @@ func (r *Repository) SetManagedGroupMemberships(ctx context.Context, am *AuthMet // We need a ticket, which won't be redeemed until all the other // writes are successful. We can't just use a single ticket because // we need to write oplog entries for deletes and adds. - mgTicket, err := w.GetTicket(ticketMg) + mgTicket, err := w.GetTicket(ctx, ticketMg) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket for oidc managed groups")) } diff --git a/internal/auth/oidc/repository_managed_group_test.go b/internal/auth/oidc/repository_managed_group_test.go index 12cbc8db9..6f8351956 100644 --- a/internal/auth/oidc/repository_managed_group_test.go +++ b/internal/auth/oidc/repository_managed_group_test.go @@ -703,7 +703,7 @@ func TestRepository_UpdateManagedGroup(t *testing.T) { chgFn: combine(nonExistentPublicId(), changeName("updating-non-existent-ManagedGroup-test-update-name-repo")), masks: []string{NameField}, wantIsErr: errors.RecordNotFound, - wantErrMsg: "oidc.(Repository).UpdateManagedGroup: abcd_OOOOOOOOOO: db.DoTx: oidc.(Repository).UpdateManagedGroup: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "oidc.(Repository).UpdateManagedGroup: abcd_OOOOOOOOOO: db.DoTx: oidc.(Repository).UpdateManagedGroup: db.Update: record not found, search issue: error #1100: dbw.Update: dbw.lookupAfterWrite: dbw.LookupById: record not found", }, { name: "empty-field-mask", diff --git a/internal/auth/oidc/service_callback_test.go b/internal/auth/oidc/service_callback_test.go index f1b66c3ca..1187f51e9 100644 --- a/internal/auth/oidc/service_callback_test.go +++ b/internal/auth/oidc/service_callback_test.go @@ -35,6 +35,8 @@ func Test_Callback(t *testing.T) { rootWrapper := db.TestWrapper(t) kmsCache := kms.TestKms(t, conn, rootWrapper) + testCtx := context.Background() + // some standard factories for unit tests which // are used in the Callback(...) call iamRepoFn := func() (*iam.Repository, error) { @@ -373,7 +375,7 @@ func Test_Callback(t *testing.T) { // make sure the account was updated properly var acct Account - err = rw.LookupWhere(ctx, &acct, "auth_method_id = ? and subject = ?", tt.am.PublicId, tt.wantSubject) + err = rw.LookupWhere(ctx, &acct, "auth_method_id = ? and subject = ?", []interface{}{tt.am.PublicId, tt.wantSubject}) require.NoError(err) assert.Equal(tt.wantInfoEmail, acct.Email) assert.Equal(tt.wantInfoName, acct.FullName) @@ -393,7 +395,7 @@ func Test_Callback(t *testing.T) { require.NoError(err) oplogWrapper, err := kmsCache.GetWrapper(ctx, tt.am.ScopeId, kms.KeyPurposeOplog) require.NoError(err) - types, err := oplog.NewTypeCatalog( + types, err := oplog.NewTypeCatalog(testCtx, oplog.Type{Interface: new(store.Account), Name: "auth_oidc_account"}, oplog.Type{Interface: new(iamStore.User), Name: "iam_user"}, oplog.Type{Interface: new(authStore.Account), Name: "auth_account"}, @@ -407,7 +409,7 @@ func Test_Callback(t *testing.T) { e.Cipherer = oplogWrapper err := e.DecryptData(ctx) require.NoError(err) - msgs, err := e.UnmarshalData(types) + msgs, err := e.UnmarshalData(ctx, types) require.NoError(err) for _, m := range msgs { switch m.TypeName { diff --git a/internal/auth/oidc/signing_alg_test.go b/internal/auth/oidc/signing_alg_test.go index 0e37aa349..def7b31c3 100644 --- a/internal/auth/oidc/signing_alg_test.go +++ b/internal/auth/oidc/signing_alg_test.go @@ -122,7 +122,7 @@ func TestSigningAlg_Create(t *testing.T) { assert.NoError(err) } found := AllocSigningAlg() - require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and signing_alg_name = ?", tt.args.authMethodId, string(tt.args.alg))) + require.NoError(rw.LookupWhere(ctx, &found, "oidc_method_id = ? and signing_alg_name = ?", []interface{}{tt.args.authMethodId, string(tt.args.alg)})) assert.Equal(got, &found) } }) @@ -141,18 +141,17 @@ func TestSigningAlg_Delete(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - testAuthMethod := - TestAuthMethod( - t, - conn, - databaseWrapper, - org.PublicId, - InactiveState, - "alice_rp", - "my-dogs-name", - WithIssuer(TestConvertToUrls(t, "https://alice.com")[0]), - WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), - WithSigningAlgs(RS256)) // seed an extra callback url to just make sure the delete only gets the right num of rows + testAuthMethod := TestAuthMethod( + t, + conn, + databaseWrapper, + org.PublicId, + InactiveState, + "alice_rp", + "my-dogs-name", + WithIssuer(TestConvertToUrls(t, "https://alice.com")[0]), + WithApiUrl(TestConvertToUrls(t, "https://api.com")[0]), + WithSigningAlgs(RS256)) // seed an extra callback url to just make sure the delete only gets the right num of rows testResource := func(authMethodId string, signingAlg Alg) *SigningAlg { c, err := NewSigningAlg(ctx, authMethodId, signingAlg) @@ -210,7 +209,7 @@ func TestSigningAlg_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := AllocSigningAlg() - err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and signing_alg_name = ?", tt.SigningAlg.OidcMethodId, tt.SigningAlg.String()) + err = rw.LookupWhere(ctx, &found, "oidc_method_id = ? and signing_alg_name = ?", []interface{}{tt.SigningAlg.OidcMethodId, tt.SigningAlg.String()}) assert.Truef(errors.IsNotFoundError(err), "unexpected error: %s", err.Error()) }) } diff --git a/internal/auth/password/repository_account_test.go b/internal/auth/password/repository_account_test.go index 13ee140a7..e1f999659 100644 --- a/internal/auth/password/repository_account_test.go +++ b/internal/auth/password/repository_account_test.go @@ -697,7 +697,7 @@ func TestRepository_UpdateAccount(t *testing.T) { chgFn: combine(nonExistentPublicId(), changeName("test-update-name-repo")), masks: []string{"Name"}, wantIsErr: errors.RecordNotFound, - wantErrMsg: "password.(Repository).UpdateAccount: abcd_OOOOOOOOOO: db.DoTx: password.(Repository).UpdateAccount: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "password.(Repository).UpdateAccount: abcd_OOOOOOOOOO: db.DoTx: password.(Repository).UpdateAccount: db.Update: record not found, search issue: error #1100: dbw.Update: dbw.lookupAfterWrite: dbw.LookupById: record not found", }, { name: "empty-field-mask", diff --git a/internal/auth/password/repository_configuration.go b/internal/auth/password/repository_configuration.go index 2cffa5841..dcd1ebda4 100644 --- a/internal/auth/password/repository_configuration.go +++ b/internal/auth/password/repository_configuration.go @@ -92,7 +92,7 @@ func (r *Repository) setArgon2Conf(ctx context.Context, scopeId string, c *Argon _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(rr db.Reader, w db.Writer) error { where, args := c.whereDup() - if err := rr.LookupWhere(ctx, newArgon2Conf, where, args...); err != nil { + if err := rr.LookupWhere(ctx, newArgon2Conf, where, args); err != nil { if !errors.IsNotFoundError(err) { return errors.Wrap(ctx, err, op) } @@ -134,7 +134,7 @@ func (c *currentConfig) TableName() string { func (r *Repository) currentConfig(ctx context.Context, authMethodId string) (*currentConfig, error) { const op = "password.(Repository).currentConfig" var cc currentConfig - if err := r.reader.LookupWhere(ctx, &cc, "password_method_id = ?", authMethodId); err != nil { + if err := r.reader.LookupWhere(ctx, &cc, "password_method_id = ?", []interface{}{authMethodId}); err != nil { return nil, errors.Wrap(ctx, err, op) } return &cc, nil @@ -151,7 +151,7 @@ func (r *Repository) currentConfigForAccount(ctx context.Context, accountId stri defer rows.Close() for rows.Next() { var conf currentConfig - if err := r.reader.ScanRows(rows, &conf); err != nil { + if err := r.reader.ScanRows(ctx, rows, &conf); err != nil { return nil, errors.Wrap(ctx, err, op) } confs = append(confs, conf) diff --git a/internal/auth/password/repository_password.go b/internal/auth/password/repository_password.go index f335afec6..655cb6172 100644 --- a/internal/auth/password/repository_password.go +++ b/internal/auth/password/repository_password.go @@ -221,7 +221,7 @@ func (r *Repository) authenticate(ctx context.Context, scopeId, authMethodId, lo defer rows.Close() for rows.Next() { var aa authAccount - if err := r.reader.ScanRows(rows, &aa); err != nil { + if err := r.reader.ScanRows(ctx, rows, &aa); err != nil { return nil, errors.Wrap(ctx, err, op) } accts = append(accts, aa) @@ -316,7 +316,7 @@ func (r *Repository) SetPassword(ctx context.Context, scopeId, accountId, passwo acct = updatedAccount oldCred := allocCredential() - if err := rr.LookupWhere(ctx, &oldCred, "password_account_id = ?", accountId); err != nil { + if err := rr.LookupWhere(ctx, &oldCred, "password_account_id = ?", []interface{}{accountId}); err != nil { if !errors.IsNotFoundError(err) { return errors.Wrap(ctx, err, op) } diff --git a/internal/auth/password/repository_password_test.go b/internal/auth/password/repository_password_test.go index bf326252b..6fed14c7f 100644 --- a/internal/auth/password/repository_password_test.go +++ b/internal/auth/password/repository_password_test.go @@ -171,7 +171,7 @@ func TestRepository_AuthenticateRehash(t *testing.T) { // Get the credential for the new account and verify the KDF used the // original argon2 configuration origCred := &Argon2Credential{Argon2Credential: &store.Argon2Credential{}} - require.NoError(rw.LookupWhere(ctx, origCred, "password_account_id = ?", origAcct.PublicId)) + require.NoError(rw.LookupWhere(ctx, origCred, "password_account_id = ?", []interface{}{origAcct.PublicId})) assert.Equal(origAcct.PublicId, origCred.PasswordAccountId) assert.Equal(origConfId, origCred.PasswordConfId) assert.Equal(origCred.CreateTime, origCred.UpdateTime, "create and update times are equal") diff --git a/internal/cmd/commands/config/encryptdecrypt.go b/internal/cmd/commands/config/encryptdecrypt.go index e95505a61..0ec6d57f1 100644 --- a/internal/cmd/commands/config/encryptdecrypt.go +++ b/internal/cmd/commands/config/encryptdecrypt.go @@ -60,13 +60,12 @@ func (c *EncryptDecryptCommand) Help() string { ) for i, line := range args { - args[i] = + args[i] = strings.Replace( strings.Replace( - strings.Replace( - line, "{{func}}", c.Func, -1, - ), - "{{upperfunc}}", textproto.CanonicalMIMEHeaderKey(c.Func), -1, - ) + line, "{{func}}", c.Func, -1, + ), + "{{upperfunc}}", textproto.CanonicalMIMEHeaderKey(c.Func), -1, + ) } return base.WrapForHelpText(args) + c.Flags().Help() diff --git a/internal/cmd/common/help.go b/internal/cmd/common/help.go index 44b66fd37..cea87b356 100644 --- a/internal/cmd/common/help.go +++ b/internal/cmd/common/help.go @@ -126,17 +126,16 @@ func subtype(in []string, resType string, prefixMap map[string]string) []string articleType = fmt.Sprintf("a %s", articleType) } for i, v := range in { - in[i] = + in[i] = strings.Replace( strings.Replace( strings.Replace( strings.Replace( strings.Replace( - strings.Replace( - v, "{{hyphentype}}", hyphenType, -1), - "{{type}}", resType, -1), - "{{uppertype}}", textproto.CanonicalMIMEHeaderKey(resType), -1), - "{{prefix}}", prefixMap[resType], -1), - "{{articletype}}", articleType, -1) + v, "{{hyphentype}}", hyphenType, -1), + "{{type}}", resType, -1), + "{{uppertype}}", textproto.CanonicalMIMEHeaderKey(resType), -1), + "{{prefix}}", prefixMap[resType], -1), + "{{articletype}}", articleType, -1) } return in } diff --git a/internal/credential/vault/jobs.go b/internal/credential/vault/jobs.go index 29977dac6..102cbf51b 100644 --- a/internal/credential/vault/jobs.go +++ b/internal/credential/vault/jobs.go @@ -235,9 +235,9 @@ func (r *TokenRenewalJob) renewToken(ctx context.Context, s *privateStore) error } // NextRunIn queries the vault credential repo to determine when the next token renewal job should run. -func (r *TokenRenewalJob) NextRunIn() (time.Duration, error) { +func (r *TokenRenewalJob) NextRunIn(ctx context.Context) (time.Duration, error) { const op = "vault.(TokenRenewalJob).NextRunIn" - next, err := nextRenewal(r) + next, err := nextRenewal(ctx, r) if err != nil { return defaultNextRunIn, errors.WrapDeprecated(err, op) } @@ -245,7 +245,7 @@ func (r *TokenRenewalJob) NextRunIn() (time.Duration, error) { return next, nil } -func nextRenewal(j scheduler.Job) (time.Duration, error) { +func nextRenewal(ctx context.Context, j scheduler.Job) (time.Duration, error) { const op = "vault.nextRenewal" var query string var r db.Reader @@ -271,7 +271,7 @@ func nextRenewal(j scheduler.Job) (time.Duration, error) { RenewalIn time.Duration } var n NextRenewal - err = r.ScanRows(rows, &n) + err = r.ScanRows(ctx, rows, &n) if err != nil { return 0, errors.WrapDeprecated(err, op) } @@ -446,7 +446,7 @@ func (r *TokenRevocationJob) revokeToken(ctx context.Context, s *privateStore) e } // NextRunIn determines when the next token revocation job should run. -func (r *TokenRevocationJob) NextRunIn() (time.Duration, error) { +func (r *TokenRevocationJob) NextRunIn(_ context.Context) (time.Duration, error) { return defaultNextRunIn, nil } @@ -603,9 +603,9 @@ func (r *CredentialRenewalJob) renewCred(ctx context.Context, c *privateCredenti } // NextRunIn queries the vault credential repo to determine when the next credential renewal job should run. -func (r *CredentialRenewalJob) NextRunIn() (time.Duration, error) { +func (r *CredentialRenewalJob) NextRunIn(ctx context.Context) (time.Duration, error) { const op = "vault.(CredentialRenewalJob).NextRunIn" - next, err := nextRenewal(r) + next, err := nextRenewal(ctx, r) if err != nil { return defaultNextRunIn, errors.WrapDeprecated(err, op) } @@ -751,7 +751,7 @@ func (r *CredentialRevocationJob) revokeCred(ctx context.Context, c *privateCred } // NextRunIn determine when the next credential revocation job should run. -func (r *CredentialRevocationJob) NextRunIn() (time.Duration, error) { +func (r *CredentialRevocationJob) NextRunIn(_ context.Context) (time.Duration, error) { return defaultNextRunIn, nil } @@ -866,7 +866,7 @@ func (r *CredentialStoreCleanupJob) Run(ctx context.Context) error { } // NextRunIn determine when the next credential store cleanup job should run. -func (r *CredentialStoreCleanupJob) NextRunIn() (time.Duration, error) { +func (r *CredentialStoreCleanupJob) NextRunIn(_ context.Context) (time.Duration, error) { return defaultNextRunIn, nil } @@ -940,7 +940,7 @@ func (r *CredentialCleanupJob) Run(ctx context.Context) error { } // NextRunIn determine when the next credential cleanup job should run. -func (r *CredentialCleanupJob) NextRunIn() (time.Duration, error) { +func (r *CredentialCleanupJob) NextRunIn(_ context.Context) (time.Duration, error) { return defaultNextRunIn, nil } diff --git a/internal/credential/vault/jobs_test.go b/internal/credential/vault/jobs_test.go index 816c2f821..795053a94 100644 --- a/internal/credential/vault/jobs_test.go +++ b/internal/credential/vault/jobs_test.go @@ -80,7 +80,7 @@ func testVaultToken(t *testing.T, require.NoError(err) outToken := allocToken() - require.NoError(rw.LookupWhere(context.Background(), &outToken, "token_hmac = ?", inToken.TokenHmac)) + require.NoError(rw.LookupWhere(context.Background(), &outToken, "token_hmac = ?", []interface{}{inToken.TokenHmac})) require.NoError(outToken.decrypt(context.Background(), databaseWrapper)) return outToken @@ -141,7 +141,7 @@ func testVaultCred(t *testing.T, assert.NoError(err) outCred := allocCredential() - require.NoError(rw.LookupWhere(context.Background(), &outCred, "public_id = ?", id)) + require.NoError(rw.LookupWhere(context.Background(), &outCred, "public_id = ?", []interface{}{id})) return secret, outCred } @@ -582,7 +582,7 @@ func TestTokenRenewalJob_NextRunIn(t *testing.T) { assert.Equal(1, count) } - got, err := r.NextRunIn() + got, err := r.NextRunIn(context.Background()) require.NoError(err) // Round to time.Minute to account for lost time between creating tokens and determining next run assert.Equal(tt.want.Round(time.Minute), got.Round(time.Minute)) @@ -1437,7 +1437,7 @@ func TestCredentialRenewalJob_NextRunIn(t *testing.T) { testVaultCred(t, conn, v, cl, sess, token, cred.s, cred.e) } - got, err := r.NextRunIn() + got, err := r.NextRunIn(context.Background()) require.NoError(err) // Round to time.Minute to account for lost time between creating credentials and determining next run assert.Equal(tt.want.Round(time.Minute), got.Round(time.Minute)) diff --git a/internal/credential/vault/private_library.go b/internal/credential/vault/private_library.go index f0392b29e..dd183638d 100644 --- a/internal/credential/vault/private_library.go +++ b/internal/credential/vault/private_library.go @@ -317,7 +317,7 @@ func (r *Repository) getPrivateLibraries(ctx context.Context, requests []credent var libs []*privateLibrary for rows.Next() { var lib privateLibrary - if err := r.reader.ScanRows(rows, &lib); err != nil { + if err := r.reader.ScanRows(ctx, rows, &lib); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed")) } purps := mapper.get(lib.GetPublicId()) diff --git a/internal/credential/vault/private_store.go b/internal/credential/vault/private_store.go index 06f5d5e34..e0f8d4212 100644 --- a/internal/credential/vault/private_store.go +++ b/internal/credential/vault/private_store.go @@ -45,7 +45,7 @@ func (r *Repository) lookupPrivateStore(ctx context.Context, publicId string) (* return nil, errors.New(ctx, errors.InvalidParameter, op, "no public id") } ps := allocPrivateStore() - if err := r.reader.LookupWhere(ctx, &ps, "public_id = ? and token_status = ?", publicId, CurrentToken); err != nil { + if err := r.reader.LookupWhere(ctx, &ps, "public_id = ? and token_status = ?", []interface{}{publicId, CurrentToken}); err != nil { if errors.IsNotFoundError(err) { return nil, nil } diff --git a/internal/credential/vault/repository_credential_library.go b/internal/credential/vault/repository_credential_library.go index 3e3ffb2df..c7185aad6 100644 --- a/internal/credential/vault/repository_credential_library.go +++ b/internal/credential/vault/repository_credential_library.go @@ -68,7 +68,7 @@ func (r *Repository) CreateCredentialLibrary(ctx context.Context, scopeId string _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { var msgs []*oplog.Message - ticket, err := w.GetTicket(l) + ticket, err := w.GetTicket(ctx, l) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -222,7 +222,7 @@ func (r *Repository) UpdateCredentialLibrary(ctx context.Context, scopeId string _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(rr db.Reader, w db.Writer) error { var msgs []*oplog.Message - ticket, err := w.GetTicket(l) + ticket, err := w.GetTicket(ctx, l) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/credential/vault/repository_credential_library_test.go b/internal/credential/vault/repository_credential_library_test.go index 542d93396..d12e7ed77 100644 --- a/internal/credential/vault/repository_credential_library_test.go +++ b/internal/credential/vault/repository_credential_library_test.go @@ -330,7 +330,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) { // verify it was persisted in the database override := allocUserPasswordOverride() - assert.NoError(rw.LookupWhere(ctx, &override, "library_id = ?", got.GetPublicId())) + assert.NoError(rw.LookupWhere(ctx, &override, "library_id = ?", []interface{}{got.GetPublicId()})) } }) } diff --git a/internal/credential/vault/repository_credential_store.go b/internal/credential/vault/repository_credential_store.go index 9e724fed4..1b58a36f2 100644 --- a/internal/credential/vault/repository_credential_store.go +++ b/internal/credential/vault/repository_credential_store.go @@ -140,7 +140,7 @@ func (r *Repository) CreateCredentialStore(ctx context.Context, cs *CredentialSt _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 3) - ticket, err := w.GetTicket(cs) + ticket, err := w.GetTicket(ctx, cs) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -519,7 +519,7 @@ func (r *Repository) UpdateCredentialStore(ctx context.Context, cs *CredentialSt _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 3) - ticket, err := w.GetTicket(cs) + ticket, err := w.GetTicket(ctx, cs) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -693,7 +693,7 @@ func (r *Repository) DeleteCredentialStore(ctx context.Context, publicId string, ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) (err error) { var msgs []*oplog.Message - ticket, err := w.GetTicket(cs) + ticket, err := w.GetTicket(ctx, cs) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/credential/vault/repository_credential_store_test.go b/internal/credential/vault/repository_credential_store_test.go index 657975b6f..fc13bceee 100644 --- a/internal/credential/vault/repository_credential_store_test.go +++ b/internal/credential/vault/repository_credential_store_test.go @@ -216,11 +216,11 @@ func TestRepository_CreateCredentialStoreNonResource(t *testing.T) { assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second))) outToken := allocToken() - assert.NoError(rw.LookupWhere(ctx, &outToken, "store_id = ?", got.PublicId)) + assert.NoError(rw.LookupWhere(ctx, &outToken, "store_id = ?", []interface{}{got.PublicId})) if tt.tls == TestClientTLS { outClientCert := allocClientCertificate() - assert.NoError(rw.LookupWhere(ctx, &outClientCert, "store_id = ?", got.PublicId)) + assert.NoError(rw.LookupWhere(ctx, &outClientCert, "store_id = ?", []interface{}{got.PublicId})) } }) } diff --git a/internal/credential/vault/testing.go b/internal/credential/vault/testing.go index 001c8240f..f53d5df20 100644 --- a/internal/credential/vault/testing.go +++ b/internal/credential/vault/testing.go @@ -226,7 +226,7 @@ func testTokens(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, scopeId, st num := r.Int31() inToken := createTestToken(t, conn, wrapper, scopeId, storeId, fmt.Sprintf("vault-token-%s-%d-%v", storeId, i, num), fmt.Sprintf("accessor-%s-%d-%v", storeId, i, num)) outToken := allocToken() - require.NoError(w.LookupWhere(ctx, &outToken, "token_hmac = ?", inToken.TokenHmac)) + require.NoError(w.LookupWhere(ctx, &outToken, "token_hmac = ?", []interface{}{inToken.TokenHmac})) require.NoError(outToken.decrypt(ctx, databaseWrapper)) tokens = append(tokens, outToken) diff --git a/internal/db/assert/asserts_test.go b/internal/db/assert/asserts_test.go index e19c2ca0a..46858490d 100644 --- a/internal/db/assert/asserts_test.go +++ b/internal/db/assert/asserts_test.go @@ -115,7 +115,7 @@ type testModel struct { 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 *db.DB, nullable *string, typeInt *int) *testModel { +func createTestModel(t dbassert.TestingT, d *db.DB, nullable *string, typeInt *int) *testModel { publicId, err := base62.Random(12) assert.NoError(t, err) m := testModel{ @@ -123,12 +123,12 @@ func createTestModel(t dbassert.TestingT, db *db.DB, nullable *string, typeInt * Nullable: nullable, TypeInt: typeInt, } - err = db.Create(&m).Error - assert.NoError(t, err) + rw := db.New(d) + require.NoError(t, rw.Create(context.Background(), &m)) return &m } -func initStore(t *testing.T, db *db.DB) { +func initStore(t *testing.T, d *db.DB) { t.Helper() const ( createDomainType = ` @@ -150,6 +150,11 @@ comment on table test_table_dbasserts is 'dbasserts test table' ` ) - require.NoError(t, db.Exec(createDomainType).Error) - require.NoError(t, db.Exec(createTable).Error) + rw := db.New(d) + + ctx := context.Background() + _, err := rw.Exec(ctx, createDomainType, nil) + require.NoError(t, err) + _, err = rw.Exec(ctx, createTable, nil) + require.NoError(t, err) } diff --git a/internal/db/clause.go b/internal/db/clause.go index 0beb4d758..41a3dc816 100644 --- a/internal/db/clause.go +++ b/internal/db/clause.go @@ -2,9 +2,6 @@ package db import ( "sort" - - "gorm.io/gorm" - "gorm.io/gorm/clause" ) // ColumnValue defines a column and it's assigned value for a database operation @@ -13,30 +10,12 @@ type ColumnValue struct { value interface{} } -type assigner interface { - toAssignment(column string) clause.Assignment -} - // column represents a table column type column struct { name string table string } -func (c *column) toAssignment(column string) clause.Assignment { - return clause.Assignment{ - Column: clause.Column{Name: column}, - Value: clause.Column{Table: c.table, Name: c.name}, - } -} - -func rawAssignment(column string, value interface{}) clause.Assignment { - return clause.Assignment{ - Column: clause.Column{Name: column}, - Value: value, - } -} - // ExprValue encapsulates an expression value for a column assignment. See // Expr(...) to create these values. type ExprValue struct { @@ -44,13 +23,6 @@ type ExprValue struct { vars []interface{} } -func (ev *ExprValue) toAssignment(column string) clause.Assignment { - return clause.Assignment{ - Column: clause.Column{Name: column}, - Value: gorm.Expr(ev.sql, ev.vars...), - } -} - // Expr creates an expression value (ExprValue) which can be used when setting // column values for database operations. See: Expr(...) // diff --git a/internal/db/db.go b/internal/db/db.go index 748764079..7add89bc6 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -6,14 +6,16 @@ import ( "fmt" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/go-hclog" - "github.com/jackc/pgconn" + "github.com/hashicorp/go-dbw" _ "github.com/jackc/pgx/v4" "gorm.io/driver/postgres" - "gorm.io/gorm" - "gorm.io/gorm/logger" ) +func init() { + dbw.InitNonCreatableFields([]string{"CreateTime", "UpdateTime"}) + dbw.InitNonUpdatableFields([]string{"PublicId", "CreateTime", "UpdateTime"}) +} + type DbType int const ( @@ -39,18 +41,12 @@ func StringToDbType(dialect string) (DbType, error) { // DB is a wrapper around the ORM type DB struct { - *gorm.DB + wrapped *dbw.DB } // Debug will enable/disable debug info for the connection func (db *DB) Debug(on bool) { - if on { - // info level in the Gorm domain which maps to a debug level in the boundary domain - db.Logger = logger.Default.LogMode(logger.Info) - } else { - // the default level in the gorm domain is: error level - db.Logger = logger.Default.LogMode(logger.Error) - } + db.wrapped.Debug(on) } // SqlDB returns the underlying sql.DB @@ -60,23 +56,19 @@ func (db *DB) Debug(on bool) { // is also an export DB type func (d *DB) SqlDB(ctx context.Context) (*sql.DB, error) { const op = "db.(DB).SqlDB" - if d.DB == nil { + if d.wrapped == nil { return nil, errors.New(ctx, errors.Internal, op, "missing underlying database") } - return d.DB.DB() + return d.wrapped.SqlDB(ctx) } // Close the underlying sql.DB func (d *DB) Close(ctx context.Context) error { const op = "db.(DB).Close" - if d.DB == nil { + if d.wrapped == nil { return errors.New(ctx, errors.Internal, op, "missing underlying database") } - underlying, err := d.DB.DB() - if err != nil { - return errors.Wrap(ctx, err, op) - } - return underlying.Close() + return d.wrapped.Close(ctx) } // Open a database connection which is long-lived. The options of @@ -86,7 +78,8 @@ func (d *DB) Close(ctx context.Context) error { // answer is no, but there are occasions when it's necessary. See the sql.DB // docs for more information. func Open(dbType DbType, connectionUrl string, opt ...Option) (*DB, error) { - var dialect gorm.Dialector + const op = "db.Open" + var dialect dbw.Dialector switch dbType { case Postgres: dialect = postgres.New(postgres.Config{ @@ -96,47 +89,18 @@ func Open(dbType DbType, connectionUrl string, opt ...Option) (*DB, error) { default: return nil, fmt.Errorf("unable to open %s database type", dbType) } - db, err := gorm.Open(dialect, &gorm.Config{}) - if err != nil { - return nil, fmt.Errorf("unable to open database: %w", err) - } opts := GetOpts(opt...) + var wrappedOpts []dbw.Option if opts.withGormFormatter != nil { - newLogger := logger.New( - getGormLogger(opts.withGormFormatter), - logger.Config{ - LogLevel: logger.Error, // Log level - Colorful: false, // Disable color - }, - ) - db = db.Session(&gorm.Session{Logger: newLogger}) + wrappedOpts = append(wrappedOpts, dbw.WithLogger(opts.withGormFormatter)) } if opts.withMaxOpenConnections > 0 { - if dialect.Name() == "postgres" && opts.withMaxOpenConnections == 1 { - return nil, 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") - } - underlyingDB, err := db.DB() - if err != nil { - return nil, fmt.Errorf("unable retreive db: %w", err) - } - underlyingDB.SetMaxOpenConns(opts.withMaxOpenConnections) + wrappedOpts = append(wrappedOpts, dbw.WithMaxOpenConnections(opts.withMaxOpenConnections)) } - return &DB{db}, nil -} -type gormLogger struct { - logger hclog.Logger -} - -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]) - } + wrapped, err := dbw.OpenWith(dialect, wrappedOpts...) + if err != nil { + return nil, fmt.Errorf("%s: %w", op, err) } -} - -func getGormLogger(log hclog.Logger) gormLogger { - return gormLogger{logger: log} + return &DB{wrapped: wrapped}, nil } diff --git a/internal/db/option.go b/internal/db/option.go index 981a01a79..b6350f4f2 100644 --- a/internal/db/option.go +++ b/internal/db/option.go @@ -1,7 +1,12 @@ package db import ( + "context" + "fmt" + + "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog" + "github.com/hashicorp/go-dbw" "github.com/hashicorp/go-hclog" wrapping "github.com/hashicorp/go-kms-wrapping" ) @@ -15,6 +20,122 @@ func GetOpts(opt ...Option) Options { return opts } +func getDbwOptions(ctx context.Context, rw *Db, i interface{}, opType OpType, opt ...Option) ([]dbw.Option, error) { + const op = "db.getDbwOptions" + opts := GetOpts(opt...) + dbwOpts := make([]dbw.Option, 0, len(opt)) + oplogBefore, after, err := rw.generateOplogBeforeAfterOpts(ctx, i, opType, opts) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + before := oplogBefore + if !opts.withSkipVetForWrite && (opType != DeleteOp && opType != DeleteItemsOp) { + if vetter, ok := i.(VetForWriter); ok { + before = func(i interface{}) error { + if err := vetter.VetForWrite(ctx, rw, opType, opt...); err != nil { + return err + } + if oplogBefore != nil { + if err := oplogBefore(i); err != nil { + return err + } + } + return nil + } + } + } + if before != nil { + dbwOpts = append(dbwOpts, dbw.WithBeforeWrite(before)) + } + if after != nil { + dbwOpts = append(dbwOpts, dbw.WithAfterWrite(after)) + } + if opts.withOnConflict != nil { + c := &dbw.OnConflict{} + switch target := opts.withOnConflict.Target.(type) { + case Constraint: + c.Target = dbw.Constraint(target) + case Columns: + c.Target = dbw.Columns(target) + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a supported target type: %T", target)) + } + switch action := opts.withOnConflict.Action.(type) { + case DoNothing: + c.Action = dbw.DoNothing(bool(action)) + case UpdateAll: + c.Action = dbw.UpdateAll(bool(action)) + case []ColumnValue: + colVals := make([]dbw.ColumnValue, 0, len(action)) + for _, cv := range action { + dbwColVal := dbw.ColumnValue{ + Column: cv.column, + } + switch cvVal := cv.value.(type) { + case ExprValue: + dbwColVal.Value = dbw.ExprValue{ + Sql: cvVal.sql, + Vars: cvVal.vars, + } + case column: + dbwColVal.Column = cvVal.name + dbwColVal.Value = dbw.Column{ + Table: cvVal.table, + Name: cvVal.name, + } + default: + dbwColVal.Value = cv.value + } + colVals = append(colVals, dbwColVal) + } + c.Action = colVals + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a valid supported action: %T", action)) + } + dbwOpts = append(dbwOpts, dbw.WithOnConflict(c)) + } + if opts.withLookup { + dbwOpts = append(dbwOpts, dbw.WithLookup(opts.withLookup)) + } + if opts.WithLimit != 0 { + dbwOpts = append(dbwOpts, dbw.WithLimit(opts.WithLimit)) + } + if len(opts.WithFieldMaskPaths) > 0 { + dbwOpts = append(dbwOpts, dbw.WithFieldMaskPaths(opts.WithFieldMaskPaths)) + } + if len(opts.WithNullPaths) > 0 { + dbwOpts = append(dbwOpts, dbw.WithNullPaths(opts.WithNullPaths)) + } + if opts.WithVersion != nil { + dbwOpts = append(dbwOpts, dbw.WithVersion(opts.WithVersion)) + } + if opts.withSkipVetForWrite { + dbwOpts = append(dbwOpts, dbw.WithSkipVetForWrite(opts.withSkipVetForWrite)) + } + if opts.withWhereClause != "" { + dbwOpts = append(dbwOpts, dbw.WithWhere(opts.withWhereClause, opts.withWhereClauseArgs...)) + } + if opts.withOrder != "" { + dbwOpts = append(dbwOpts, dbw.WithOrder(opts.withOrder)) + } + if len(opts.withPrngValues) > 0 { + dbwOpts = append(dbwOpts, dbw.WithPrngValues(opts.withPrngValues)) + } + if opts.withGormFormatter != nil { + dbwOpts = append(dbwOpts, dbw.WithLogger(opts.withGormFormatter)) + } + if opts.withMaxOpenConnections > 0 { + dbwOpts = append(dbwOpts, dbw.WithMaxOpenConnections(opts.withMaxOpenConnections)) + } + if opts.withDebug { + dbwOpts = append(dbwOpts, dbw.WithDebug(opts.withDebug)) + } + if opts.withRowsAffected != nil { + dbwOpts = append(dbwOpts, dbw.WithReturnRowsAffected(opts.withRowsAffected)) + } + return dbwOpts, nil +} + // Option - how Options are passed as arguments. type Option func(*Options) diff --git a/internal/db/read_writer.go b/internal/db/read_writer.go index 87ce6104f..1a4aa3407 100644 --- a/internal/db/read_writer.go +++ b/internal/db/read_writer.go @@ -3,19 +3,16 @@ package db import ( "context" "database/sql" + stderrors "errors" "fmt" "reflect" - "strings" "time" - "github.com/hashicorp/boundary/internal/db/common" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/oplog/store" + "github.com/hashicorp/go-dbw" wrapping "github.com/hashicorp/go-kms-wrapping" - "google.golang.org/protobuf/proto" - "gorm.io/gorm" - "gorm.io/gorm/clause" ) const ( @@ -53,7 +50,7 @@ type Reader interface { LookupByPublicId(ctx context.Context, resource ResourcePublicIder, opt ...Option) error // LookupWhere will lookup and return the first resource using a where clause with parameters - LookupWhere(ctx context.Context, resource interface{}, where string, args ...interface{}) error + LookupWhere(ctx context.Context, resource interface{}, where string, args []interface{}, opt ...Option) error // SearchWhere will search for all the resources it can find using a where // clause with parameters. Supports the WithLimit option. If @@ -68,7 +65,7 @@ type Reader interface { Query(ctx context.Context, sql string, values []interface{}, opt ...Option) (*sql.Rows, error) // ScanRows will scan sql rows into the interface provided - ScanRows(rows *sql.Rows, result interface{}) error + ScanRows(ctx context.Context, rows *sql.Rows, result interface{}) error } // Writer interface defines create, update and retryable transaction handlers @@ -134,7 +131,7 @@ type Writer interface { // GetTicket returns an oplog ticket for the aggregate root of "i" which can // be used to WriteOplogEntryWith for that aggregate root. - GetTicket(i interface{}) (*store.Ticket, error) + GetTicket(ctx context.Context, i interface{}) (*store.Ticket, error) // WriteOplogEntryWith will write an oplog entry with the msgs provided for // the ticket's aggregateName. No options are currently supported. @@ -148,7 +145,7 @@ type Writer interface { ) error // ScanRows will scan sql rows into the interface provided - ScanRows(rows *sql.Rows, result interface{}) error + ScanRows(ctx context.Context, rows *sql.Rows, result interface{}) error } const ( @@ -179,10 +176,14 @@ type ResourcePrivateIder interface { type OpType int const ( - UnknownOp OpType = 0 - CreateOp OpType = 1 - UpdateOp OpType = 2 - DeleteOp OpType = 3 + UnknownOp OpType = 0 + CreateOp OpType = 1 + UpdateOp OpType = 2 + DeleteOp OpType = 3 + CreateItemsOp OpType = 4 + DeleteItemsOp OpType = 5 + LookupOp OpType = 6 + SearchOp OpType = 7 ) // VetForWriter provides an interface that Create and Update can use to vet the @@ -209,58 +210,48 @@ func New(underlying *DB) *Db { } // Exec will execute the sql with the values as parameters. The int returned -// is the number of rows affected by the sql. No options are currently -// supported. -func (rw *Db) Exec(ctx context.Context, sql string, values []interface{}, _ ...Option) (int, error) { +// is the number of rows affected by the sql. WithDebug is supported. +func (rw *Db) Exec(ctx context.Context, sql string, values []interface{}, opt ...Option) (int, error) { const op = "db.Exec" if sql == "" { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing sql") } - gormDb := rw.underlying.Exec(sql, values...) - if gormDb.Error != nil { - return NoRowsAffected, errors.Wrap(ctx, gormDb.Error, op, errors.WithoutEvent()) + opts := GetOpts(opt...) + rowsAffected, err := dbw.New(rw.underlying.wrapped).Exec(ctx, sql, values, dbw.WithDebug(opts.withDebug)) + if err != nil { + return NoRowsAffected, wrapError(ctx, err, op) } - return int(gormDb.RowsAffected), nil + return rowsAffected, nil } // Query will run the raw query and return the *sql.Rows results. Query will // operate within the context of any ongoing transaction for the db.Reader. The // caller must close the returned *sql.Rows. Query can/should be used in // combination with ScanRows. -func (rw *Db) Query(ctx context.Context, sql string, values []interface{}, _ ...Option) (*sql.Rows, error) { +func (rw *Db) Query(ctx context.Context, sql string, values []interface{}, opt ...Option) (*sql.Rows, error) { const op = "db.Query" if sql == "" { return nil, errors.New(ctx, errors.InvalidParameter, op, "missing sql") } - gormDb := rw.underlying.Raw(sql, values...) - if gormDb.Error != nil { - return nil, errors.Wrap(ctx, gormDb.Error, op, errors.WithoutEvent()) + opts := GetOpts(opt...) + rows, err := dbw.New(rw.underlying.wrapped).Query(ctx, sql, values, dbw.WithDebug(opts.withDebug)) + if err != nil { + return nil, wrapError(ctx, err, op) } - return gormDb.Rows() + return rows, nil } // Scan rows will scan the rows into the interface -func (rw *Db) ScanRows(rows *sql.Rows, result interface{}) error { +func (rw *Db) ScanRows(ctx context.Context, rows *sql.Rows, result interface{}) error { const op = "db.ScanRows" if rw.underlying == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing underlying db") + return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } if isNil(result) { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing result") + return errors.New(ctx, errors.InvalidParameter, op, "missing result") } - return rw.underlying.ScanRows(rows, result) -} - -func (rw *Db) lookupAfterWrite(ctx context.Context, i interface{}, opt ...Option) error { - const op = "db.lookupAfterWrite" - opts := GetOpts(opt...) - withLookup := opts.withLookup - - if !withLookup { - return nil - } - if err := rw.LookupById(ctx, i, opt...); err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + if err := dbw.New(rw.underlying.wrapped).ScanRows(rows, result); err != nil { + return wrapError(ctx, err, op) } return nil } @@ -285,157 +276,16 @@ func (rw *Db) Create(ctx context.Context, i interface{}, opt ...Option) error { if rw.underlying == nil { return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if isNil(i) { - return errors.New(ctx, errors.InvalidParameter, op, "missing interface") + dbwOpts, err := getDbwOptions(ctx, rw, i, CreateOp, opt...) + if err != nil { + return errors.Wrap(ctx, err, op) } - opts := GetOpts(opt...) - withOplog := opts.withOplog - if withOplog && opts.newOplogMsg != nil { - return errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsg options have been specified") - } - if withOplog { - // let's validate oplog options before we start writing to the database - _, err := validateOplogArgs(ctx, i, opts) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) - } - } - // these fields should be nil, since they are not writeable and we want the - // db to manage them - setFieldsToNil(i, []string{"CreateTime", "UpdateTime"}) - - if !opts.withSkipVetForWrite { - if vetter, ok := i.(VetForWriter); ok { - if err := vetter.VetForWrite(ctx, rw, CreateOp); err != nil { - return errors.Wrap(ctx, err, op) - } - } - } - - db := rw.underlying.WithContext(ctx) - var onConflictDoNothing bool - if opts.withOnConflict != nil { - c := clause.OnConflict{} - switch opts.withOnConflict.Target.(type) { - case Constraint: - c.OnConstraint = string(opts.withOnConflict.Target.(Constraint)) - case Columns: - columns := make([]clause.Column, 0, len(opts.withOnConflict.Target.(Columns))) - for _, name := range opts.withOnConflict.Target.(Columns) { - columns = append(columns, clause.Column{Name: name}) - } - c.Columns = columns - default: - return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid conflict target: %v", reflect.TypeOf(opts.withOnConflict.Target))) - } - - switch opts.withOnConflict.Action.(type) { - case DoNothing: - c.DoNothing = true - onConflictDoNothing = true - case UpdateAll: - c.UpdateAll = true - case []ColumnValue: - updates := opts.withOnConflict.Action.([]ColumnValue) - set := make(clause.Set, 0, len(updates)) - for _, s := range updates { - // make sure it's not one of the std immutable columns - if contains([]string{"createtime", "publicid"}, strings.ToLower(s.column)) { - return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("Cannot do update on conflict for column %s", s.column)) - } - switch sv := s.value.(type) { - case column: - set = append(set, sv.toAssignment(s.column)) - case ExprValue: - set = append(set, sv.toAssignment(s.column)) - default: - set = append(set, rawAssignment(s.column, s.value)) - } - } - c.DoUpdates = set - default: - return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid conflict action: %v", reflect.TypeOf(opts.withOnConflict.Action))) - } - if opts.WithVersion != nil || opts.withWhereClause != "" { - where, args, err := rw.whereClausesFromOpts(ctx, i, opts) - if err != nil { - return errors.Wrap(ctx, err, op) - } - whereConditions := db.Statement.BuildCondition(where, args...) - c.Where = clause.Where{Exprs: whereConditions} - } - db = db.Clauses(c) - } - if opts.withDebug { - db = db.Debug() - } - - var ticket *store.Ticket - if withOplog { - var err error - ticket, err = rw.GetTicket(i) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) - } - } - tx := db.Create(i) - if tx.Error != nil { - return errors.Wrap(ctx, tx.Error, op, errors.WithMsg("create failed"), errors.WithoutEvent()) - } - if opts.withRowsAffected != nil { - *opts.withRowsAffected = tx.RowsAffected - } - if withOplog { - switch { - case onConflictDoNothing && tx.RowsAffected == 0: - default: - if err := rw.addOplog(ctx, CreateOp, opts, ticket, i); err != nil { - return errors.Wrap(ctx, err, op) - } - } - } - if opts.newOplogMsg != nil { - switch { - case onConflictDoNothing && tx.RowsAffected == 0: - default: - msg, err := rw.newOplogMessage(ctx, CreateOp, i) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog failed")) - } - *opts.newOplogMsg = *msg - } - } - if err := rw.lookupAfterWrite(ctx, i, opt...); err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + if err := dbw.New(rw.underlying.wrapped).Create(ctx, i, dbwOpts...); err != nil { + return wrapError(ctx, err, op) } return nil } -func (rw *Db) whereClausesFromOpts(ctx context.Context, i interface{}, opts Options) (string, []interface{}, error) { - const op = "db.whereClausesFromOpts" - var where []string - var args []interface{} - if opts.WithVersion != nil { - if *opts.WithVersion == 0 { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, "with version option is zero") - } - mDb := rw.underlying.Model(i) - err := mDb.Statement.Parse(i) - if err != nil && mDb.Statement.Schema == nil { - return "", nil, errors.New(ctx, errors.Unknown, op, "internal error: unable to parse stmt", errors.WithWrap(err)) - } - if !contains(mDb.Statement.Schema.DBNames, "version") { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s does not have a version field", mDb.Statement.Schema.Table)) - } - where = append(where, fmt.Sprintf("%s.version = ?", mDb.Statement.Schema.Table)) // we need to include the table name because of "on conflict" use cases - args = append(args, opts.WithVersion) - } - if opts.withWhereClause != "" { - where, args = append(where, opts.withWhereClause), append(args, opts.withWhereClauseArgs...) - } - return strings.Join(where, " and "), args, nil -} - // CreateItems will create multiple items of the same type. Supported options: // WithDebug, WithOplog, WithOplogMsgs, WithReturnRowsAffected, OnConflict, // WithVersion, and WithWhere WithOplog and WithOplogMsgs may not be used @@ -445,63 +295,12 @@ func (rw *Db) CreateItems(ctx context.Context, createItems []interface{}, opt .. if rw.underlying == nil { return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if len(createItems) == 0 { - return errors.New(ctx, errors.InvalidParameter, op, "missing interfaces") + dbwOpts, err := getDbwOptions(ctx, rw, createItems, CreateItemsOp, opt...) + if err != nil { + return errors.Wrap(ctx, err, op) } - opts := GetOpts(opt...) - if opts.withLookup { - return errors.New(ctx, errors.InvalidParameter, op, "with lookup not a supported option") - } - if opts.newOplogMsg != nil { - return errors.New(ctx, errors.InvalidParameter, op, "new oplog msg (singular) is not a supported option") - } - if opts.withOplog && opts.newOplogMsgs != nil { - return errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsgs options have been specified") - } - // verify that createItems are all the same type. - var foundType reflect.Type - for i, v := range createItems { - if i == 0 { - foundType = reflect.TypeOf(v) - } - currentType := reflect.TypeOf(v) - if foundType != currentType { - return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("create items contains disparate types. item %d is not a %s", i, foundType.Name())) - } - } - var ticket *store.Ticket - if opts.withOplog { - _, err := validateOplogArgs(ctx, createItems[0], opts) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) - } - ticket, err = rw.GetTicket(createItems[0]) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) - } - } - for _, item := range createItems { - if err := rw.Create(ctx, item, - WithOnConflict(opts.withOnConflict), - WithReturnRowsAffected(opts.withRowsAffected), - WithDebug(opts.withDebug), - WithVersion(opts.WithVersion), - WithWhere(opts.withWhereClause, opts.withWhereClauseArgs...), - ); err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - } - if opts.withOplog { - if err := rw.addOplogForItems(ctx, CreateOp, opts, ticket, createItems); err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to add oplog")) - } - } - if opts.newOplogMsgs != nil { - msgs, err := rw.oplogMsgsForItems(ctx, CreateOp, opts, createItems) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog msgs failed")) - } - *opts.newOplogMsgs = append(*opts.newOplogMsgs, msgs...) + if err := dbw.New(rw.underlying.wrapped).CreateItems(ctx, createItems, dbwOpts...); err != nil { + return wrapError(ctx, err, op) } return nil } @@ -531,130 +330,16 @@ func (rw *Db) Update(ctx context.Context, i interface{}, fieldMaskPaths []string if rw.underlying == nil { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if isNil(i) { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing interface") - } - if len(fieldMaskPaths) == 0 && len(setToNullPaths) == 0 { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "both fieldMaskPaths and setToNullPaths are missing") - } - opts := GetOpts(opt...) - withOplog := opts.withOplog - if withOplog && opts.newOplogMsg != nil { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsg options have been specified") - } - - // we need to filter out some non-updatable fields (like: CreateTime, etc) - fieldMaskPaths = filterPaths(fieldMaskPaths) - setToNullPaths = filterPaths(setToNullPaths) - if len(fieldMaskPaths) == 0 && len(setToNullPaths) == 0 { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "after filtering non-updated fields, there are no fields left in fieldMaskPaths or setToNullPaths") - } - - updateFields, err := common.UpdateFields(i, fieldMaskPaths, setToNullPaths) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("getting update fields failed")) - } - if len(updateFields) == 0 { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("no fields matched using fieldMaskPaths %s", fieldMaskPaths)) - } - - names, isZero, err := rw.primaryFieldsAreZero(ctx, i) + optCp := make([]Option, 0, len(opt)+2) + optCp = append(optCp, opt...) + optCp = append(optCp, WithFieldMaskPaths(fieldMaskPaths), WithNullPaths(setToNullPaths)) + dbwOpts, err := getDbwOptions(ctx, rw, i, UpdateOp, optCp...) 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()) - } - - 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)) - } - } - - if withOplog { - // let's validate oplog options before we start writing to the database - _, err := validateOplogArgs(ctx, i, opts) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) - } - } - if !opts.withSkipVetForWrite { - if vetter, ok := i.(VetForWriter); ok { - if err := vetter.VetForWrite(ctx, rw, UpdateOp, WithFieldMaskPaths(fieldMaskPaths), WithNullPaths(setToNullPaths)); err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op) - } - } - } - var ticket *store.Ticket - if withOplog { - var err error - ticket, err = rw.GetTicket(i) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) - } - } - underlying := rw.underlying.Model(i) - if opts.withDebug { - underlying = underlying.Debug() - } - switch { - case opts.WithVersion != nil || opts.withWhereClause != "": - where, args, err := rw.whereClausesFromOpts(ctx, i, opts) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op) - } - underlying = underlying.Where(where, args...).Updates(updateFields) - default: - underlying = underlying.Updates(updateFields) - } - if underlying.Error != nil { - if underlying.Error == gorm.ErrRecordNotFound { - return NoRowsAffected, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op), errors.WithoutEvent()) - } - return NoRowsAffected, errors.Wrap(ctx, underlying.Error, op, errors.WithoutEvent()) - } - rowsUpdated := int(underlying.RowsAffected) - if rowsUpdated > 0 && (withOplog || opts.newOplogMsg != nil) { - // we don't want to change the inbound slices in opts, so we'll make our - // own copy to pass to addOplog() - oplogFieldMasks := make([]string, len(fieldMaskPaths)) - copy(oplogFieldMasks, fieldMaskPaths) - oplogNullPaths := make([]string, len(setToNullPaths)) - copy(oplogNullPaths, setToNullPaths) - oplogOpts := Options{ - oplogOpts: opts.oplogOpts, - withOplog: opts.withOplog, - WithFieldMaskPaths: oplogFieldMasks, - WithNullPaths: oplogNullPaths, - } - if withOplog { - if err := rw.addOplog(ctx, UpdateOp, oplogOpts, ticket, i); err != nil { - return rowsUpdated, errors.Wrap(ctx, err, op, errors.WithMsg("add oplog failed")) - } - } - if opts.newOplogMsg != nil { - msg, err := rw.newOplogMessage(ctx, UpdateOp, i, WithFieldMaskPaths(oplogFieldMasks), WithNullPaths(oplogNullPaths)) - if err != nil { - return rowsUpdated, errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog failed")) - } - *opts.newOplogMsg = *msg - } - } - // we need to force a lookupAfterWrite so the resource returned is correctly initialized - // from the db - opt = append(opt, WithLookup(true)) - if err := rw.lookupAfterWrite(ctx, i, opt...); err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithoutEvent()) + rowsUpdated, err := dbw.New(rw.underlying.wrapped).Update(ctx, i, fieldMaskPaths, setToNullPaths, dbwOpts...) + if err != nil { + return NoRowsAffected, wrapError(ctx, err, op) } return rowsUpdated, nil } @@ -669,68 +354,15 @@ func (rw *Db) Delete(ctx context.Context, i interface{}, opt ...Option) (int, er if rw.underlying == nil { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if isNil(i) { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing interface") + dbwOpts, err := getDbwOptions(ctx, rw, i, DeleteOp, opt...) + if err != nil { + return NoRowsAffected, wrapError(ctx, err, op) } - opts := GetOpts(opt...) - withOplog := opts.withOplog - if withOplog && opts.newOplogMsg != nil { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsg options have been specified") + rowsUpdated, err := dbw.New(rw.underlying.wrapped).Delete(ctx, i, dbwOpts...) + if err != nil { + return NoRowsAffected, wrapError(ctx, err, op) } - - 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 { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) - } - } - var ticket *store.Ticket - if withOplog { - var err error - ticket, err = rw.GetTicket(i) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) - } - } - db := rw.underlying.DB - if opts.withWhereClause != "" { - db = db.Where(opts.withWhereClause, opts.withWhereClauseArgs...) - } - if opts.withDebug { - db = db.Debug() - } - db = db.Delete(i) - if db.Error != nil { - return NoRowsAffected, errors.Wrap(ctx, db.Error, op, errors.WithoutEvent()) - } - rowsDeleted := int(db.RowsAffected) - if rowsDeleted > 0 && (withOplog || opts.newOplogMsg != nil) { - if withOplog { - if err := rw.addOplog(ctx, DeleteOp, opts, ticket, i); err != nil { - return rowsDeleted, errors.Wrap(ctx, err, op, errors.WithMsg("add oplog failed")) - } - } - if opts.newOplogMsg != nil { - msg, err := rw.newOplogMessage(ctx, DeleteOp, i) - if err != nil { - return rowsDeleted, errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog failed")) - } - *opts.newOplogMsg = *msg - } - } - return rowsDeleted, nil + return rowsUpdated, nil } // DeleteItems will delete multiple items of the same type. Supported options: @@ -741,312 +373,32 @@ func (rw *Db) DeleteItems(ctx context.Context, deleteItems []interface{}, opt .. if rw.underlying == nil { return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if len(deleteItems) == 0 { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "no interfaces to delete") + dbwOpts, err := getDbwOptions(ctx, rw, deleteItems, DeleteItemsOp, opt...) + if err != nil { + return NoRowsAffected, errors.Wrap(ctx, err, op) } - opts := GetOpts(opt...) - if opts.newOplogMsg != nil { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "new oplog msg (singular) is not a supported option") - } - if opts.withOplog && opts.newOplogMsgs != nil { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsgs options have been specified") - } - // verify that createItems are all the same type. - var foundType reflect.Type - for i, v := range deleteItems { - if i == 0 { - foundType = reflect.TypeOf(v) - } - currentType := reflect.TypeOf(v) - if foundType != currentType { - return NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("items contain disparate types. item %d is not a %s", i, foundType.Name())) - } - } - - var ticket *store.Ticket - if opts.withOplog { - _, err := validateOplogArgs(ctx, deleteItems[0], opts) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) - } - ticket, err = rw.GetTicket(deleteItems[0]) - if err != nil { - return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) - } - } - rowsDeleted := 0 - for _, item := range deleteItems { - // calling delete directly on the underlying db, since the writer.Delete - // doesn't provide capabilities needed here (which is different from the - // relationship between Create and CreateItems). - underlying := rw.underlying.Delete(item) - if underlying.Error != nil { - return rowsDeleted, errors.Wrap(ctx, underlying.Error, op, errors.WithoutEvent()) - } - rowsDeleted += int(underlying.RowsAffected) - } - if rowsDeleted > 0 && (opts.withOplog || opts.newOplogMsgs != nil) { - if opts.withOplog { - if err := rw.addOplogForItems(ctx, DeleteOp, opts, ticket, deleteItems); err != nil { - return rowsDeleted, errors.Wrap(ctx, err, op, errors.WithMsg("unable to add oplog")) - } - } - if opts.newOplogMsgs != nil { - msgs, err := rw.oplogMsgsForItems(ctx, DeleteOp, opts, deleteItems) - if err != nil { - return rowsDeleted, errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog msgs failed")) - } - *opts.newOplogMsgs = append(*opts.newOplogMsgs, msgs...) - } + rowsDeleted, err := dbw.New(rw.underlying.wrapped).DeleteItems(ctx, deleteItems, dbwOpts...) + if err != nil { + return NoRowsAffected, wrapError(ctx, err, op) } return rowsDeleted, nil } -func validateOplogArgs(ctx context.Context, i interface{}, opts Options) (oplog.ReplayableMessage, error) { - const op = "db.validateOplogArgs" - oplogArgs := opts.oplogOpts - if oplogArgs.wrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing wrapper", errors.WithoutEvent()) - } - if len(oplogArgs.metadata) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing metadata", errors.WithoutEvent()) - } - replayable, ok := i.(oplog.ReplayableMessage) - if !ok { - return nil, errors.E(ctx, errors.WithOp(op), errors.WithMsg("not a replayable message"), errors.WithoutEvent()) - } - return replayable, nil -} - -func (rw *Db) getTicketFor(aggregateName string) (*store.Ticket, error) { - const op = "db.getTicketFor" - if rw.underlying == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprintf("%s: underlying db missing", aggregateName), errors.WithoutEvent()) - } - ticketer, err := oplog.NewGormTicketer(rw.underlying.DB, oplog.WithAggregateNames(true)) - if err != nil { - return nil, errors.WrapDeprecated(err, op, errors.WithMsg(fmt.Sprintf("%s: unable to get Ticketer", aggregateName)), errors.WithoutEvent()) - } - ticket, err := ticketer.GetTicket(aggregateName) - if err != nil { - return nil, errors.WrapDeprecated(err, op, errors.WithMsg(fmt.Sprintf("%s: unable to get ticket", aggregateName)), errors.WithoutEvent()) - } - return ticket, nil -} - -// GetTicket returns an oplog ticket for the aggregate root of "i" which can -// be used to WriteOplogEntryWith for that aggregate root. -func (rw *Db) GetTicket(i interface{}) (*store.Ticket, error) { - const op = "db.GetTicket" - if rw.underlying == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing underlying db", errors.WithoutEvent()) - } - if isNil(i) { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing interface", errors.WithoutEvent()) - } - replayable, ok := i.(oplog.ReplayableMessage) - if !ok { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "not a replayable message", errors.WithoutEvent()) - } - return rw.getTicketFor(replayable.TableName()) -} - -func (rw *Db) oplogMsgsForItems(ctx context.Context, opType OpType, opts Options, items []interface{}) ([]*oplog.Message, error) { - const op = "db.oplogMsgsForItems" - if len(items) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing items", errors.WithoutEvent()) - } - oplogMsgs := []*oplog.Message{} - var foundType reflect.Type - for i, item := range items { - if i == 0 { - foundType = reflect.TypeOf(item) - } - currentType := reflect.TypeOf(item) - if foundType != currentType { - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("items contains disparate types. item (%d) %s is not a %s", i, currentType, foundType), errors.WithoutEvent()) - } - msg, err := rw.newOplogMessage(ctx, opType, item, WithFieldMaskPaths(opts.WithFieldMaskPaths), WithNullPaths(opts.WithNullPaths)) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - oplogMsgs = append(oplogMsgs, msg) - } - return oplogMsgs, nil -} - -// addOplogForItems will add a multi-message oplog entry with one msg for each -// item. Items must all be of the same type. Only CreateOp and DeleteOp are -// currently supported operations. -func (rw *Db) addOplogForItems(ctx context.Context, opType OpType, opts Options, ticket *store.Ticket, items []interface{}) error { - const op = "db.addOplogForItems" - oplogArgs := opts.oplogOpts - if ticket == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing ticket", errors.WithoutEvent()) - } - if len(items) == 0 { - return errors.New(ctx, errors.InvalidParameter, op, "missing items", errors.WithoutEvent()) - } - if oplogArgs.metadata == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing metadata", errors.WithoutEvent()) - } - if oplogArgs.wrapper == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing wrapper", errors.WithoutEvent()) - } - - oplogMsgs, err := rw.oplogMsgsForItems(ctx, opType, opts, items) - if err != nil { - return errors.Wrap(ctx, err, op) - } - - replayable, err := validateOplogArgs(ctx, items[0], opts) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed"), errors.WithoutEvent()) - } - ticketer, err := oplog.NewGormTicketer(rw.underlying.DB, oplog.WithAggregateNames(true)) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer"), errors.WithoutEvent()) - } - entry, err := oplog.NewEntry( - replayable.TableName(), - oplogArgs.metadata, - oplogArgs.wrapper, - ticketer, - ) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create oplog entry"), errors.WithoutEvent()) - } - if err := entry.WriteEntryWith( - ctx, - &oplog.GormWriter{Tx: rw.underlying.DB}, - ticket, - oplogMsgs..., - ); err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry"), errors.WithoutEvent()) - } - return nil -} - -func (rw *Db) addOplog(ctx context.Context, opType OpType, opts Options, ticket *store.Ticket, i interface{}) error { - const op = "db.addOplog" - oplogArgs := opts.oplogOpts - replayable, err := validateOplogArgs(ctx, i, opts) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - if ticket == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing ticket", errors.WithoutEvent()) - } - ticketer, err := oplog.NewGormTicketer(rw.underlying.DB, oplog.WithAggregateNames(true)) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer"), errors.WithoutEvent()) - } - entry, err := oplog.NewEntry( - replayable.TableName(), - oplogArgs.metadata, - oplogArgs.wrapper, - ticketer, - ) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - msg, err := rw.newOplogMessage(ctx, opType, i, WithFieldMaskPaths(opts.WithFieldMaskPaths), WithNullPaths(opts.WithNullPaths)) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - err = entry.WriteEntryWith( - ctx, - &oplog.GormWriter{Tx: rw.underlying.DB}, - ticket, - msg, - ) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry"), errors.WithoutEvent()) - } - return nil -} - -// WriteOplogEntryWith will write an oplog entry with the msgs provided for -// the ticket's aggregateName. No options are currently supported. -func (rw *Db) WriteOplogEntryWith(ctx context.Context, wrapper wrapping.Wrapper, ticket *store.Ticket, metadata oplog.Metadata, msgs []*oplog.Message, _ ...Option) error { - const op = "db.WriteOplogEntryWith" - if wrapper == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing wrapper") - } - if ticket == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing ticket") - } - if len(msgs) == 0 { - return errors.New(ctx, errors.InvalidParameter, op, "missing msgs") - } - if rw.underlying == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") - } - if len(metadata) == 0 { - return errors.New(ctx, errors.InvalidParameter, op, "missing metadata") - } - - ticketer, err := oplog.NewGormTicketer(rw.underlying.DB, oplog.WithAggregateNames(true)) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer")) - } - - entry, err := oplog.NewEntry( - ticket.Name, - metadata, - wrapper, - ticketer, - ) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create oplog entry")) - } - err = entry.WriteEntryWith( - ctx, - &oplog.GormWriter{Tx: rw.underlying.DB}, - ticket, - msgs..., - ) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry")) - } - return nil -} - -func (rw *Db) newOplogMessage(ctx context.Context, opType OpType, i interface{}, opt ...Option) (*oplog.Message, error) { - const op = "db.newOplogMessage" - opts := GetOpts(opt...) - replayable, ok := i.(oplog.ReplayableMessage) - if !ok { - return nil, errors.New(ctx, errors.InvalidParameter, op, "not a replayable interface", errors.WithoutEvent()) - } - msg := oplog.Message{ - Message: i.(proto.Message), - TypeName: replayable.TableName(), - } - switch opType { - case CreateOp: - msg.OpType = oplog.OpType_OP_TYPE_CREATE - case UpdateOp: - msg.OpType = oplog.OpType_OP_TYPE_UPDATE - msg.FieldMaskPaths = opts.WithFieldMaskPaths - msg.SetToNullPaths = opts.WithNullPaths - case DeleteOp: - msg.OpType = oplog.OpType_OP_TYPE_DELETE - default: - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("operation type %v is not supported", opType), errors.WithoutEvent()) - } - return &msg, nil -} - // DoTx will wrap the Handler func passed within a transaction with retries // you should ensure that any objects written to the db in your TxHandler are retryable, which // means that the object may be sent to the db several times (retried), so things like the primary key must // be reset before retry -func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, Handler TxHandler) (RetryInfo, error) { +func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, handler TxHandler) (RetryInfo, error) { const op = "db.DoTx" if w.underlying == nil { return RetryInfo{}, errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } + if backOff == nil { + return RetryInfo{}, errors.New(ctx, errors.InvalidParameter, op, "missing backoff") + } + if handler == nil { + return RetryInfo{}, errors.New(ctx, errors.InvalidParameter, op, "missing handler") + } info := RetryInfo{} for attempts := uint(1); ; attempts++ { if attempts > retries+1 { @@ -1054,13 +406,15 @@ func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, Handler Tx } // step one of this, start a transaction... - newTx := w.underlying.WithContext(ctx) - newTx = newTx.Begin() + beginTx, err := dbw.New(w.underlying.wrapped).Begin(ctx) + if err != nil { + return info, wrapError(ctx, err, op) + } + newRW := New(&DB{wrapped: beginTx.DB()}) - rw := &Db{underlying: &DB{newTx}} - if err := Handler(rw, rw); err != nil { - if err := newTx.Rollback().Error; err != nil { - return info, errors.Wrap(ctx, err, op, errors.WithoutEvent()) + if err := handler(newRW, newRW); err != nil { + if err := beginTx.Rollback(ctx); err != nil { + return info, wrapError(ctx, err, op) } if errors.Match(errors.T(errors.TicketAlreadyRedeemed), err) { d := backOff.Duration(attempts) @@ -1072,8 +426,8 @@ func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, Handler Tx return info, errors.Wrap(ctx, err, op, errors.WithoutEvent()) } - if err := newTx.Commit().Error; err != nil { - if err := newTx.Rollback().Error; err != nil { + if err := beginTx.Commit(ctx); err != nil { + if err := beginTx.Rollback(ctx); err != nil { return info, errors.Wrap(ctx, err, op) } return info, errors.Wrap(ctx, err, op) @@ -1084,91 +438,34 @@ func (w *Db) DoTx(ctx context.Context, retries uint, backOff Backoff, Handler Tx // LookupByPublicId will lookup resource by its public_id or private_id, which // must be unique. Options are ignored. -func (rw *Db) LookupById(ctx context.Context, resourceWithIder interface{}, _ ...Option) error { +func (rw *Db) LookupById(ctx context.Context, resourceWithIder interface{}, opt ...Option) error { const op = "db.LookupById" if rw.underlying == nil { return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if reflect.ValueOf(resourceWithIder).Kind() != reflect.Ptr { - return errors.New(ctx, errors.InvalidParameter, op, "interface parameter must to be a pointer") - } - where, keys, err := rw.primaryKeysWhere(ctx, resourceWithIder) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if err := rw.underlying.Where(where, keys...).First(resourceWithIder).Error; err != nil { - if err == gorm.ErrRecordNotFound { - return errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op), errors.WithoutEvent()) - } - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + opts := GetOpts(opt...) + if err := dbw.New(rw.underlying.wrapped).LookupBy(ctx, resourceWithIder, dbw.WithDebug(opts.withDebug)); err != nil { + return wrapError(ctx, err, op) } return nil } -func (rw *Db) primaryKeysWhere(ctx context.Context, i interface{}) (string, []interface{}, error) { - const op = "db.primaryKeysWhere" - var fieldNames []string - var fieldValues []interface{} - tx := rw.underlying.Model(i) - if err := tx.Statement.Parse(i); err != nil { - return "", nil, errors.Wrap(ctx, err, op, errors.WithoutEvent()) - } - switch resourceType := i.(type) { - case ResourcePublicIder: - if resourceType.GetPublicId() == "" { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, "missing primary key", errors.WithoutEvent()) - } - fieldValues = []interface{}{resourceType.GetPublicId()} - fieldNames = []string{"public_id"} - case ResourcePrivateIder: - if resourceType.GetPrivateId() == "" { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, "missing primary key", errors.WithoutEvent()) - } - fieldValues = []interface{}{resourceType.GetPrivateId()} - fieldNames = []string{"private_id"} - default: - v := reflect.ValueOf(i) - for _, f := range tx.Statement.Schema.PrimaryFields { - if f.PrimaryKey { - val, isZero := f.ValueOf(v) - if isZero { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("primary field %s is zero", f.Name)) - } - fieldNames = append(fieldNames, f.DBName) - fieldValues = append(fieldValues, val) - } - } - } - if len(fieldNames) == 0 { - return "", nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("no primary key(s) for %t", i)) - } - clauses := make([]string, 0, len(fieldNames)) - for _, col := range fieldNames { - clauses = append(clauses, fmt.Sprintf("%s = ?", col)) - } - return strings.Join(clauses, " and "), fieldValues, nil -} - // LookupByPublicId will lookup resource by its public_id, which must be unique. -// Options are ignored. +// WithDebug is supported. func (rw *Db) LookupByPublicId(ctx context.Context, resource ResourcePublicIder, opt ...Option) error { return rw.LookupById(ctx, resource, opt...) } -// LookupWhere will lookup the first resource using a where clause with parameters (it only returns the first one) -func (rw *Db) LookupWhere(ctx context.Context, resource interface{}, where string, args ...interface{}) error { +// LookupWhere will lookup the first resource using a where clause with +// parameters (it only returns the first one). WithDebug is supported. +func (rw *Db) LookupWhere(ctx context.Context, resource interface{}, where string, args []interface{}, opt ...Option) error { const op = "db.LookupWhere" if rw.underlying == nil { return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if reflect.ValueOf(resource).Kind() != reflect.Ptr { - return errors.New(ctx, errors.InvalidParameter, op, "interface parameter must to be a pointer") - } - if err := rw.underlying.Where(where, args...).First(resource).Error; err != nil { - if err == gorm.ErrRecordNotFound { - return errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op), errors.WithoutEvent()) - } - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + opts := GetOpts(opt...) + if err := dbw.New(rw.underlying.wrapped).LookupWhere(ctx, resource, where, args, dbw.WithDebug(opts.withDebug)); err != nil { + return wrapError(ctx, err, op) } return nil } @@ -1182,89 +479,19 @@ func (rw *Db) LookupWhere(ctx context.Context, resource interface{}, where strin // Supports the WithOrder and WithDebug options. func (rw *Db) SearchWhere(ctx context.Context, resources interface{}, where string, args []interface{}, opt ...Option) error { const op = "db.SearchWhere" - opts := GetOpts(opt...) if rw.underlying == nil { return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") } - if where == "" && len(args) > 0 { - return errors.New(ctx, errors.InvalidParameter, op, "args provided with empty where") - } - if reflect.ValueOf(resources).Kind() != reflect.Ptr { - return errors.New(ctx, errors.InvalidParameter, op, "interface parameter must to be a pointer") - } - var err error - db := rw.underlying.WithContext(ctx) - if opts.withOrder != "" { - db = db.Order(opts.withOrder) - } - if opts.withDebug { - db = db.Debug() - } - // Perform limiting - switch { - case opts.WithLimit < 0: // any negative number signals unlimited results - case opts.WithLimit == 0: // zero signals the default value and default limits - db = db.Limit(DefaultLimit) - default: - db = db.Limit(opts.WithLimit) - } - - if where != "" { - db = db.Where(where, args...) - } - - // Perform the query - err = db.Find(resources).Error + dbwOpts, err := getDbwOptions(ctx, rw, resources, SearchOp, opt...) if err != nil { - // searching with a slice parameter does not return a gorm.ErrRecordNotFound - return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + return errors.Wrap(ctx, err, op) + } + if err := dbw.New(rw.underlying.wrapped).SearchWhere(ctx, resources, where, args, dbwOpts...); err != nil { + return wrapError(ctx, err, op) } 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 { - return nil - } - var filtered []string - for _, p := range paths { - switch { - case strings.EqualFold(p, "CreateTime"): - continue - case strings.EqualFold(p, "UpdateTime"): - continue - case strings.EqualFold(p, "PublicId"): - continue - default: - filtered = append(filtered, p) - } - } - return filtered -} - -func setFieldsToNil(i interface{}, fieldNames []string) { - // Note: error cases are not handled - _ = Clear(i, fieldNames, 2) -} - func isNil(i interface{}) bool { if i == nil { return true @@ -1276,65 +503,23 @@ func isNil(i interface{}) bool { return false } -func contains(ss []string, t string) bool { - for _, s := range ss { - if strings.EqualFold(s, t) { - return true - } - } - return false -} - -// Clear sets fields in the value pointed to by i to their zero value. -// Clear descends i to depth clearing fields at each level. i must be a -// pointer to a struct. Cycles in i are not detected. -// -// A depth of 2 will change i and i's children. A depth of 1 will change i -// but no children of i. A depth of 0 will return with no changes to i. -func Clear(i interface{}, fields []string, depth int) error { - const op = "db.Clear" - if len(fields) == 0 || depth == 0 { - return nil - } - fm := make(map[string]bool) - for _, f := range fields { - fm[f] = true - } - - v := reflect.ValueOf(i) - - switch v.Kind() { - case reflect.Ptr: - if v.IsNil() || v.Elem().Kind() != reflect.Struct { - return errors.EDeprecated(errors.WithCode(errors.InvalidParameter), errors.WithOp(op), errors.WithoutEvent()) - } - clear(v, fm, depth) +func wrapError(ctx context.Context, err error, op string, errOpts ...errors.Option) error { + // See github.com/hashicorp/go-dbw/error.go for appropriate errors to test + // for and wrap + switch { + case stderrors.Is(err, dbw.ErrUnknown): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.Unknown)) + case stderrors.Is(err, dbw.ErrInvalidParameter): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.InvalidParameter)) + case stderrors.Is(err, dbw.ErrInternal): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.Internal)) + case stderrors.Is(err, dbw.ErrRecordNotFound): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.RecordNotFound)) + case stderrors.Is(err, dbw.ErrMaxRetries): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.MaxRetries)) + case stderrors.Is(err, dbw.ErrInvalidFieldMask): + return errors.Wrap(ctx, err, errors.Op(op), errors.WithCode(errors.InvalidFieldMask)) default: - return errors.EDeprecated(errors.WithCode(errors.InvalidParameter), errors.WithOp(op), errors.WithoutEvent()) - } - return nil -} - -func clear(v reflect.Value, fields map[string]bool, depth int) { - if depth == 0 { - return - } - depth-- - - switch v.Kind() { - case reflect.Ptr: - clear(v.Elem(), fields, depth+1) - case reflect.Struct: - typeOfT := v.Type() - for i := 0; i < v.NumField(); i++ { - f := v.Field(i) - if ok := fields[typeOfT.Field(i).Name]; ok { - if f.IsValid() && f.CanSet() { - f.Set(reflect.Zero(f.Type())) - } - continue - } - clear(f, fields, depth) - } + return errors.Wrap(ctx, err, errors.Op(op), errOpts...) } } diff --git a/internal/db/read_writer_oplog.go b/internal/db/read_writer_oplog.go new file mode 100644 index 000000000..4efe84792 --- /dev/null +++ b/internal/db/read_writer_oplog.go @@ -0,0 +1,388 @@ +package db + +import ( + "context" + "fmt" + "reflect" + + "github.com/hashicorp/boundary/internal/errors" + "github.com/hashicorp/boundary/internal/oplog" + "github.com/hashicorp/boundary/internal/oplog/store" + "github.com/hashicorp/go-dbw" + wrapping "github.com/hashicorp/go-kms-wrapping" + "google.golang.org/protobuf/proto" +) + +type ( + beforeWriteFn func(interface{}) error + afterWriteFn func(interface{}, int) error +) + +func (rw *Db) generateOplogBeforeAfterOpts(ctx context.Context, i interface{}, opType OpType, opts Options) (beforeWriteFn, afterWriteFn, error) { + const op = "db.generateOplogBeforeAfterOpts" + withOplog := opts.withOplog + if !withOplog && opts.newOplogMsg == nil && opts.newOplogMsgs == nil { + return nil, nil, nil // nothing to do, so we're done + } + if withOplog && opts.newOplogMsg != nil { + return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsg options have been specified") + } + if opts.withOplog && opts.newOplogMsgs != nil { + return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "both WithOplog and NewOplogMsgs options have been specified") + } + if opts.newOplogMsg != nil && opts.newOplogMsgs != nil { + return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "both NewOplogMsg and NewOplogMsgs (plural) options have been specified") + } + + var isSlice bool + var items []interface{} + rv := reflect.ValueOf(i) + if isSlice = rv.Kind() == reflect.Slice; isSlice { + for i := 0; i < rv.Len(); i++ { + items = append(items, rv.Index(i).Interface()) + } + } + if isSlice { + switch opType { + case CreateOp, DeleteOp, UpdateOp: + return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "Cannot use a slice on a single item operation") + } + } + + // let's validate oplog options before we start writing to the database + switch { + case isSlice && withOplog: + if _, err := validateOplogArgs(ctx, items[0], opts); err != nil { + return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) + } + case withOplog: + if _, err := validateOplogArgs(ctx, i, opts); err != nil { + return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed")) + } + } + + var onConflictDoNothing bool + if opts.withOnConflict != nil { + switch opts.withOnConflict.Action.(type) { + case dbw.DoNothing: + onConflictDoNothing = true + } + } + + var beforeFn beforeWriteFn + var afterFn afterWriteFn + + var ticket *store.Ticket + if opts.withOplog { + beforeFn = func(interface{}) error { + const op = "db.beforeFn" + var err error + switch isSlice { + case true: + ticket, err = rw.GetTicket(ctx, items[0]) + default: + ticket, err = rw.GetTicket(ctx, i) + } + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) + } + return nil + } + } + switch { + case withOplog && (opType == CreateOp || opType == UpdateOp || opType == DeleteOp): + afterFn = func(i interface{}, rowsAffected int) error { + const op = "db.afterFnSingleItem" + switch { + case onConflictDoNothing && rowsAffected == 0: + default: + if err := rw.addOplog(ctx, CreateOp, opts, ticket, i); err != nil { + return errors.Wrap(ctx, err, op) + } + } + return nil + } + case withOplog && (opType == CreateItemsOp || opType == DeleteItemsOp): + afterFn = func(i interface{}, rowsAffected int) error { + const op = "db.afterFnMultiItem" + err := rw.addOplogForItems(ctx, opType, opts, ticket, i.([]interface{})) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog msgs failed")) + } + return nil + } + case opts.newOplogMsg != nil: + if isSlice { + return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "new oplog msg (singular) is not a supported option") + } + afterFn = func(i interface{}, rowsAffected int) error { + const op = "db.afterFnNewOplogMsg" + switch { + case onConflictDoNothing && rowsAffected == 0: + default: + msg, err := rw.newOplogMessage(ctx, CreateOp, i) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog failed")) + } + *opts.newOplogMsg = *msg + } + return nil + } + + case opts.newOplogMsgs != nil: + afterFn = func(i interface{}, rowsAffected int) error { + const op = "db.afterFnNewOplogMsgs" + if rowsAffected > 0 { + msgs, err := rw.oplogMsgsForItems(ctx, CreateOp, opts, items) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("returning oplog msgs failed")) + } + *opts.newOplogMsgs = append(*opts.newOplogMsgs, msgs...) + } + return nil + } + } + return beforeFn, afterFn, nil +} + +func validateOplogArgs(ctx context.Context, i interface{}, opts Options) (oplog.ReplayableMessage, error) { + const op = "db.validateOplogArgs" + oplogArgs := opts.oplogOpts + if oplogArgs.wrapper == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing wrapper", errors.WithoutEvent()) + } + if len(oplogArgs.metadata) == 0 { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing metadata", errors.WithoutEvent()) + } + replayable, ok := i.(oplog.ReplayableMessage) + if !ok { + return nil, errors.E(ctx, errors.WithOp(op), errors.WithMsg("not a replayable message"), errors.WithoutEvent()) + } + return replayable, nil +} + +func (rw *Db) getTicketFor(ctx context.Context, aggregateName string) (*store.Ticket, error) { + const op = "db.getTicketFor" + if rw.underlying == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s: underlying db missing", aggregateName), errors.WithoutEvent()) + } + ticketer, err := oplog.NewTicketer(ctx, rw.underlying.wrapped, oplog.WithAggregateNames(true)) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("%s: unable to get Ticketer", aggregateName)), errors.WithoutEvent()) + } + ticket, err := ticketer.GetTicket(ctx, aggregateName) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("%s: unable to get ticket", aggregateName)), errors.WithoutEvent()) + } + return ticket, nil +} + +// GetTicket returns an oplog ticket for the aggregate root of "i" which can +// be used to WriteOplogEntryWith for that aggregate root. +func (rw *Db) GetTicket(ctx context.Context, i interface{}) (*store.Ticket, error) { + const op = "db.GetTicket" + if rw.underlying == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing underlying db", errors.WithoutEvent()) + } + if isNil(i) { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing interface", errors.WithoutEvent()) + } + replayable, ok := i.(oplog.ReplayableMessage) + if !ok { + return nil, errors.New(ctx, errors.InvalidParameter, op, "not a replayable message", errors.WithoutEvent()) + } + return rw.getTicketFor(ctx, replayable.TableName()) +} + +func (rw *Db) oplogMsgsForItems(ctx context.Context, opType OpType, opts Options, items []interface{}) ([]*oplog.Message, error) { + const op = "db.oplogMsgsForItems" + if len(items) == 0 { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing items", errors.WithoutEvent()) + } + oplogMsgs := []*oplog.Message{} + var foundType reflect.Type + for i, item := range items { + if i == 0 { + foundType = reflect.TypeOf(item) + } + currentType := reflect.TypeOf(item) + if foundType != currentType { + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("items contains disparate types. item (%d) %s is not a %s", i, currentType, foundType), errors.WithoutEvent()) + } + msg, err := rw.newOplogMessage(ctx, opType, item, WithFieldMaskPaths(opts.WithFieldMaskPaths), WithNullPaths(opts.WithNullPaths)) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithoutEvent()) + } + oplogMsgs = append(oplogMsgs, msg) + } + return oplogMsgs, nil +} + +// addOplogForItems will add a multi-message oplog entry with one msg for each +// item. Items must all be of the same type. Only CreateOp and DeleteOp are +// currently supported operations. +func (rw *Db) addOplogForItems(ctx context.Context, opType OpType, opts Options, ticket *store.Ticket, items []interface{}) error { + const op = "db.addOplogForItems" + oplogArgs := opts.oplogOpts + if ticket == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing ticket", errors.WithoutEvent()) + } + if len(items) == 0 { + return errors.New(ctx, errors.InvalidParameter, op, "missing items", errors.WithoutEvent()) + } + if oplogArgs.metadata == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing metadata", errors.WithoutEvent()) + } + if oplogArgs.wrapper == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing wrapper", errors.WithoutEvent()) + } + + oplogMsgs, err := rw.oplogMsgsForItems(ctx, opType, opts, items) + if err != nil { + return errors.Wrap(ctx, err, op) + } + + replayable, err := validateOplogArgs(ctx, items[0], opts) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("oplog validation failed"), errors.WithoutEvent()) + } + ticketer, err := oplog.NewTicketer(ctx, rw.underlying.wrapped, oplog.WithAggregateNames(true)) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer"), errors.WithoutEvent()) + } + entry, err := oplog.NewEntry( + ctx, + replayable.TableName(), + oplogArgs.metadata, + oplogArgs.wrapper, + ticketer, + ) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create oplog entry"), errors.WithoutEvent()) + } + if err := entry.WriteEntryWith( + ctx, + &oplog.Writer{DB: rw.underlying.wrapped}, + ticket, + oplogMsgs..., + ); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry"), errors.WithoutEvent()) + } + return nil +} + +func (rw *Db) addOplog(ctx context.Context, opType OpType, opts Options, ticket *store.Ticket, i interface{}) error { + const op = "db.addOplog" + oplogArgs := opts.oplogOpts + replayable, err := validateOplogArgs(ctx, i, opts) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + } + if ticket == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing ticket", errors.WithoutEvent()) + } + ticketer, err := oplog.NewTicketer(ctx, rw.underlying.wrapped, oplog.WithAggregateNames(true)) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer"), errors.WithoutEvent()) + } + entry, err := oplog.NewEntry( + ctx, + replayable.TableName(), + oplogArgs.metadata, + oplogArgs.wrapper, + ticketer, + ) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + } + msg, err := rw.newOplogMessage(ctx, opType, i, WithFieldMaskPaths(opts.WithFieldMaskPaths), WithNullPaths(opts.WithNullPaths)) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithoutEvent()) + } + err = entry.WriteEntryWith( + ctx, + &oplog.Writer{DB: rw.underlying.wrapped}, + ticket, + msg, + ) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry"), errors.WithoutEvent()) + } + return nil +} + +// WriteOplogEntryWith will write an oplog entry with the msgs provided for +// the ticket's aggregateName. No options are currently supported. +func (rw *Db) WriteOplogEntryWith(ctx context.Context, wrapper wrapping.Wrapper, ticket *store.Ticket, metadata oplog.Metadata, msgs []*oplog.Message, _ ...Option) error { + const op = "db.WriteOplogEntryWith" + if wrapper == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing wrapper") + } + if ticket == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing ticket") + } + if len(msgs) == 0 { + return errors.New(ctx, errors.InvalidParameter, op, "missing msgs") + } + if rw.underlying == nil { + return errors.New(ctx, errors.InvalidParameter, op, "missing underlying db") + } + if len(metadata) == 0 { + return errors.New(ctx, errors.InvalidParameter, op, "missing metadata") + } + ticketer, err := oplog.NewTicketer(ctx, rw.underlying.wrapped, oplog.WithAggregateNames(true)) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get Ticketer")) + } + + entry, err := oplog.NewEntry( + ctx, + ticket.Name, + metadata, + wrapper, + ticketer, + ) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create oplog entry")) + } + err = entry.WriteEntryWith( + ctx, + &oplog.Writer{DB: rw.underlying.wrapped}, + ticket, + msgs..., + ) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog entry")) + } + return nil +} + +func (rw *Db) newOplogMessage(ctx context.Context, opType OpType, i interface{}, opt ...Option) (*oplog.Message, error) { + const op = "db.newOplogMessage" + opts := GetOpts(opt...) + replayable, ok := i.(oplog.ReplayableMessage) + if !ok { + return nil, errors.New(ctx, errors.InvalidParameter, op, "not a replayable interface", errors.WithoutEvent()) + } + msg := oplog.Message{ + Message: i.(proto.Message), + TypeName: replayable.TableName(), + } + switch opType { + case CreateOp: + msg.OpType = oplog.OpType_OP_TYPE_CREATE + case UpdateOp: + msg.OpType = oplog.OpType_OP_TYPE_UPDATE + msg.FieldMaskPaths = opts.WithFieldMaskPaths + msg.SetToNullPaths = opts.WithNullPaths + case DeleteOp: + msg.OpType = oplog.OpType_OP_TYPE_DELETE + case CreateItemsOp: + msg.OpType = oplog.OpType_OP_TYPE_CREATE_ITEMS + case DeleteItemsOp: + msg.OpType = oplog.OpType_OP_TYPE_DELETE_ITEMS + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("operation type %v is not supported", opType), errors.WithoutEvent()) + } + return &msg, nil +} diff --git a/internal/db/read_writer_test.go b/internal/db/read_writer_test.go index ab8ce6bb7..8dfd36bb6 100644 --- a/internal/db/read_writer_test.go +++ b/internal/db/read_writer_test.go @@ -4,7 +4,6 @@ import ( "context" stderrors "errors" "fmt" - "io" "strconv" "strings" "testing" @@ -25,11 +24,9 @@ import ( ) func TestDb_UpdateUnsetField(t *testing.T) { - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) - rw := &Db{ - underlying: db, - } + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) + rw := New(conn) tu := &db_test.TestUser{ StoreTestUser: &db_test.StoreTestUser{ PublicId: testId(t), @@ -49,8 +46,9 @@ func TestDb_UpdateUnsetField(t *testing.T) { } func TestDb_Update(t *testing.T) { - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + testCtx := context.Background() + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) now := ×tamp.Timestamp{Timestamp: timestamppb.Now()} publicId, err := NewPublicId("testuser") require.NoError(t, err) @@ -131,7 +129,7 @@ func TestDb_Update(t *testing.T) { }, want: 0, wantErr: true, - wantErrMsg: "with version option is zero: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100: dbw.Update: dbw.whereClausesFromOpts: with version option is zero", }, { name: "simple-with-version", @@ -278,7 +276,7 @@ func TestDb_Update(t *testing.T) { }, want: 0, wantErr: true, - wantErrMsg: "db.Update: not allowed on primary key field Id: parameter violation: error #103", + wantErrMsg: "parameter violation: error #103: dbw.Update: not allowed on primary key field Id: invalid field mask", }, { name: "both are missing", @@ -295,7 +293,7 @@ func TestDb_Update(t *testing.T) { }, want: 0, wantErr: true, - wantErrMsg: "db.Update: both fieldMaskPaths and setToNullPaths are missing: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100: dbw.Update: both fieldMaskPaths and setToNullPaths are missing", }, { name: "i is nil", @@ -306,7 +304,7 @@ func TestDb_Update(t *testing.T) { }, want: 0, wantErr: true, - wantErrMsg: "db.Update: missing interface: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100: dbw.Update: missing interface: invalid parameter", }, { name: "only read-only", @@ -323,16 +321,14 @@ func TestDb_Update(t *testing.T) { }, want: 0, wantErr: true, - wantErrMsg: "db.Update: after filtering non-updated fields, there are no fields left in fieldMaskPaths or setToNullPaths: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100: dbw.Update: after filtering non-updated fields, there are no fields left in fieldMaskPaths or setToNullPaths", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: db, - } - u := testUser(t, db, tt.name+id, id, id) + rw := New(conn) + u := testUser(t, conn, tt.name+id, id, id) if tt.args.i != nil { tt.args.i.Id = u.Id @@ -361,7 +357,7 @@ func TestDb_Update(t *testing.T) { } where = fmt.Sprintf("%s and %s is null", where, f) } - err = rw.LookupWhere(context.Background(), foundUser, where, tt.args.i.PublicId) + err = rw.LookupWhere(context.Background(), foundUser, where, []interface{}{tt.args.i.PublicId}) require.NoError(err) assert.Equal(tt.args.i.Id, foundUser.Id) assert.Equal(tt.wantName, foundUser.Name) @@ -375,10 +371,10 @@ func TestDb_Update(t *testing.T) { } t.Run("no-version-field", func(t *testing.T) { assert := assert.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() assert.NoError(err) - car := testCar(t, db, "foo-"+id, id, int32(100)) + car := testCar(t, conn, "foo-"+id, id, int32(100)) car.Name = "friendly-" + id versionOne := uint32(1) @@ -388,10 +384,10 @@ func TestDb_Update(t *testing.T) { }) t.Run("valid-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) - user := testUser(t, db, "foo-"+id, id, id) + user := testUser(t, conn, "foo-"+id, id, id) user.Name = "friendly-" + id rowsUpdated, err := w.Update(context.Background(), user, []string{"Name"}, nil, @@ -406,6 +402,8 @@ func TestDb_Update(t *testing.T) { "op-type": []string{oplog.OpType_OP_TYPE_UPDATE.String()}, }), ) + conn.Debug(false) + require.NoError(err) assert.Equal(1, rowsUpdated) @@ -416,12 +414,12 @@ func TestDb_Update(t *testing.T) { require.NoError(err) assert.Equal(foundUser.Name, user.Name) - err = TestVerifyOplog(t, &w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UPDATE), WithCreateNotBefore(10*time.Second)) + err = TestVerifyOplog(t, w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UPDATE), WithCreateNotBefore(10*time.Second)) require.NoError(err) }) t.Run("both-WithOplog-NewOplogMsg", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -450,9 +448,9 @@ func TestDb_Update(t *testing.T) { }) t.Run("valid-NewOplogMsg", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) - ticket, err := w.GetTicket(&db_test.TestUser{}) + ticket, err := w.GetTicket(testCtx, &db_test.TestUser{}) require.NoError(err) id, err := uuid.GenerateUUID() @@ -488,12 +486,12 @@ func TestDb_Update(t *testing.T) { err = w.WriteOplogEntryWith(context.Background(), TestWrapper(t), ticket, metadata, []*oplog.Message{&createMsg, &updateMsg}) require.NoError(err) - err = TestVerifyOplog(t, &w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) + err = TestVerifyOplog(t, w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) assert.NoError(err) }) t.Run("vet-for-write", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() assert.NoError(err) user := &testUserWithVet{ @@ -502,7 +500,7 @@ func TestDb_Update(t *testing.T) { PhoneNumber: id, Email: id, } - err = db.Create(user).Error + err = w.Create(context.Background(), user) require.NoError(err) user.Name = "friendly-" + id @@ -528,7 +526,7 @@ func TestDb_Update(t *testing.T) { id, err := uuid.GenerateUUID() assert.NoError(err) - user := testUser(t, db, "foo-"+id, id, id) + user := testUser(t, conn, "foo-"+id, id, id) rowsUpdated, err := w.Update(context.Background(), user, []string{"Name"}, nil) assert.Error(err) assert.Equal(0, rowsUpdated) @@ -536,10 +534,10 @@ func TestDb_Update(t *testing.T) { }) t.Run("no-wrapper-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) - user := testUser(t, db, "foo-"+id, id, id) + user := testUser(t, conn, "foo-"+id, id, id) user.Name = "friendly-" + id rowsUpdated, err := w.Update(context.Background(), user, []string{"Name"}, @@ -554,14 +552,14 @@ func TestDb_Update(t *testing.T) { ) require.Error(err) assert.Equal(0, rowsUpdated) - assert.Contains(err.Error(), "db.Update: oplog validation failed: db.validateOplogArgs: missing wrapper: parameter violation: error #100") + assert.Contains(err.Error(), "oplog validation failed: db.validateOplogArgs: missing wrapper: parameter violation: error #100") }) t.Run("no-metadata-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) - user := testUser(t, db, "foo-"+id, id, id) + user := testUser(t, conn, "foo-"+id, id, id) user.Name = "friendly-" + id rowsUpdated, err := w.Update(context.Background(), user, []string{"Name"}, nil, WithOplog( @@ -571,14 +569,14 @@ func TestDb_Update(t *testing.T) { ) require.Error(err) assert.Equal(0, rowsUpdated) - assert.Contains(err.Error(), "db.Update: oplog validation failed: db.validateOplogArgs: missing metadata: parameter violation: error #100") + assert.Contains(err.Error(), "oplog validation failed: db.validateOplogArgs: missing metadata: parameter violation: error #100") }) t.Run("multi-column", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} - scooter := testScooter(t, db, "", 0) - accessory := testAccessory(t, db, "test accessory") - scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId) + w := New(conn) + scooter := testScooter(t, conn, "", 0) + accessory := testAccessory(t, conn, "test accessory") + scooterAccessory := testScooterAccessory(t, conn, scooter.Id, accessory.AccessoryId) scooterAccessory.Review = "this is great" rowsUpdated, err := w.Update(context.Background(), scooterAccessory, []string{"Review"}, nil) require.NoError(err) @@ -627,11 +625,11 @@ func (u *testUserWithVet) VetForWrite(ctx context.Context, r Reader, opType OpTy func TestDb_Create(t *testing.T) { // intentionally not run with t.Parallel so we don't need to use DoTx for the Create tests - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -656,7 +654,7 @@ func TestDb_Create(t *testing.T) { }) t.Run("valid-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -686,7 +684,7 @@ func TestDb_Create(t *testing.T) { }) t.Run("both-Oplog-NewOplogMsg", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -703,10 +701,11 @@ func TestDb_Create(t *testing.T) { assert.True(errors.Match(errors.T(errors.InvalidParameter), err)) }) t.Run("valid-NewOplogMsg", func(t *testing.T) { + testCtx := context.Background() assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) - ticket, err := w.GetTicket(&db_test.TestUser{}) + ticket, err := w.GetTicket(testCtx, &db_test.TestUser{}) require.NoError(err) id, err := uuid.GenerateUUID() @@ -742,12 +741,12 @@ func TestDb_Create(t *testing.T) { err = w.WriteOplogEntryWith(context.Background(), TestWrapper(t), ticket, metadata, []*oplog.Message{&createMsg, &updateMsg}) require.NoError(err) - err = TestVerifyOplog(t, &w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) + err = TestVerifyOplog(t, w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) require.NoError(err) }) t.Run("no-wrapper-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -766,11 +765,11 @@ func TestDb_Create(t *testing.T) { ), ) require.Error(err) - assert.Contains(err.Error(), "db.Create: oplog validation failed: db.validateOplogArgs: missing wrapper: parameter violation: error #100") + assert.Contains(err.Error(), "oplog validation failed: db.validateOplogArgs: missing wrapper: parameter violation: error #100") }) t.Run("no-metadata-WithOplog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -785,7 +784,7 @@ func TestDb_Create(t *testing.T) { ), ) require.Error(err) - assert.Contains(err.Error(), "db.Create: oplog validation failed: db.validateOplogArgs: missing metadata: parameter violation: error #100") + assert.Contains(err.Error(), "oplog validation failed: db.validateOplogArgs: missing metadata: parameter violation: error #100") }) t.Run("nil-tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) @@ -803,11 +802,11 @@ func TestDb_Create(t *testing.T) { func TestDb_LookupByPublicId(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -835,17 +834,17 @@ func TestDb_LookupByPublicId(t *testing.T) { }) t.Run("no-public-id-set", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) foundUser, err := db_test.NewTestUser() foundUser.PublicId = "" require.NoError(err) err = w.LookupByPublicId(context.Background(), foundUser) require.Error(err) - assert.Contains(err.Error(), "db.LookupById: db.primaryKeysWhere: missing primary key: parameter violation: error #100") + assert.Contains(err.Error(), "missing primary key: invalid parameter") }) t.Run("not-found", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) foundUser, err := db_test.NewTestUser() @@ -859,11 +858,11 @@ func TestDb_LookupByPublicId(t *testing.T) { func TestDb_LookupWhere(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("simple", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -874,7 +873,7 @@ func TestDb_LookupWhere(t *testing.T) { assert.NotEmpty(user.PublicId) var foundUser db_test.TestUser - err = w.LookupWhere(context.Background(), &foundUser, "public_id = ?", user.PublicId) + err = w.LookupWhere(context.Background(), &foundUser, "public_id = ?", []interface{}{user.PublicId}) require.NoError(err) assert.Equal(foundUser.Id, user.Id) }) @@ -882,38 +881,38 @@ func TestDb_LookupWhere(t *testing.T) { assert, require := assert.New(t), require.New(t) w := Db{} var foundUser db_test.TestUser - err := w.LookupWhere(context.Background(), &foundUser, "public_id = ?", 1) + err := w.LookupWhere(context.Background(), &foundUser, "public_id = ?", []interface{}{1}) require.Error(err) assert.Equal("db.LookupWhere: missing underlying db: parameter violation: error #100", err.Error()) }) t.Run("not-found", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) var foundUser db_test.TestUser - err = w.LookupWhere(context.Background(), &foundUser, "public_id = ?", id) + err = w.LookupWhere(context.Background(), &foundUser, "public_id = ?", []interface{}{id}) require.Error(err) assert.True(errors.Match(errors.T(errors.RecordNotFound), err)) }) t.Run("bad-where", func(t *testing.T) { require := require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) var foundUser db_test.TestUser - err = w.LookupWhere(context.Background(), &foundUser, "? = ?", id) + err = w.LookupWhere(context.Background(), &foundUser, "? = ?", []interface{}{id}) require.Error(err) }) } func TestDb_SearchWhere(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) - knownUser := testUser(t, db, "zedUser", "", "") + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) + knownUser := testUser(t, conn, "zedUser", "", "") type args struct { where string @@ -922,7 +921,7 @@ func TestDb_SearchWhere(t *testing.T) { } tests := []struct { name string - db Db + db *Db createCnt int args args wantCnt int @@ -931,7 +930,7 @@ func TestDb_SearchWhere(t *testing.T) { }{ { name: "no-limit", - db: Db{underlying: db}, + db: New(conn), createCnt: 10, args: args{ where: "1=1", @@ -943,7 +942,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "no-where", - db: Db{underlying: db}, + db: New(conn), createCnt: 10, args: args{ opt: []Option{WithLimit(10)}, @@ -953,7 +952,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "custom-limit", - db: Db{underlying: db}, + db: New(conn), createCnt: 10, args: args{ where: "1=1", @@ -964,7 +963,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "simple", - db: Db{underlying: db}, + db: New(conn), createCnt: 1, args: args{ where: "public_id = ?", @@ -976,7 +975,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "no args", - db: Db{underlying: db}, + db: New(conn), createCnt: 1, args: args{ where: fmt.Sprintf("public_id = '%v'", knownUser.PublicId), @@ -987,7 +986,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "no where, but with args", - db: Db{underlying: db}, + db: New(conn), createCnt: 1, args: args{ arg: []interface{}{knownUser.PublicId}, @@ -997,7 +996,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "not-found", - db: Db{underlying: db}, + db: New(conn), createCnt: 1, args: args{ where: "public_id = ?", @@ -1009,7 +1008,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "bad-where", - db: Db{underlying: db}, + db: New(conn), createCnt: 1, args: args{ where: "bad_column_name = ?", @@ -1021,7 +1020,7 @@ func TestDb_SearchWhere(t *testing.T) { }, { name: "nil-underlying", - db: Db{}, + db: New(nil), createCnt: 1, args: args{ where: "public_id = ?", @@ -1037,7 +1036,7 @@ func TestDb_SearchWhere(t *testing.T) { assert, require := assert.New(t), require.New(t) testUsers := []*db_test.TestUser{} for i := 0; i < tt.createCnt; i++ { - testUsers = append(testUsers, testUser(t, db, tt.name+strconv.Itoa(i), "", "")) + testUsers = append(testUsers, testUser(t, conn, tt.name+strconv.Itoa(i), "", "")) } assert.Equal(tt.createCnt, len(testUsers)) @@ -1064,10 +1063,10 @@ func TestDb_SearchWhere(t *testing.T) { func TestDb_Exec(t *testing.T) { t.Parallel() t.Run("update", func(t *testing.T) { - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) require := require.New(t) - w := Db{underlying: db} + w := New(conn) id := testId(t) user, err := db_test.NewTestUser() require.NoError(err) @@ -1084,11 +1083,11 @@ func TestDb_Exec(t *testing.T) { func TestDb_DoTx(t *testing.T) { t.Parallel() ctx := context.TODO() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("valid-with-10-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 10, ExpBackoff{}, func(Reader, Writer) error { @@ -1104,7 +1103,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("valid-with-1-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 1, ExpBackoff{}, func(Reader, Writer) error { @@ -1120,7 +1119,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("valid-with-2-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 3, ExpBackoff{}, func(Reader, Writer) error { @@ -1136,7 +1135,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("valid-with-4-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 4, ExpBackoff{}, func(Reader, Writer) error { @@ -1152,7 +1151,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("zero-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 0, ExpBackoff{}, func(Reader, Writer) error { attempts += 1; return nil }) require.NoError(err) @@ -1161,7 +1160,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("nil-tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{nil} + w := Db{} attempts := 0 got, err := w.DoTx(context.Background(), 1, ExpBackoff{}, func(Reader, Writer) error { attempts += 1; return nil }) require.Error(err) @@ -1170,7 +1169,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("not-a-retry-err", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) got, err := w.DoTx(context.Background(), 1, ExpBackoff{}, func(Reader, Writer) error { return stderrors.New("not a retry error") }) require.Error(err) assert.Equal(RetryInfo{}, got) @@ -1178,7 +1177,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("too-many-retries", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := &Db{underlying: db} + w := New(conn) attempts := 0 got, err := w.DoTx(context.Background(), 2, ExpBackoff{}, func(Reader, Writer) error { attempts += 1 @@ -1190,7 +1189,7 @@ func TestDb_DoTx(t *testing.T) { }) t.Run("updating-good-bad-good", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := Db{underlying: db} + rw := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -1257,12 +1256,10 @@ func TestDb_DoTx(t *testing.T) { } func TestDb_Delete(t *testing.T) { - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) newUser := func() *db_test.TestUser { - w := &Db{ - underlying: db, - } + w := New(conn) u, err := db_test.NewTestUser() require.NoError(t, err) err = w.Create(context.Background(), u) @@ -1307,7 +1304,7 @@ func TestDb_Delete(t *testing.T) { }{ { name: "simple-no-oplog", - underlying: db, + underlying: conn, wrapper: TestWrapper(t), args: args{ i: newUser(), @@ -1317,7 +1314,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "with-where-no-delete", - underlying: db, + underlying: conn, wrapper: TestWrapper(t), args: args{ i: newUser(), @@ -1329,7 +1326,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "with-where-and-delete", - underlying: db, + underlying: conn, wrapper: TestWrapper(t), args: args{ i: newUser(), @@ -1340,7 +1337,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "valid-with-oplog", - underlying: db, + underlying: conn, wrapper: TestWrapper(t), args: args{ i: newUser(), @@ -1352,7 +1349,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "nil-wrapper", - underlying: db, + underlying: conn, wrapper: nil, args: args{ i: newUser(), @@ -1365,7 +1362,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "nil-metadata", - underlying: db, + underlying: conn, wrapper: nil, args: args{ i: newUser(), @@ -1389,7 +1386,7 @@ func TestDb_Delete(t *testing.T) { }, { name: "not-found", - underlying: db, + underlying: conn, wrapper: TestWrapper(t), args: args{ i: notFoundUser(), @@ -1402,9 +1399,7 @@ func TestDb_Delete(t *testing.T) { t.Run(tt.name, func(t *testing.T) { require := require.New(t) assert := assert.New(t) - rw := &Db{ - underlying: tt.underlying, - } + rw := New(tt.underlying) if tt.wantOplog { metadata := tt.args.metadata(tt.args.i.PublicId) opLog := WithOplog(tt.wrapper, metadata) @@ -1443,7 +1438,7 @@ func TestDb_Delete(t *testing.T) { }) t.Run("both-WithOplog-NewOplogMsg", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) id, err := uuid.GenerateUUID() require.NoError(err) user, err := db_test.NewTestUser() @@ -1464,10 +1459,11 @@ func TestDb_Delete(t *testing.T) { assert.True(errors.Match(errors.T(errors.InvalidParameter), err)) }) t.Run("valid-NewOplogMsg", func(t *testing.T) { + testCtx := context.Background() assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) - ticket, err := w.GetTicket(&db_test.TestUser{}) + ticket, err := w.GetTicket(testCtx, &db_test.TestUser{}) require.NoError(err) id, err := uuid.GenerateUUID() @@ -1501,15 +1497,15 @@ func TestDb_Delete(t *testing.T) { err = w.WriteOplogEntryWith(context.Background(), TestWrapper(t), ticket, metadata, []*oplog.Message{&createMsg, &deleteMsg}) require.NoError(err) - err = TestVerifyOplog(t, &w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) + err = TestVerifyOplog(t, w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second)) require.NoError(err) }) t.Run("multi-column", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} - scooter := testScooter(t, db, "", 0) - accessory := testAccessory(t, db, "test accessory") - scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId) + w := New(conn) + scooter := testScooter(t, conn, "", 0) + accessory := testAccessory(t, conn, "test accessory") + scooterAccessory := testScooterAccessory(t, conn, scooter.Id, accessory.AccessoryId) rowsDeleted, err := w.Delete(context.Background(), scooterAccessory) require.NoError(err) assert.Equal(1, rowsDeleted) @@ -1519,11 +1515,11 @@ func TestDb_Delete(t *testing.T) { func TestDb_ScanRows(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := Db{underlying: db} + w := New(conn) user, err := db_test.NewTestUser() require.NoError(err) err = w.Create(context.Background(), user) @@ -1538,7 +1534,7 @@ func TestDb_ScanRows(t *testing.T) { require.NoError(err) // scan the row into your Gorm struct - err = w.ScanRows(rows, &u) + err = w.ScanRows(context.Background(), rows, &u) require.NoError(err) assert.Equal(user.PublicId, u.PublicId) } @@ -1547,11 +1543,11 @@ func TestDb_ScanRows(t *testing.T) { func TestDb_Query(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := Db{underlying: db} + rw := New(conn) user, err := db_test.NewTestUser() user.Name = "alice" require.NoError(err) @@ -1568,7 +1564,7 @@ func TestDb_Query(t *testing.T) { u, err := db_test.NewTestUser() require.NoError(err) // scan the row into your Gorm struct - err = rw.ScanRows(rows, &u) + err = rw.ScanRows(context.Background(), rows, &u) require.NoError(err) assert.Equal(user.PublicId, u.PublicId) } @@ -1755,9 +1751,7 @@ func TestDb_CreateItems(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } + rw := New(tt.underlying) err := rw.CreateItems(context.Background(), tt.args.createItems, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -1951,9 +1945,7 @@ func TestDb_DeleteItems(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } + rw := New(tt.underlying) rowsDeleted, err := rw.DeleteItems(context.Background(), tt.args.deleteItems, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -1998,7 +1990,8 @@ func testUser(t *testing.T, conn *DB, name, email, phoneNumber string) *db_test. }, } if conn != nil { - err = conn.Create(u).Error + rw := New(conn) + err := rw.Create(context.Background(), u) require.NoError(err) } return u @@ -2019,7 +2012,8 @@ func testCar(t *testing.T, conn *DB, name, model string, mpg int32) *db_test.Tes }, } if conn != nil { - err = conn.Create(c).Error + rw := New(conn) + err := rw.Create(context.Background(), c) require.NoError(err) } return c @@ -2047,7 +2041,8 @@ func testScooter(t *testing.T, conn *DB, model string, mpg int32) *db_test.TestS }, } if conn != nil { - err = conn.Create(u).Error + rw := New(conn) + err := rw.Create(context.Background(), u) require.NoError(err) } return u @@ -2059,7 +2054,8 @@ func testAccessory(t *testing.T, conn *DB, description string) *db_test.TestAcce a, err := db_test.NewTestAccessory(description) require.NoError(err) if conn != nil { - err = conn.Create(a).Error + rw := New(conn) + rw.Create(context.Background(), a) require.NoError(err) } return a @@ -2071,7 +2067,8 @@ func testScooterAccessory(t *testing.T, conn *DB, scooterId, accessoryId uint32) a, err := db_test.NewTestScooterAccessory(scooterId, accessoryId) require.NoError(err) if conn != nil { - err = conn.Create(a).Error + rw := New(conn) + rw.Create(context.Background(), a) require.NoError(err) } return a @@ -2079,12 +2076,12 @@ func testScooterAccessory(t *testing.T, conn *DB, scooterId, accessoryId uint32) func TestDb_LookupById(t *testing.T) { t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) - scooter := testScooter(t, db, "", 0) - user := testUser(t, db, "", "", "") - accessory := testAccessory(t, db, "test accessory") - scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId) + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) + scooter := testScooter(t, conn, "", 0) + user := testUser(t, conn, "", "", "") + accessory := testAccessory(t, conn, "test accessory") + scooterAccessory := testScooterAccessory(t, conn, scooter.Id, accessory.AccessoryId) type args struct { resource interface{} @@ -2100,7 +2097,7 @@ func TestDb_LookupById(t *testing.T) { }{ { name: "simple-private-id", - underlying: db, + underlying: conn, args: args{ resource: scooter, }, @@ -2109,7 +2106,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "simple-public-id", - underlying: db, + underlying: conn, args: args{ resource: user, }, @@ -2118,7 +2115,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "simple-non-public-non-private-id", - underlying: db, + underlying: conn, args: args{ resource: accessory, }, @@ -2127,7 +2124,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "compond", - underlying: db, + underlying: conn, args: args{ resource: scooterAccessory, }, @@ -2136,7 +2133,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "compond-with-zero-value-pk", - underlying: db, + underlying: conn, args: args{ resource: func() interface{} { cp := scooterAccessory.Clone() @@ -2149,7 +2146,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "missing-public-id", - underlying: db, + underlying: conn, args: args{ resource: &db_test.TestUser{ StoreTestUser: &db_test.StoreTestUser{}, @@ -2160,7 +2157,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "missing-private-id", - underlying: db, + underlying: conn, args: args{ resource: &db_test.TestScooter{ StoreTestScooter: &db_test.StoreTestScooter{}, @@ -2171,7 +2168,7 @@ func TestDb_LookupById(t *testing.T) { }, { name: "not-an-ider", - underlying: db, + underlying: conn, args: args{ resource: &db_test.NotIder{}, }, @@ -2191,9 +2188,7 @@ func TestDb_LookupById(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } + rw := New(tt.underlying) cloner, ok := tt.args.resource.(db_test.Cloner) require.True(ok) cp := cloner.Clone() @@ -2208,10 +2203,8 @@ func TestDb_LookupById(t *testing.T) { }) } t.Run("not-ptr", func(t *testing.T) { - u := testUser(t, db, "", "", "") - rw := &Db{ - underlying: db, - } + u := testUser(t, conn, "", "", "") + rw := New(conn) err := rw.LookupById(context.Background(), *u) require.Error(t, err) assert.True(t, errors.Match(errors.T(errors.InvalidParameter), err)) @@ -2219,6 +2212,7 @@ func TestDb_LookupById(t *testing.T) { } func TestDb_GetTicket(t *testing.T) { + testCtx := context.Background() db, _ := TestSetup(t, "postgres") TestCreateTables(t, db) type notReplayable struct{} @@ -2260,10 +2254,8 @@ func TestDb_GetTicket(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } - got, err := rw.GetTicket(tt.aggregateType) + rw := New(tt.underlying) + got, err := rw.GetTicket(testCtx, tt.aggregateType) if tt.wantErr { require.Error(err) assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error type: %s", err.Error()) @@ -2279,11 +2271,12 @@ func TestDb_GetTicket(t *testing.T) { } func TestDb_WriteOplogEntryWith(t *testing.T) { - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) - w := Db{underlying: db} + conn, _ := TestSetup(t, "postgres") + TestCreateTables(t, conn) + w := New(conn) + testCtx := context.Background() - ticket, err := w.GetTicket(&db_test.TestUser{}) + ticket, err := w.GetTicket(testCtx, &db_test.TestUser{}) require.NoError(t, err) id, err := uuid.GenerateUUID() @@ -2319,7 +2312,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }{ { name: "valid", - underlying: db, + underlying: conn, args: args{ wrapper: TestWrapper(t), ticket: ticket, @@ -2330,7 +2323,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }, { name: "valid-multiple", - underlying: db, + underlying: conn, args: args{ wrapper: TestWrapper(t), ticket: ticket, @@ -2341,7 +2334,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }, { name: "missing-ticket", - underlying: db, + underlying: conn, args: args{ wrapper: TestWrapper(t), ticket: nil, @@ -2365,7 +2358,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }, { name: "missing-wrapper", - underlying: db, + underlying: conn, args: args{ wrapper: nil, ticket: ticket, @@ -2377,7 +2370,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }, { name: "nil-metadata", - underlying: db, + underlying: conn, args: args{ wrapper: TestWrapper(t), ticket: ticket, @@ -2389,7 +2382,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { }, { name: "empty-metadata", - underlying: db, + underlying: conn, args: args{ wrapper: TestWrapper(t), ticket: ticket, @@ -2403,9 +2396,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } + rw := New(tt.underlying) err := rw.WriteOplogEntryWith(context.Background(), tt.args.wrapper, tt.args.ticket, tt.args.metadata, tt.args.msgs, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -2420,492 +2411,492 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { } } -func TestClear_InputTypes(t *testing.T) { - type Z struct { - F string - } +// func TestClear_InputTypes(t *testing.T) { +// type Z struct { +// F string +// } - var nilZ *Z - s := "test-string" +// var nilZ *Z +// s := "test-string" - type args struct { - v interface{} - f []string - d int - } +// type args struct { +// v interface{} +// f []string +// d int +// } - tests := []struct { - name string - args args - want interface{} - err errors.Code - }{ - { - name: "nil", - args: args{ - v: nil, - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "string", - args: args{ - v: "blank", - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "pointer-to-nil-struct", - args: args{ - v: nilZ, - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "pointer-to-string", - args: args{ - v: &s, - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "not-pointer", - args: args{ - v: Z{ - F: "foo", - }, - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "map", - args: args{ - v: map[string]int{ - "A": 31, - "B": 34, - }, - f: []string{"field"}, - d: 1, - }, - err: errors.InvalidParameter, - }, - { - name: "pointer-to-struct", - args: args{ - v: &Z{ - F: "foo", - }, - f: []string{"field"}, - d: 1, - }, - want: &Z{ - F: "foo", - }, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - input := tt.args.v - err := Clear(input, tt.args.f, tt.args.d) - if tt.err != 0 { - assert.True(errors.Match(errors.T(tt.err), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, input) - }) - } -} +// tests := []struct { +// name string +// args args +// want interface{} +// err errors.Code +// }{ +// { +// name: "nil", +// args: args{ +// v: nil, +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "string", +// args: args{ +// v: "blank", +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "pointer-to-nil-struct", +// args: args{ +// v: nilZ, +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "pointer-to-string", +// args: args{ +// v: &s, +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "not-pointer", +// args: args{ +// v: Z{ +// F: "foo", +// }, +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "map", +// args: args{ +// v: map[string]int{ +// "A": 31, +// "B": 34, +// }, +// f: []string{"field"}, +// d: 1, +// }, +// err: errors.InvalidParameter, +// }, +// { +// name: "pointer-to-struct", +// args: args{ +// v: &Z{ +// F: "foo", +// }, +// f: []string{"field"}, +// d: 1, +// }, +// want: &Z{ +// F: "foo", +// }, +// }, +// } +// for _, tt := range tests { +// tt := tt +// t.Run(tt.name, func(t *testing.T) { +// assert, require := assert.New(t), require.New(t) +// input := tt.args.v +// err := Clear(input, tt.args.f, tt.args.d) +// if tt.err != 0 { +// assert.True(errors.Match(errors.T(tt.err), err)) +// return +// } +// require.NoError(err) +// assert.Equal(tt.want, input) +// }) +// } +// } -func TestClear_Structs(t *testing.T) { - s := "test-string" +// func TestClear_Structs(t *testing.T) { +// s := "test-string" - type A struct{ F string } - type B struct{ F *string } +// type A struct{ F string } +// type B struct{ F *string } - type AB struct { - A A - B *B - F string +// type AB struct { +// A A +// B *B +// F string - IN io.Reader - MP map[int]int - SL []string - AR [1]int - CH chan int - FN func() - } +// IN io.Reader +// MP map[int]int +// SL []string +// AR [1]int +// CH chan int +// FN func() +// } - type AFB struct { - F A - B *B - } +// type AFB struct { +// F A +// B *B +// } - type ABF struct { - A A - F *B - } +// type ABF struct { +// A A +// F *B +// } - type C struct { - F string - NF string - } +// type C struct { +// F string +// NF string +// } - type EA struct { - A - M string - NF string - } +// type EA struct { +// A +// M string +// NF string +// } - type EAP struct { - *A - M string - NF string - } +// type EAP struct { +// *A +// M string +// NF string +// } - type DEA struct { - EA - F string - } +// type DEA struct { +// EA +// F string +// } - type DEAP struct { - *EAP - F string - } +// type DEAP struct { +// *EAP +// F string +// } - type args struct { - v interface{} - f []string - d int - } - tests := []struct { - name string - args args - want interface{} - }{ - { - name: "blank-A", - args: args{ - v: &A{}, - f: []string{"F"}, - d: 1, - }, - want: &A{}, - }, - { - name: "clear-A", - args: args{ - v: &A{"clear"}, - f: []string{"F"}, - d: 1, - }, - want: &A{}, - }, - { - name: "clear-B", - args: args{ - v: &B{&s}, - f: []string{"F"}, - d: 1, - }, - want: &B{}, - }, - { - name: "clear-C", - args: args{ - v: &C{"clear", "notclear"}, - f: []string{"F"}, - d: 1, - }, - want: &C{"", "notclear"}, - }, - { - name: "shallow-clear-AB", - args: args{ - v: &AB{ - A: A{"notclear"}, - B: &B{&s}, - F: "clear", - }, - f: []string{"F"}, - d: 1, - }, - want: &AB{ - A: A{"notclear"}, - B: &B{&s}, - F: "", - }, - }, - { - name: "deep-clear-AB", - args: args{ - v: &AB{ - A: A{"clear"}, - B: &B{&s}, - F: "clear", - }, - f: []string{"F"}, - d: 2, - }, - want: &AB{ - A: A{""}, - B: &B{}, - F: "", - }, - }, - { - name: "clear-AFB", - args: args{ - v: &AFB{ - F: A{"clear"}, - B: &B{&s}, - }, - f: []string{"F"}, - d: 2, - }, - want: &AFB{ - F: A{""}, - B: &B{}, - }, - }, - { - name: "clear-ABF", - args: args{ - v: &ABF{ - A: A{"clear"}, - F: &B{&s}, - }, - f: []string{"F"}, - d: 2, - }, - want: &ABF{ - A: A{""}, - F: nil, - }, - }, - { - name: "embedded-struct", - args: args{ - v: &EA{ - A: A{"clear"}, - M: "clear", - NF: "notclear", - }, - f: []string{"F", "M"}, - d: 2, - }, - want: &EA{ - A: A{""}, - M: "", - NF: "notclear", - }, - }, - { - name: "embedded-struct-pointer", - args: args{ - v: &EAP{ - A: &A{"clear"}, - M: "clear", - NF: "notclear", - }, - f: []string{"F", "M"}, - d: 2, - }, - want: &EAP{ - A: &A{""}, - M: "", - NF: "notclear", - }, - }, - { - name: "embedded-struct-pointer-extra-depth", - args: args{ - v: &EAP{ - A: &A{"clear"}, - M: "clear", - NF: "notclear", - }, - f: []string{"F", "M"}, - d: 12, - }, - want: &EAP{ - A: &A{""}, - M: "", - NF: "notclear", - }, - }, - { - name: "deep-embedded-struct", - args: args{ - v: &DEA{ - EA: EA{ - A: A{"clear"}, - M: "clear", - NF: "notclear", - }, - F: "clear", - }, - f: []string{"F", "M"}, - d: 3, - }, - want: &DEA{ - EA: EA{ - A: A{""}, - M: "", - NF: "notclear", - }, - F: "", - }, - }, - { - name: "deep-embedded-struct-pointer", - args: args{ - v: &DEAP{ - EAP: &EAP{ - A: &A{"clear"}, - M: "clear", - NF: "notclear", - }, - F: "clear", - }, - f: []string{"F", "M"}, - d: 3, - }, - want: &DEAP{ - EAP: &EAP{ - A: &A{""}, - M: "", - NF: "notclear", - }, - F: "", - }, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - input := tt.args.v - err := Clear(input, tt.args.f, tt.args.d) - assert.NotEmpty(s) - require.NoError(err) - assert.Equal(tt.want, input) - }) - } -} +// type args struct { +// v interface{} +// f []string +// d int +// } +// tests := []struct { +// name string +// args args +// want interface{} +// }{ +// { +// name: "blank-A", +// args: args{ +// v: &A{}, +// f: []string{"F"}, +// d: 1, +// }, +// want: &A{}, +// }, +// { +// name: "clear-A", +// args: args{ +// v: &A{"clear"}, +// f: []string{"F"}, +// d: 1, +// }, +// want: &A{}, +// }, +// { +// name: "clear-B", +// args: args{ +// v: &B{&s}, +// f: []string{"F"}, +// d: 1, +// }, +// want: &B{}, +// }, +// { +// name: "clear-C", +// args: args{ +// v: &C{"clear", "notclear"}, +// f: []string{"F"}, +// d: 1, +// }, +// want: &C{"", "notclear"}, +// }, +// { +// name: "shallow-clear-AB", +// args: args{ +// v: &AB{ +// A: A{"notclear"}, +// B: &B{&s}, +// F: "clear", +// }, +// f: []string{"F"}, +// d: 1, +// }, +// want: &AB{ +// A: A{"notclear"}, +// B: &B{&s}, +// F: "", +// }, +// }, +// { +// name: "deep-clear-AB", +// args: args{ +// v: &AB{ +// A: A{"clear"}, +// B: &B{&s}, +// F: "clear", +// }, +// f: []string{"F"}, +// d: 2, +// }, +// want: &AB{ +// A: A{""}, +// B: &B{}, +// F: "", +// }, +// }, +// { +// name: "clear-AFB", +// args: args{ +// v: &AFB{ +// F: A{"clear"}, +// B: &B{&s}, +// }, +// f: []string{"F"}, +// d: 2, +// }, +// want: &AFB{ +// F: A{""}, +// B: &B{}, +// }, +// }, +// { +// name: "clear-ABF", +// args: args{ +// v: &ABF{ +// A: A{"clear"}, +// F: &B{&s}, +// }, +// f: []string{"F"}, +// d: 2, +// }, +// want: &ABF{ +// A: A{""}, +// F: nil, +// }, +// }, +// { +// name: "embedded-struct", +// args: args{ +// v: &EA{ +// A: A{"clear"}, +// M: "clear", +// NF: "notclear", +// }, +// f: []string{"F", "M"}, +// d: 2, +// }, +// want: &EA{ +// A: A{""}, +// M: "", +// NF: "notclear", +// }, +// }, +// { +// name: "embedded-struct-pointer", +// args: args{ +// v: &EAP{ +// A: &A{"clear"}, +// M: "clear", +// NF: "notclear", +// }, +// f: []string{"F", "M"}, +// d: 2, +// }, +// want: &EAP{ +// A: &A{""}, +// M: "", +// NF: "notclear", +// }, +// }, +// { +// name: "embedded-struct-pointer-extra-depth", +// args: args{ +// v: &EAP{ +// A: &A{"clear"}, +// M: "clear", +// NF: "notclear", +// }, +// f: []string{"F", "M"}, +// d: 12, +// }, +// want: &EAP{ +// A: &A{""}, +// M: "", +// NF: "notclear", +// }, +// }, +// { +// name: "deep-embedded-struct", +// args: args{ +// v: &DEA{ +// EA: EA{ +// A: A{"clear"}, +// M: "clear", +// NF: "notclear", +// }, +// F: "clear", +// }, +// f: []string{"F", "M"}, +// d: 3, +// }, +// want: &DEA{ +// EA: EA{ +// A: A{""}, +// M: "", +// NF: "notclear", +// }, +// F: "", +// }, +// }, +// { +// name: "deep-embedded-struct-pointer", +// args: args{ +// v: &DEAP{ +// EAP: &EAP{ +// A: &A{"clear"}, +// M: "clear", +// NF: "notclear", +// }, +// F: "clear", +// }, +// f: []string{"F", "M"}, +// d: 3, +// }, +// want: &DEAP{ +// EAP: &EAP{ +// A: &A{""}, +// M: "", +// NF: "notclear", +// }, +// F: "", +// }, +// }, +// } +// for _, tt := range tests { +// tt := tt +// t.Run(tt.name, func(t *testing.T) { +// assert, require := assert.New(t), require.New(t) +// input := tt.args.v +// err := Clear(input, tt.args.f, tt.args.d) +// assert.NotEmpty(s) +// require.NoError(err) +// assert.Equal(tt.want, input) +// }) +// } +// } -func TestClear_SetFieldsToNil(t *testing.T) { - type P struct{ F *string } - type A struct{ F string } +// func TestClear_SetFieldsToNil(t *testing.T) { +// type P struct{ F *string } +// type A struct{ F string } - type EA struct { - A - M string - NF string - } +// type EA struct { +// A +// M string +// NF string +// } - type EAP struct { - *A - M string - NF string - } +// type EAP struct { +// *A +// M string +// NF string +// } - type DEA struct { - EA - F string - } +// type DEA struct { +// EA +// F string +// } - type DEAP struct { - *EAP - F string - } +// type DEAP struct { +// *EAP +// F string +// } - type args struct { - v interface{} - f []string - } - tests := []struct { - name string - args args - want interface{} - }{ - { - name: "dont-panic", - args: args{ - v: P{}, - f: []string{"F"}, - }, - want: P{}, - }, - { - name: "deep-embedded-struct", - args: args{ - v: &DEA{ - EA: EA{ - A: A{"notclear"}, - M: "clear", - NF: "notclear", - }, - F: "clear", - }, - f: []string{"F", "M"}, - }, - want: &DEA{ - EA: EA{ - A: A{"notclear"}, - M: "", - NF: "notclear", - }, - F: "", - }, - }, - { - name: "deep-embedded-struct-pointer", - args: args{ - v: &DEAP{ - EAP: &EAP{ - A: &A{"notclear"}, - M: "clear", - NF: "notclear", - }, - F: "clear", - }, - f: []string{"F", "M"}, - }, - want: &DEAP{ - EAP: &EAP{ - A: &A{"notclear"}, - M: "", - NF: "notclear", - }, - F: "", - }, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - input := tt.args.v - require.NotPanics(func() { - setFieldsToNil(input, tt.args.f) - }) - assert.Equal(tt.want, input) - }) - } -} +// type args struct { +// v interface{} +// f []string +// } +// tests := []struct { +// name string +// args args +// want interface{} +// }{ +// { +// name: "dont-panic", +// args: args{ +// v: P{}, +// f: []string{"F"}, +// }, +// want: P{}, +// }, +// { +// name: "deep-embedded-struct", +// args: args{ +// v: &DEA{ +// EA: EA{ +// A: A{"notclear"}, +// M: "clear", +// NF: "notclear", +// }, +// F: "clear", +// }, +// f: []string{"F", "M"}, +// }, +// want: &DEA{ +// EA: EA{ +// A: A{"notclear"}, +// M: "", +// NF: "notclear", +// }, +// F: "", +// }, +// }, +// { +// name: "deep-embedded-struct-pointer", +// args: args{ +// v: &DEAP{ +// EAP: &EAP{ +// A: &A{"notclear"}, +// M: "clear", +// NF: "notclear", +// }, +// F: "clear", +// }, +// f: []string{"F", "M"}, +// }, +// want: &DEAP{ +// EAP: &EAP{ +// A: &A{"notclear"}, +// M: "", +// NF: "notclear", +// }, +// F: "", +// }, +// }, +// } +// for _, tt := range tests { +// tt := tt +// t.Run(tt.name, func(t *testing.T) { +// assert, require := assert.New(t), require.New(t) +// input := tt.args.v +// require.NotPanics(func() { +// setFieldsToNil(input, tt.args.f) +// }) +// assert.Equal(tt.want, input) +// }) +// } +// } func TestDb_oplogMsgsForItems(t *testing.T) { t.Parallel() @@ -3008,92 +2999,90 @@ func TestDb_oplogMsgsForItems(t *testing.T) { } } -func TestDb_lookupAfterWrite(t *testing.T) { - t.Parallel() - db, _ := TestSetup(t, "postgres") - TestCreateTables(t, db) - scooter := testScooter(t, db, "", 0) - user := testUser(t, db, "", "", "") - type args struct { - resourceWithIder interface{} - opt []Option - } - tests := []struct { - name string - underlying *DB - args args - wantErr bool - want proto.Message - wantIsErr error - }{ - { - name: "simple-private-id", - underlying: db, - args: args{ - resourceWithIder: scooter, - opt: []Option{WithLookup(true)}, - }, - wantErr: false, - want: scooter, - }, - { - name: "simple-public-id", - underlying: db, - args: args{ - resourceWithIder: user, - opt: []Option{WithLookup(true)}, - }, - wantErr: false, - want: user, - }, - { - name: "no-lookup-private-id", - underlying: db, - args: args{ - resourceWithIder: scooter, - opt: []Option{WithLookup(false)}, - }, - wantErr: false, - want: nil, - }, - { - name: "no-lookup-public-id", - underlying: db, - args: args{ - resourceWithIder: user, - opt: []Option{WithLookup(false)}, - }, - wantErr: false, - want: nil, - }, - { - name: "not-an-ider", - underlying: db, - args: args{ - resourceWithIder: &db_test.NotIder{}, - opt: []Option{WithLookup(true)}, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - rw := &Db{ - underlying: tt.underlying, - } - cloner, ok := tt.args.resourceWithIder.(db_test.Cloner) - require.True(ok) - cp := cloner.Clone() - err := rw.lookupAfterWrite(context.Background(), cp, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.want != nil { - assert.True(proto.Equal(tt.want, cp.(proto.Message))) - } - }) - } -} +// func TestDb_lookupAfterWrite(t *testing.T) { +// t.Parallel() +// db, _ := TestSetup(t, "postgres") +// TestCreateTables(t, db) +// scooter := testScooter(t, db, "", 0) +// user := testUser(t, db, "", "", "") +// type args struct { +// resourceWithIder interface{} +// opt []Option +// } +// tests := []struct { +// name string +// underlying *DB +// args args +// wantErr bool +// want proto.Message +// wantIsErr error +// }{ +// { +// name: "simple-private-id", +// underlying: db, +// args: args{ +// resourceWithIder: scooter, +// opt: []Option{WithLookup(true)}, +// }, +// wantErr: false, +// want: scooter, +// }, +// { +// name: "simple-public-id", +// underlying: db, +// args: args{ +// resourceWithIder: user, +// opt: []Option{WithLookup(true)}, +// }, +// wantErr: false, +// want: user, +// }, +// { +// name: "no-lookup-private-id", +// underlying: db, +// args: args{ +// resourceWithIder: scooter, +// opt: []Option{WithLookup(false)}, +// }, +// wantErr: false, +// want: nil, +// }, +// { +// name: "no-lookup-public-id", +// underlying: db, +// args: args{ +// resourceWithIder: user, +// opt: []Option{WithLookup(false)}, +// }, +// wantErr: false, +// want: nil, +// }, +// { +// name: "not-an-ider", +// underlying: db, +// args: args{ +// resourceWithIder: &db_test.NotIder{}, +// opt: []Option{WithLookup(true)}, +// }, +// wantErr: true, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// assert, require := assert.New(t), require.New(t) +// rw := New(tt.underlying) +// cloner, ok := tt.args.resourceWithIder.(db_test.Cloner) +// require.True(ok) +// cp := cloner.Clone() +// err := rw.lookupAfterWrite(context.Background(), cp, tt.args.opt...) +// if tt.wantErr { +// require.Error(err) +// return +// } +// require.NoError(err) +// if tt.want != nil { +// assert.True(proto.Equal(tt.want, cp.(proto.Message))) +// } +// }) +// } +// } diff --git a/internal/db/testing.go b/internal/db/testing.go index 6a5eaf853..d63777a05 100644 --- a/internal/db/testing.go +++ b/internal/db/testing.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "encoding/base64" + "fmt" "strings" "testing" "time" @@ -14,14 +15,16 @@ import ( "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/oplog/store" "github.com/hashicorp/boundary/testing/dbtest" + "github.com/hashicorp/go-dbw" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gorm.io/gorm/logger" ) -// setup the tests (initialize the database one-time and intialized testDatabaseURL). Do not close the returned db. +// setup the tests (initialize the database one-time and intialized +// testDatabaseURL). Do not close the returned db. Supported options: +// WithTestLogLevel, WithTestDatabaseUrl func TestSetup(t *testing.T, dialect string, opt ...TestOption) (*DB, string) { var cleanup func() error var url string @@ -55,7 +58,12 @@ func TestSetup(t *testing.T, dialect string, opt ...TestOption) (*DB, string) { if err != nil { t.Fatal(err) } - db.Logger.LogMode(logger.Error) + switch { + case opts.withLogLevel != DefaultTestLogLevel: + db.wrapped.LogLevel(dbw.LogLevel(opts.withLogLevel)) + default: + db.wrapped.LogLevel(dbw.Error) + } t.Cleanup(func() { sqlDB, err := db.SqlDB(ctx) assert.NoError(t, err) @@ -97,6 +105,20 @@ func AssertPublicId(t *testing.T, prefix, actual string) { assert.Equalf(t, prefix, parts[0], "PublicId want prefix: %q, got: %q in %q", prefix, parts[0], actual) } +// TestDeleteWhere allows you to easily delete resources for testing purposes +// including all the current resources. +func TestDeleteWhere(t *testing.T, conn *DB, i interface{}, whereClause string, args ...interface{}) { + t.Helper() + require := require.New(t) + ctx := context.Background() + tabler, ok := i.(interface { + TableName() string + }) + require.True(ok) + _, err := dbw.New(conn.wrapped).Exec(ctx, fmt.Sprintf(`delete from "%s" where %s`, tabler.TableName(), whereClause), []interface{}{args}) + require.NoError(err) +} + // TestVerifyOplog will verify that there is an oplog entry that matches the provided resourceId. // By default it matches the provided resourceId against the `resource-public-id` tag. If the // WithResourcePrivateId option is provided, the lookup will use the `resource-private-id` tag. @@ -151,12 +173,12 @@ and create_time > NOW()::timestamp - (interval '1 second' * ?) } var metadata store.Metadata - if err := r.LookupWhere(context.Background(), &metadata, where, whereArgs...); err != nil { + if err := r.LookupWhere(context.Background(), &metadata, where, whereArgs); err != nil { return err } var foundEntry oplog.Entry - if err := r.LookupWhere(context.Background(), &foundEntry, "id = ?", metadata.EntryId); err != nil { + if err := r.LookupWhere(context.Background(), &foundEntry, "id = ?", []interface{}{metadata.EntryId}); err != nil { return err } return nil @@ -181,6 +203,7 @@ type testOptions struct { withTestDatabaseUrl string withResourcePrivateId bool withTemplate string + withLogLevel TestLogLevel } func getDefaultTestOptions() testOptions { @@ -229,6 +252,26 @@ func WithTemplate(template string) TestOption { } } +// TestLogLevel defines a test log level for the underlying db package (if applicable) +type TestLogLevel int + +const ( + // See WithTestLogLevel(...) test only option + DefaultTestLogLevel TestLogLevel = iota + SilentTestLogLevel + ErrorTestLogLevel + WarnTestLogLevel + InfoTestLogLevel +) + +// WithTestLogLevel provides a way to specify a test log level for the +// underlying database package (if applicable). +func WithTestLogLevel(_ *testing.T, l TestLogLevel) TestOption { + return func(o *testOptions) { + o.withLogLevel = l + } +} + // TestCreateTables will create the test tables for the db pkg func TestCreateTables(t *testing.T, conn *DB) { t.Helper() diff --git a/internal/db/testing_test.go b/internal/db/testing_test.go index bffe0b3a9..963247bd7 100644 --- a/internal/db/testing_test.go +++ b/internal/db/testing_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_Utils(t *testing.T) { @@ -21,12 +22,12 @@ func Test_Utils(t *testing.T) { } func TestVerifyOplogEntry(t *testing.T) { - db, _ := TestSetup(t, "postgres") + d, _ := TestSetup(t, "postgres") assert := assert.New(t) - TestCreateTables(t, db) + TestCreateTables(t, d) t.Run("valid", func(t *testing.T) { - rw := Db{underlying: db} + rw := New(d) id, err := uuid.GenerateUUID() assert.NoError(err) user, err := db_test.NewTestUser() @@ -51,14 +52,14 @@ func TestVerifyOplogEntry(t *testing.T) { err = rw.LookupByPublicId(context.Background(), foundUser) assert.NoError(err) assert.Equal(foundUser.Id, user.Id) - err = TestVerifyOplog(t, &rw, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_CREATE), WithCreateNotBefore(5*time.Second)) + err = TestVerifyOplog(t, rw, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_CREATE), WithCreateNotBefore(5*time.Second)) assert.NoError(err) }) t.Run("should-fail", func(t *testing.T) { - rw := Db{underlying: db} + rw := New(d) id, err := uuid.GenerateUUID() assert.NoError(err) - err = TestVerifyOplog(t, &rw, id) + err = TestVerifyOplog(t, rw, id) assert.Error(err) }) } @@ -121,3 +122,21 @@ func TestWithCreateNotBefore(t *testing.T) { }) } } + +func Test_TestDeleteWhere(t *testing.T) { + assert, require := assert.New(t), require.New(t) + d, _ := TestSetup(t, "postgres") + TestCreateTables(t, d) + user, err := db_test.NewTestUser() + assert.NoError(err) + id, err := uuid.GenerateUUID() + assert.NoError(err) + user.Name = "foo-" + id + rw := New(d) + err = rw.Create( + context.Background(), + user, + ) + require.NoError(err) + TestDeleteWhere(t, d, user, "1 = ?", 1) +} diff --git a/internal/errors/error.go b/internal/errors/error.go index a4fdf3f99..72494c72d 100644 --- a/internal/errors/error.go +++ b/internal/errors/error.go @@ -211,7 +211,7 @@ func Convert(e error) *Err { } switch pgxError.Code { case "42P01": - return E(ctx, WithoutEvent(), WithCode(MissingTable), WithMsg(pgxError.Message)).(*Err) + return E(ctx, WithoutEvent(), WithCode(MissingTable), WithMsg(pgxError.Message), WithWrap(e)).(*Err) case "42703": return E(ctx, WithoutEvent(), WithCode(ColumnNotFound), WithMsg(pgxError.Message)).(*Err) case "P0001": diff --git a/internal/errors/error_test.go b/internal/errors/error_test.go index 91101bfef..516258e32 100644 --- a/internal/errors/error_test.go +++ b/internal/errors/error_test.go @@ -518,6 +518,6 @@ func TestConvertError(t *testing.T) { e := errors.Convert(err) require.NotNil(e) assert.True(errors.Match(errors.T(errors.MissingTable), e)) - assert.Equal("db.Exec: relation \"not_a_defined_table\" does not exist: integrity violation: error #1004", e.Error()) + assert.Contains(err.Error(), "db.Exec: relation \"not_a_defined_table\" does not exist: integrity violation: error #1004") }) } diff --git a/internal/host/plugin/job_orphaned_host_cleanup.go b/internal/host/plugin/job_orphaned_host_cleanup.go index ed521f4b0..57e5498b4 100644 --- a/internal/host/plugin/job_orphaned_host_cleanup.go +++ b/internal/host/plugin/job_orphaned_host_cleanup.go @@ -86,7 +86,7 @@ func (r *OrphanedHostCleanupJob) Run(ctx context.Context) error { } // NextRunIn returns the default run frequency of the cleanup job. -func (r *OrphanedHostCleanupJob) NextRunIn() (time.Duration, error) { +func (r *OrphanedHostCleanupJob) NextRunIn(_ context.Context) (time.Duration, error) { const op = "plugin.(OrphanedHostCleanupJob).NextRunIn" return orphanedHostCleanupJobRunInterval, nil } diff --git a/internal/host/plugin/job_set_sync.go b/internal/host/plugin/job_set_sync.go index 33cef5b2a..30a73b6ef 100644 --- a/internal/host/plugin/job_set_sync.go +++ b/internal/host/plugin/job_set_sync.go @@ -115,9 +115,9 @@ func (r *SetSyncJob) Run(ctx context.Context) error { } // NextRunIn queries the plugin host set db to determine when the next set should be synced. -func (r *SetSyncJob) NextRunIn() (time.Duration, error) { +func (r *SetSyncJob) NextRunIn(ctx context.Context) (time.Duration, error) { const op = "plugin.(SetSyncJob).NextRunIn" - next, err := nextSync(r) + next, err := nextSync(ctx, r) if err != nil { return setSyncJobRunInterval, errors.WrapDeprecated(err, op) } @@ -134,7 +134,7 @@ func (r *SetSyncJob) Description() string { return "Periodically syncs plugin based catalog hosts and host set memberships." } -func nextSync(j scheduler.Job) (time.Duration, error) { +func nextSync(ctx context.Context, j scheduler.Job) (time.Duration, error) { const op = "plugin.nextSync" var query string var r db.Reader @@ -162,7 +162,7 @@ func nextSync(j scheduler.Job) (time.Duration, error) { ResyncIn time.Duration } var n NextResync - err = r.ScanRows(rows, &n) + err = r.ScanRows(ctx, rows, &n) if err != nil { return 0, errors.WrapDeprecated(err, op) } @@ -409,7 +409,7 @@ func (r *SetSyncJob) upsertAndCleanHosts( db.ExpBackoff{}, func(r db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0) - ticket, err := w.GetTicket(ret) + ticket, err := w.GetTicket(ctx, ret) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -524,7 +524,7 @@ func (r *SetSyncJob) upsertAndCleanHosts( func(r db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0) - ticket, err := w.GetTicket(hs) + ticket, err := w.GetTicket(ctx, hs) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/host/plugin/job_set_sync_test.go b/internal/host/plugin/job_set_sync_test.go index 1dea7986c..fdd1a1cbc 100644 --- a/internal/host/plugin/job_set_sync_test.go +++ b/internal/host/plugin/job_set_sync_test.go @@ -525,7 +525,7 @@ func TestSetSyncJob_NextRunIn(t *testing.T) { _, err = rw.Update(ctx, hostSet, fieldMaskPaths, setToNullPaths) require.NoError(err) - got, err := r.NextRunIn() + got, err := r.NextRunIn(context.Background()) require.NoError(err) // Round to five seconds to account for lost time between updating set and determining next run assert.Equal(tt.want.Round(5*time.Second), got.Round(5*time.Second)) diff --git a/internal/host/plugin/repository_host_catalog.go b/internal/host/plugin/repository_host_catalog.go index 3b6f6469b..f914a3497 100644 --- a/internal/host/plugin/repository_host_catalog.go +++ b/internal/host/plugin/repository_host_catalog.go @@ -106,7 +106,7 @@ func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, _ ...Opt db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 3) - ticket, err := w.GetTicket(c) + ticket, err := w.GetTicket(ctx, c) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -341,7 +341,7 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 3) - ticket, err := w.GetTicket(newCatalog) + ticket, err := w.GetTicket(ctx, newCatalog) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/host/plugin/repository_host_catalog_test.go b/internal/host/plugin/repository_host_catalog_test.go index 32e371639..ba6cba4c8 100644 --- a/internal/host/plugin/repository_host_catalog_test.go +++ b/internal/host/plugin/repository_host_catalog_test.go @@ -302,7 +302,7 @@ func TestRepository_CreateCatalog(t *testing.T) { assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second))) cSecret := allocHostCatalogSecret() - err = rw.LookupWhere(ctx, &cSecret, "catalog_id=?", got.GetPublicId()) + err = rw.LookupWhere(ctx, &cSecret, "catalog_id=?", []interface{}{got.GetPublicId()}) if tt.wantSecret == nil { assert.Nil(got.Secrets) require.Error(t, err) @@ -608,7 +608,7 @@ func TestRepository_UpdateCatalog(t *testing.T) { require := require.New(t) cSecret := allocHostCatalogSecret() - err := dbRW.LookupWhere(ctx, &cSecret, "catalog_id=?", gotCatalog.GetPublicId()) + err := dbRW.LookupWhere(ctx, &cSecret, "catalog_id=?", []interface{}{gotCatalog.GetPublicId()}) require.NoError(err) require.Empty(cSecret.Secret) require.NotEmpty(cSecret.CtSecret) @@ -629,7 +629,7 @@ func TestRepository_UpdateCatalog(t *testing.T) { assert := assert.New(t) cSecret := allocHostCatalogSecret() - err := dbRW.LookupWhere(ctx, &cSecret, "catalog_id=?", gotCatalog.GetPublicId()) + err := dbRW.LookupWhere(ctx, &cSecret, "catalog_id=?", []interface{}{gotCatalog.GetPublicId()}) assert.Error(err) assert.True(errors.IsNotFoundError(err)) } @@ -1453,10 +1453,12 @@ func (j *testSyncJob) Status() scheduler.JobStatus { } } -func (j *testSyncJob) Run(_ context.Context) error { return nil } -func (j *testSyncJob) NextRunIn() (time.Duration, error) { return setSyncJobRunInterval, nil } -func (j *testSyncJob) Name() string { return setSyncJobName } -func (j *testSyncJob) Description() string { return setSyncJobName } +func (j *testSyncJob) Run(_ context.Context) error { return nil } +func (j *testSyncJob) NextRunIn(_ context.Context) (time.Duration, error) { + return setSyncJobRunInterval, nil +} +func (j *testSyncJob) Name() string { return setSyncJobName } +func (j *testSyncJob) Description() string { return setSyncJobName } func TestRepository_UpdateCatalog_SyncSets(t *testing.T) { ctx := context.Background() diff --git a/internal/host/plugin/repository_host_set.go b/internal/host/plugin/repository_host_set.go index 9388519aa..482bb1688 100644 --- a/internal/host/plugin/repository_host_set.go +++ b/internal/host/plugin/repository_host_set.go @@ -117,7 +117,7 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, len(preferredEndpoints)+2) - ticket, err := w.GetTicket(s) + ticket, err := w.GetTicket(ctx, s) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -365,7 +365,7 @@ func (r *Repository) UpdateSet(ctx context.Context, scopeId string, s *HostSet, func(reader db.Reader, w db.Writer) error { returnedSet = newSet.clone() msgs := make([]*oplog.Message, 0, len(preferredEndpoints)+len(currentSet.PreferredEndpoints)+2) - ticket, err := w.GetTicket(s) + ticket, err := w.GetTicket(ctx, s) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/host/plugin/repository_host_util.go b/internal/host/plugin/repository_host_util.go index 28f023e23..16c1e23af 100644 --- a/internal/host/plugin/repository_host_util.go +++ b/internal/host/plugin/repository_host_util.go @@ -44,8 +44,8 @@ type hostInfo struct { func createNewHostMap(ctx context.Context, catalog *HostCatalog, phs []*plgpb.ListHostsResponseHost, - currentHostMap map[string]*Host) (map[string]*hostInfo, error) { - + currentHostMap map[string]*Host) (map[string]*hostInfo, error, +) { const op = "plugin.createNewHostMap" newHostMap := make(map[string]*hostInfo, len(phs)) @@ -200,8 +200,8 @@ func getSetChanges( currentHostMap map[string]*Host, newHostMap map[string]*hostInfo) ( setMembershipsToAdd, setMembershipsToRemove map[string][]string, - allSetIds map[string]struct{}) { - + allSetIds map[string]struct{}, +) { // First, find sets that hosts should be added to: hosts that are new or // have new set IDs returned. for newHostId, newHost := range newHostMap { diff --git a/internal/host/preferred_endpoint_test.go b/internal/host/preferred_endpoint_test.go index a4a6a6ff9..dc784a650 100644 --- a/internal/host/preferred_endpoint_test.go +++ b/internal/host/preferred_endpoint_test.go @@ -141,7 +141,7 @@ func TestPreferredEndpoint_Create(t *testing.T) { assert.NoError(err) } found := host.AllocPreferredEndpoint() - require.NoError(rw.LookupWhere(ctx, found, "host_set_id = ? and priority = ?", tt.args.hostSetId, tt.args.priority)) + require.NoError(rw.LookupWhere(ctx, found, "host_set_id = ? and priority = ?", []interface{}{tt.args.hostSetId, tt.args.priority})) assert.Equal(got, found) } }) @@ -220,7 +220,7 @@ func TestPreferredEndpoint_Delete(t *testing.T) { } require.Equal(tt.wantRowsDeleted, deletedRows) found := host.AllocPreferredEndpoint() - err = rw.LookupWhere(ctx, &found, "host_set_id = ?", set.PublicId) + err = rw.LookupWhere(ctx, &found, "host_set_id = ?", []interface{}{set.PublicId}) assert.True(errors.IsNotFoundError(err)) }) } diff --git a/internal/host/static/host_set_test.go b/internal/host/static/host_set_test.go index d52fbd484..73fb10aca 100644 --- a/internal/host/static/host_set_test.go +++ b/internal/host/static/host_set_test.go @@ -9,15 +9,13 @@ 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) { - conn, _ := db.TestSetup(t, "postgres") + conn, _ := db.TestSetup(t, "postgres", db.WithTestLogLevel(t, db.SilentTestLogLevel)) wrapper := db.TestWrapper(t) _, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) cat := testCatalog(t, conn, prj.PublicId) - 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 4176f506b..2236aa36e 100644 --- a/internal/host/static/host_test.go +++ b/internal/host/static/host_test.go @@ -9,16 +9,14 @@ 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) { - conn, _ := db.TestSetup(t, "postgres") + conn, _ := db.TestSetup(t, "postgres", db.WithTestLogLevel(t, db.SilentTestLogLevel)) wrapper := db.TestWrapper(t) _, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) cat := testCatalog(t, conn, prj.PublicId) - conn.Logger.LogMode(logger.Silent) type args struct { catalogId string opts []Option diff --git a/internal/host/static/immutable_fields_test.go b/internal/host/static/immutable_fields_test.go index d5b593417..c43aff743 100644 --- a/internal/host/static/immutable_fields_test.go +++ b/internal/host/static/immutable_fields_test.go @@ -270,7 +270,7 @@ func TestStaticHostSetMember_ImmutableFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.testCloneHostSetMember() - err = w.LookupWhere(context.Background(), orig, "host_id = ? and set_id = ?", orig.HostId, orig.SetId) + err = w.LookupWhere(context.Background(), orig, "host_id = ? and set_id = ?", []interface{}{orig.HostId, orig.SetId}) require.NoError(err) rowsUpdated, err := w.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) @@ -278,7 +278,7 @@ func TestStaticHostSetMember_ImmutableFields(t *testing.T) { assert.Equal(0, rowsUpdated) after := new.testCloneHostSetMember() - err = w.LookupWhere(context.Background(), after, "host_id = ? and set_id = ?", after.HostId, after.SetId) + err = w.LookupWhere(context.Background(), after, "host_id = ? and set_id = ?", []interface{}{after.HostId, after.SetId}) require.NoError(err) assert.True(proto.Equal(orig, after)) diff --git a/internal/host/static/repository_host_set_member.go b/internal/host/static/repository_host_set_member.go index 76b25fb99..f3be42263 100644 --- a/internal/host/static/repository_host_set_member.go +++ b/internal/host/static/repository_host_set_member.go @@ -109,7 +109,7 @@ func updateVersion(ctx context.Context, w db.Writer, wrapper wrapping.Wrapper, m msgs = append(msgs, setMsg) // Write oplog - ticket, err := w.GetTicket(set) + ticket, err := w.GetTicket(ctx, set) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -356,7 +356,7 @@ func (r *Repository) changes(ctx context.Context, setId string, hostIds []string var changes []*change for rows.Next() { var chg change - if err := r.reader.ScanRows(rows, &chg); err != nil { + if err := r.reader.ScanRows(ctx, rows, &chg); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed")) } changes = append(changes, &chg) diff --git a/internal/iam/group_member_test.go b/internal/iam/group_member_test.go index 13e1ae8c7..0b19fc020 100644 --- a/internal/iam/group_member_test.go +++ b/internal/iam/group_member_test.go @@ -166,7 +166,7 @@ func Test_GroupMemberCreate(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: `db.Create: create failed: insert or update on table "iam_group_member_user" violates foreign key constraint`, + wantErrMsg: `db.Create: insert or update on table "iam_group_member_user" violates foreign key constraint`, }, { name: "bad-user-id", @@ -180,7 +180,7 @@ func Test_GroupMemberCreate(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: `db.Create: create failed: insert or update on table "iam_group_member_user" violates foreign key constraint`, + wantErrMsg: `integrity violation: error #1003`, }, { name: "missing-group-id", @@ -227,7 +227,7 @@ func Test_GroupMemberCreate(t *testing.T) { }, wantDup: true, wantErr: true, - wantErrMsg: `db.Create: create failed: duplicate key value violates unique constraint "iam_group_member_user_pkey"`, + wantErrMsg: `db.Create: duplicate key value violates unique constraint "iam_group_member_user_pkey"`, }, } @@ -251,7 +251,7 @@ func Test_GroupMemberCreate(t *testing.T) { assert.NoError(err) found := allocGroupMember() - err = w.LookupWhere(context.Background(), &found, "group_id = ? and member_id = ?", gm.GroupId, gm.MemberId) + err = w.LookupWhere(context.Background(), &found, "group_id = ? and member_id = ?", []interface{}{gm.GroupId, gm.MemberId}) require.NoError(err) assert.Equal(gm, &found) }) @@ -329,7 +329,7 @@ func Test_GroupMemberDelete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := allocGroupMember() - err = rw.LookupWhere(context.Background(), &found, "group_id = ? and member_id = ?", tt.gm.GetGroupId(), tt.gm.GetMemberId()) + err = rw.LookupWhere(context.Background(), &found, "group_id = ? and member_id = ?", []interface{}{tt.gm.GetGroupId(), tt.gm.GetMemberId()}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) diff --git a/internal/iam/group_test.go b/internal/iam/group_test.go index d08e9b4c7..45dac36ef 100644 --- a/internal/iam/group_test.go +++ b/internal/iam/group_test.go @@ -169,7 +169,7 @@ func Test_GroupCreate(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(Group).VetForWrite: iam.validateScopeForWrite: scope is not found: search issue: error #1100", + wantErrMsg: "iam.validateScopeForWrite: scope is not found: search issue: error #1100", }, } @@ -189,7 +189,7 @@ func Test_GroupCreate(t *testing.T) { err := w.Create(context.Background(), g) if tt.wantErr { require.Error(err) - assert.Equal(tt.wantErrMsg, err.Error()) + assert.Contains(err.Error(), tt.wantErrMsg) return } assert.NoError(err) @@ -246,7 +246,7 @@ func Test_GroupUpdate(t *testing.T) { ScopeId: proj.PublicId, }, wantErr: true, - wantErrMsg: "db.Update: iam.(Group).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", + wantErrMsg: "db.Update: dbw.Update: error before write: iam.(Group).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", }, { name: "proj-scope-id-not-in-mask", diff --git a/internal/iam/principal_role_ext_test.go b/internal/iam/principal_role_ext_test.go index 58020e462..89483ac71 100644 --- a/internal/iam/principal_role_ext_test.go +++ b/internal/iam/principal_role_ext_test.go @@ -159,7 +159,7 @@ func TestManagedGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_managed_group_role\" violates foreign key constraint \"iam_managed_group_role_role_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "bad-principal-id", @@ -173,7 +173,7 @@ func TestManagedGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_managed_group_role\" violates foreign key constraint \"iam_managed_group_role_principal_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "missing-role-id", @@ -188,7 +188,7 @@ func TestManagedGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(ManagedGroupRole).VetForWrite: missing role id: parameter violation: error #100", + wantErrMsg: "iam.(ManagedGroupRole).VetForWrite: missing role id: parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -205,7 +205,7 @@ func TestManagedGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(ManagedGroupRole).VetForWrite: missing managed group id: parameter violation: error #100", + wantErrMsg: "iam.(ManagedGroupRole).VetForWrite: missing managed group id: parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -220,7 +220,7 @@ func TestManagedGroupRole_Create(t *testing.T) { }, wantDup: true, wantErr: true, - wantErrMsg: `db.Create: create failed: duplicate key value violates unique constraint`, + wantErrMsg: `db.Create: duplicate key value violates unique constraint "iam_managed_group_role_pkey": unique constraint violation`, }, } @@ -244,7 +244,7 @@ func TestManagedGroupRole_Create(t *testing.T) { assert.NoError(err) found := iam.AllocManagedGroupRole() - err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", r.RoleId, r.PrincipalId) + err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{r.RoleId, r.PrincipalId}) require.NoError(err) assert.Equal(r, &found) }) @@ -358,7 +358,7 @@ func TestManagedGroupRole_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := iam.AllocManagedGroupRole() - err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", tt.role.GetRoleId(), tt.role.GetPrincipalId()) + err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{tt.role.GetRoleId(), tt.role.GetPrincipalId()}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) diff --git a/internal/iam/principal_role_test.go b/internal/iam/principal_role_test.go index 9f03c1a90..16736569a 100644 --- a/internal/iam/principal_role_test.go +++ b/internal/iam/principal_role_test.go @@ -176,7 +176,7 @@ func TestUserRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_user_role\" violates foreign key constraint \"iam_user_role_role_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "bad-user-id", @@ -190,7 +190,7 @@ func TestUserRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_user_role\" violates foreign key constraint \"iam_user_role_principal_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "missing-role-id", @@ -206,7 +206,7 @@ func TestUserRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(UserRole).VetForWrite: missing role id: parameter violation: error #100", + wantErrMsg: "iam.(UserRole).VetForWrite: missing role id: parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -223,7 +223,7 @@ func TestUserRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(UserRole).VetForWrite: missing user id: parameter violation: error #100", + wantErrMsg: "iam.(UserRole).VetForWrite: missing user id: parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -239,7 +239,7 @@ func TestUserRole_Create(t *testing.T) { }, wantDup: true, wantErr: true, - wantErrMsg: `db.Create: create failed: duplicate key value violates unique constraint "iam_user_role_pkey"`, + wantErrMsg: `db.Create: duplicate key value violates unique constraint "iam_user_role_pkey": unique constraint violation`, }, } @@ -263,7 +263,7 @@ func TestUserRole_Create(t *testing.T) { assert.NoError(err) found := allocUserRole() - err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", r.RoleId, r.PrincipalId) + err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{r.RoleId, r.PrincipalId}) require.NoError(err) assert.Equal(r, &found) }) @@ -341,7 +341,7 @@ func TestUserRole_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := allocUserRole() - err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", tt.role.GetRoleId(), tt.role.GetPrincipalId()) + err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{tt.role.GetRoleId(), tt.role.GetPrincipalId()}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) @@ -537,7 +537,7 @@ func TestGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_group_role\" violates foreign key constraint \"iam_group_role_role_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "bad-user-id", @@ -551,7 +551,7 @@ func TestGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: create failed: insert or update on table \"iam_group_role\" violates foreign key constraint \"iam_group_role_principal_id_fkey\"", + wantErrMsg: "integrity violation: error #1003", }, { name: "missing-role-id", @@ -567,7 +567,7 @@ func TestGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(GroupRole).VetForWrite: missing role id: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -584,7 +584,7 @@ func TestGroupRole_Create(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(GroupRole).VetForWrite: missing group id: parameter violation: error #100", + wantErrMsg: "parameter violation: error #100", wantIsErr: errors.InvalidParameter, }, { @@ -600,7 +600,7 @@ func TestGroupRole_Create(t *testing.T) { }, wantDup: true, wantErr: true, - wantErrMsg: `db.Create: create failed: duplicate key value violates unique constraint`, + wantErrMsg: `unique constraint violation: integrity violation: error #1002`, }, { name: "dup-at-proj", @@ -615,7 +615,7 @@ func TestGroupRole_Create(t *testing.T) { }, wantDup: true, wantErr: true, - wantErrMsg: `db.Create: create failed: duplicate key value violates unique constraint`, + wantErrMsg: `unique constraint violation: integrity violation: error #1002`, }, } @@ -639,7 +639,7 @@ func TestGroupRole_Create(t *testing.T) { assert.NoError(err) found := allocGroupRole() - err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", r.RoleId, r.PrincipalId) + err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{r.RoleId, r.PrincipalId}) require.NoError(err) assert.Equal(r, &found) }) @@ -722,7 +722,7 @@ func TestGroupRole_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) found := allocGroupRole() - err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", tt.role.GetRoleId(), tt.role.GetPrincipalId()) + err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []interface{}{tt.role.GetRoleId(), tt.role.GetPrincipalId()}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) diff --git a/internal/iam/repository_group.go b/internal/iam/repository_group.go index 44ca3e1e9..9077b841c 100644 --- a/internal/iam/repository_group.go +++ b/internal/iam/repository_group.go @@ -240,7 +240,7 @@ func (r *Repository) AddGroupMembers(ctx context.Context, groupId string, groupV db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - groupTicket, err := w.GetTicket(&group) + groupTicket, err := w.GetTicket(ctx, &group) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -333,7 +333,7 @@ func (r *Repository) DeleteGroupMembers(ctx context.Context, groupId string, gro db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - groupTicket, err := w.GetTicket(&group) + groupTicket, err := w.GetTicket(ctx, &group) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -438,7 +438,7 @@ func (r *Repository) SetGroupMembers(ctx context.Context, groupId string, groupV // we need a group, which won't be redeemed until all the other // writes are successful. We can't just use a single ticket because // we need to write oplog entries for deletes and adds - groupTicket, err := w.GetTicket(&group) + groupTicket, err := w.GetTicket(ctx, &group) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -526,7 +526,7 @@ func groupMemberChanges(ctx context.Context, reader db.Reader, groupId string, u var changes []*change for rows.Next() { var chg change - if err := reader.ScanRows(rows, &chg); err != nil { + if err := reader.ScanRows(ctx, rows, &chg); err != nil { return nil, nil, errors.Wrap(ctx, err, op) } changes = append(changes, &chg) diff --git a/internal/iam/repository_group_test.go b/internal/iam/repository_group_test.go index 5ea3b4b53..dfa24846e 100644 --- a/internal/iam/repository_group_test.go +++ b/internal/iam/repository_group_test.go @@ -239,7 +239,7 @@ func TestRepository_UpdateGroup(t *testing.T) { newScopeId: org.PublicId, wantErr: true, wantRowsUpdate: 0, - wantErrMsg: "db.DoTx: iam.(Repository).UpdateGroup: iam.(Repository).update: db.DoTx: iam.(Repository).update: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "record not found, search issue: error #1100", wantIsError: errors.RecordNotFound, }, { @@ -627,7 +627,7 @@ func TestRepository_ListGroups(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocGroup()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocGroup(); ; return &i }(), "1=1") testGroups := []*Group{} for i := 0; i < tt.createCnt; i++ { testGroups = append(testGroups, TestGroup(t, conn, tt.createScopeId)) @@ -651,7 +651,7 @@ func TestRepository_ListGroups_Multiple_Scopes(t *testing.T) { repo := TestRepo(t, conn, wrapper) org, proj := TestScopes(t, repo) - require.NoError(t, conn.Where("1=1").Delete(allocGroup()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { g := allocGroup(); return &g }(), "1=1") const numPerScope = 10 var total int @@ -733,7 +733,7 @@ func TestRepository_ListMembers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocGroupMember()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocGroupMember(); ; return &i }(), "1=1") gm := []*GroupMemberUser{} for i := 0; i < tt.createCnt; i++ { u := TestUser(t, repo, org.PublicId) @@ -851,7 +851,9 @@ func TestRepository_AddGroupMembers(t *testing.T) { groupVersion += 1 version = groupVersion } - require.NoError(conn.Where("1=1").Delete(allocGroupMember()).Error) + gm := allocGroupMember() + db.TestDeleteWhere(t, conn, &gm, "1=1") + got, err := repo.AddGroupMembers(context.Background(), tt.args.groupId, version, tt.args.userIds, tt.args.opt...) if tt.wantErr { require.Error(err) diff --git a/internal/iam/repository_principal_role.go b/internal/iam/repository_principal_role.go index 98f67148c..b8b08f969 100644 --- a/internal/iam/repository_principal_role.go +++ b/internal/iam/repository_principal_role.go @@ -77,7 +77,7 @@ func (r *Repository) AddPrincipalRoles(ctx context.Context, roleId string, roleV db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -196,7 +196,7 @@ func (r *Repository) SetPrincipalRoles(ctx context.Context, roleId string, roleV // we need a roleTicket, which won't be redeemed until all the other // writes are successful. We can't just use a single ticket because // we need to write oplog entries for deletes and adds - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket for role")) } @@ -376,7 +376,7 @@ func (r *Repository) DeletePrincipalRoles(ctx context.Context, roleId string, ro db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/iam/repository_principal_role_test.go b/internal/iam/repository_principal_role_test.go index 9ac480aef..9e788b84e 100644 --- a/internal/iam/repository_principal_role_test.go +++ b/internal/iam/repository_principal_role_test.go @@ -125,8 +125,8 @@ func TestRepository_AddPrincipalRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocUserRole()).Error) - require.NoError(conn.Where("1=1").Delete(allocGroupRole()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { r := allocUserRole(); return &r }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { g := allocGroupRole(); return &g }(), "1=1") orgs, projects := createScopesFn() var userIds, groupIds []string @@ -264,7 +264,7 @@ func TestRepository_ListPrincipalRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRole()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { r := allocRole(); return &r }(), "1=1") role := TestRole(t, conn, tt.createScopeId) userRoles := make([]string, 0, tt.createCnt) groupRoles := make([]string, 0, tt.createCnt) diff --git a/internal/iam/repository_role_grant.go b/internal/iam/repository_role_grant.go index 0bb39d82f..445333414 100644 --- a/internal/iam/repository_role_grant.go +++ b/internal/iam/repository_role_grant.go @@ -52,7 +52,7 @@ func (r *Repository) AddRoleGrants(ctx context.Context, roleId string, roleVersi db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -133,7 +133,7 @@ func (r *Repository) DeleteRoleGrants(ctx context.Context, roleId string, roleVe db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -307,7 +307,7 @@ func (r *Repository) SetRoleGrants(ctx context.Context, roleId string, roleVersi db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - roleTicket, err := w.GetTicket(&role) + roleTicket, err := w.GetTicket(ctx, &role) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -483,7 +483,7 @@ select role_id as role_id, role_scope as scope_id, role_grant as grant from fina defer rows.Close() for rows.Next() { var g perms.GrantTuple - if err := r.reader.ScanRows(rows, &g); err != nil { + if err := r.reader.ScanRows(ctx, rows, &g); err != nil { return nil, errors.Wrap(ctx, err, op) } grants = append(grants, g) diff --git a/internal/iam/repository_role_grant_test.go b/internal/iam/repository_role_grant_test.go index 96f35065f..6aeabdd98 100644 --- a/internal/iam/repository_role_grant_test.go +++ b/internal/iam/repository_role_grant_test.go @@ -82,7 +82,7 @@ func TestRepository_AddRoleGrants(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { rg := allocRoleGrant(); return &rg }(), "1=1") got, err := repo.AddRoleGrants(context.Background(), tt.args.roleId, tt.args.roleVersion, tt.args.grants, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -190,7 +190,7 @@ func TestRepository_ListRoleGrants(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRole()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { r := allocRole(); return &r }(), "1=1") role := TestRole(t, conn, tt.createScopeId) roleGrants := make([]string, 0, tt.createCnt) for i := 0; i < tt.createCnt; i++ { @@ -333,7 +333,7 @@ func TestRepository_DeleteRoleGrants(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { rg := allocRoleGrant(); return &rg }(), "1=1") grants := make([]*RoleGrant, 0, tt.args.createCnt) grantStrings := make([]string, 0, tt.args.createCnt) for i := 0; i < tt.args.createCnt; i++ { @@ -408,7 +408,7 @@ func TestRepository_SetRoleGrants_Randomize(t *testing.T) { repo := TestRepo(t, conn, wrapper) org, _ := TestScopes(t, repo) role := TestRole(t, conn, org.PublicId) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocRoleGrant(); return &i }(), "1=1") type roleGrantWrapper struct { grantString string @@ -550,7 +550,8 @@ func TestRepository_SetRoleGrants_Parameters(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + rg := allocRoleGrant() + db.TestDeleteWhere(t, conn, &rg, "1=1") got, gotAffectedRows, err := repo.SetRoleGrants(context.Background(), tt.args.roleId, tt.args.roleVersion, tt.args.grants, tt.args.opt...) if tt.wantErr { require.Error(err) diff --git a/internal/iam/repository_role_test.go b/internal/iam/repository_role_test.go index f1551334c..d2ec41271 100644 --- a/internal/iam/repository_role_test.go +++ b/internal/iam/repository_role_test.go @@ -240,7 +240,7 @@ func TestRepository_UpdateRole(t *testing.T) { newScopeId: org.PublicId, wantErr: true, wantRowsUpdate: 0, - wantErrMsg: "db.DoTx: iam.(Repository).UpdateRole: iam.(Repository).update: db.DoTx: iam.(Repository).update: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "error #1100", wantIsError: errors.RecordNotFound, }, { @@ -625,7 +625,7 @@ func TestRepository_ListRoles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRole()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { r := allocRole(); return &r }(), "1=1") testRoles := []*Role{} for i := 0; i < tt.createCnt; i++ { testRoles = append(testRoles, TestRole(t, conn, tt.createScopeId)) @@ -649,7 +649,7 @@ func TestRepository_ListRoles_Multiple_Scopes(t *testing.T) { repo := TestRepo(t, conn, wrapper) org, proj := TestScopes(t, repo) - require.NoError(t, conn.Where("1=1").Delete(allocRole()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocRole(); return &i }(), "1=1") const numPerScope = 10 var total int diff --git a/internal/iam/repository_scope.go b/internal/iam/repository_scope.go index 39b8065fd..466b436ee 100644 --- a/internal/iam/repository_scope.go +++ b/internal/iam/repository_scope.go @@ -204,7 +204,7 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o adminRole = adminRoleRaw.(*Role) msgs := make([]*oplog.Message, 0, 3) - roleTicket, err := w.GetTicket(adminRole) + roleTicket, err := w.GetTicket(ctx, adminRole) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -267,7 +267,7 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o defaultRole = defaultRoleRaw.(*Role) msgs := make([]*oplog.Message, 0, 6) - roleTicket, err := w.GetTicket(defaultRole) + roleTicket, err := w.GetTicket(ctx, defaultRole) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/iam/repository_scope_test.go b/internal/iam/repository_scope_test.go index 6a3691763..d27105306 100644 --- a/internal/iam/repository_scope_test.go +++ b/internal/iam/repository_scope_test.go @@ -448,7 +448,7 @@ func TestRepository_UpdateScope(t *testing.T) { for _, f := range tt.wantNullFields { where = fmt.Sprintf("%s and %s is null", where, f) } - err = rw.LookupWhere(context.Background(), &foundScope, where, org.PublicId) + err = rw.LookupWhere(context.Background(), &foundScope, where, []interface{}{org.PublicId}) require.NoError(err) assert.Equal(org.PublicId, foundScope.PublicId) assert.Equal(tt.wantName, foundScope.Name) @@ -520,7 +520,8 @@ func Test_Repository_ListScopes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("type = 'org'").Delete(AllocScope()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocScope(); ; return &i }(), "type = 'org'") + testOrgs := []*Scope{} for i := 0; i < tt.createCnt; i++ { testOrgs = append(testOrgs, testOrg(t, repo, "", "")) @@ -543,7 +544,7 @@ func TestRepository_ListScopes_Multiple_Scopes(t *testing.T) { wrapper := db.TestWrapper(t) repo := TestRepo(t, conn, wrapper) - require.NoError(t, conn.Where("public_id != 'global'").Delete(AllocScope()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocScope(); return &i }(), "public_id != 'global'") const numPerScope = 10 var total int diff --git a/internal/iam/repository_test.go b/internal/iam/repository_test.go index 128932a32..bb1b4d4a9 100644 --- a/internal/iam/repository_test.go +++ b/internal/iam/repository_test.go @@ -104,6 +104,7 @@ func TestNewRepository(t *testing.T) { func Test_Repository_create(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) wrapper := db.TestWrapper(t) repo := TestRepo(t, conn, wrapper) t.Run("valid-scope", func(t *testing.T) { @@ -125,11 +126,11 @@ func Test_Repository_create(t *testing.T) { assert.True(proto.Equal(foundScope, retScope.(*Scope))) var metadata store.Metadata - err = conn.Where("key = ? and value = ?", "resource-public-id", s.PublicId).First(&metadata).Error + err = rw.LookupWhere(context.Background(), &metadata, "key = ? and value = ?", []interface{}{"resource-public-id", s.PublicId}) require.NoError(err) var foundEntry oplog.Entry - err = conn.Where("id = ?", metadata.EntryId).First(&foundEntry).Error + err = rw.LookupWhere(context.Background(), &foundEntry, "id = ?", []interface{}{metadata.EntryId}) assert.NoError(err) }) t.Run("nil-resource", func(t *testing.T) { @@ -159,7 +160,8 @@ func Test_Repository_delete(t *testing.T) { err = db.TestVerifyOplog(t, rw, s.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(5*time.Second)) require.NoError(err) }) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + rk := kms.AllocRootKey() + db.TestDeleteWhere(t, conn, &rk, "1=1") t.Run("nil-resource", func(t *testing.T) { assert, require := assert.New(t), require.New(t) @@ -243,7 +245,7 @@ func TestRepository_update(t *testing.T) { }, wantUpdatedRows: 0, wantErr: true, - wantErrMsg: "iam.(Repository).update: db.DoTx: iam.(Repository).update: db.Update: getting update fields failed: common.UpdateFields: fieldMashPaths and setToNullPaths cannot intersect: parameter violation: error #100", + wantErrMsg: "fieldMashPaths and setToNullPaths cannot intersect: invalid parameter", }, { name: "only-field-masks", @@ -299,7 +301,7 @@ func TestRepository_update(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(tt.wantUpdatedRows, rowsUpdated) - assert.Equal(tt.wantErrMsg, err.Error()) + assert.Contains(err.Error(), tt.wantErrMsg) return } require.NoError(err) @@ -313,7 +315,7 @@ func TestRepository_update(t *testing.T) { for _, f := range tt.args.setToNullPaths { where = fmt.Sprintf("%s and %s is null", where, f) } - err = rw.LookupWhere(context.Background(), &foundResource, where, tt.args.resource.GetPublicId()) + err = rw.LookupWhere(context.Background(), &foundResource, where, []interface{}{tt.args.resource.GetPublicId()}) require.NoError(err) assert.Equal(tt.args.resource.GetPublicId(), foundResource.GetPublicId()) assert.Equal(tt.wantName, foundResource.GetName()) diff --git a/internal/iam/repository_user.go b/internal/iam/repository_user.go index f22e87758..284810e52 100644 --- a/internal/iam/repository_user.go +++ b/internal/iam/repository_user.go @@ -274,7 +274,7 @@ func (r *Repository) LookupUserWithLogin(ctx context.Context, accountId string, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - ticket, err := w.GetTicket(&acct) + ticket, err := w.GetTicket(ctx, &acct) if err != nil { return errors.Wrap(ctx, err, op) } @@ -354,7 +354,7 @@ func (r *Repository) getUserWithAccount(ctx context.Context, withAccountId strin defer rows.Close() u := AllocUser() if rows.Next() { - err = r.reader.ScanRows(rows, &u) + err = r.reader.ScanRows(ctx, rows, &u) if err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to scan rows for account %s", withAccountId))) } @@ -419,7 +419,7 @@ func (r *Repository) AddUserAccounts(ctx context.Context, userId string, userVer db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { - userTicket, err := w.GetTicket(user) + userTicket, err := w.GetTicket(ctx, user) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -498,7 +498,7 @@ func (r *Repository) DeleteUserAccounts(ctx context.Context, userId string, user db.StdRetryCnt, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { - userTicket, err := w.GetTicket(user) + userTicket, err := w.GetTicket(ctx, user) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -594,7 +594,7 @@ func (r *Repository) SetUserAccounts(ctx context.Context, userId string, userVer } return nil } - userTicket, err := w.GetTicket(user) + userTicket, err := w.GetTicket(ctx, user) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -814,7 +814,7 @@ func associationChanges(ctx context.Context, reader db.Reader, userId string, ac var changes []*change for rows.Next() { var chg change - if err := reader.ScanRows(rows, &chg); err != nil { + if err := reader.ScanRows(ctx, rows, &chg); err != nil { return nil, nil, errors.Wrap(ctx, err, op) } changes = append(changes, &chg) diff --git a/internal/iam/repository_user_test.go b/internal/iam/repository_user_test.go index 88d8c5240..b8e764925 100644 --- a/internal/iam/repository_user_test.go +++ b/internal/iam/repository_user_test.go @@ -260,7 +260,7 @@ func TestRepository_UpdateUser(t *testing.T) { }, wantErr: true, wantRowsUpdate: 0, - wantErrMsg: "iam.(Repository).UpdateUser: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "iam.(Repository).UpdateUser: db.Update: record not found, search issue: error #1100", wantIsErr: errors.RecordNotFound, }, { @@ -648,7 +648,7 @@ func TestRepository_ListUsers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("public_id != 'u_anon' and public_id != 'u_auth' and public_id != 'u_recovery'").Delete(iam.AllocUser()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { u := iam.AllocUser(); return &u }(), "public_id != 'u_anon' and public_id != 'u_auth' and public_id != 'u_recovery'") testUsers := []*iam.User{} wantUserInfo := map[string]userInfo{} for i := 0; i < tt.createCnt; i++ { @@ -693,7 +693,7 @@ func TestRepository_ListUsers_Multiple_Scopes(t *testing.T) { repo := iam.TestRepo(t, conn, wrapper) org, _ := iam.TestScopes(t, repo) - require.NoError(t, conn.Where("public_id != 'u_anon' and public_id != 'u_auth' and public_id != 'u_recovery'").Delete(iam.AllocUser()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := iam.AllocUser(); return &i }(), "public_id != 'u_anon' and public_id != 'u_auth' and public_id != 'u_recovery'") const numPerScope = 10 var total int = 3 // anon, auth, recovery @@ -902,7 +902,7 @@ func TestRepository_AssociateAccounts(t *testing.T) { user := iam.TestUser(t, repo, org.PublicId) createAccountsFn := func(prefix string) []string { - require.NoError(t, conn.Where("iam_user_id = ?", user.PublicId).Delete(allocAuthAccount()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocAuthAccount(); return &i }(), "iam_user_id = ?", user.PublicId) results := []string{} for i := 0; i < 5; i++ { authMethod := oidc.TestAuthMethod(t, conn, databaseWrapper, org.PublicId, oidc.ActivePrivateState, fmt.Sprintf("%s-alice-rp-%d", prefix, i), "fido", @@ -1072,7 +1072,7 @@ func TestRepository_DisassociateAccounts(t *testing.T) { user := iam.TestUser(t, repo, org.PublicId) createAccountsFn := func(prefix string) []string { - require.NoError(t, conn.Where("iam_user_id = ?", user.PublicId).Delete(allocAuthAccount()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { a := allocAuthAccount(); return &a }(), "iam_user_id = ?", user.PublicId) results := []string{} for i := 0; i < 1; i++ { authMethod := oidc.TestAuthMethod(t, conn, databaseWrapper, org.PublicId, oidc.ActivePrivateState, fmt.Sprintf("%s-alice-rp-%d", prefix, i), "fido", @@ -1220,7 +1220,7 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) { user := iam.TestUser(t, repo, org.PublicId) createAccountsFn := func(prefix string) []string { - require.NoError(t, conn.Where("iam_user_id = ?", user.PublicId).Delete(allocAuthAccount()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocAuthAccount(); return &i }(), "iam_user_id = ?", user.PublicId) results := []string{} for i := 0; i < 1; i++ { authMethod := oidc.TestAuthMethod(t, conn, databaseWrapper, org.PublicId, oidc.ActivePrivateState, fmt.Sprintf("%s-alice-rp-%d", prefix, i), "fido", @@ -1382,7 +1382,7 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("iam_user_id = ?", user.PublicId).Delete(allocAuthAccount()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { a := allocAuthAccount(); return &a }(), "iam_user_id = ?", user.PublicId) accountIds, changes := tt.args.accountIdsFn() sort.Strings(accountIds) diff --git a/internal/iam/resource.go b/internal/iam/resource.go index d110af7f4..02e90d06d 100644 --- a/internal/iam/resource.go +++ b/internal/iam/resource.go @@ -69,7 +69,7 @@ func LookupScope(ctx context.Context, reader db.Reader, resource ResourceWithSco } } var p Scope - if err := reader.LookupWhere(ctx, &p, "public_id = ?", resource.GetScopeId()); err != nil { + if err := reader.LookupWhere(ctx, &p, "public_id = ?", []interface{}{resource.GetScopeId()}); err != nil { return nil, errors.Wrap(ctx, err, op) } return &p, nil diff --git a/internal/iam/role_grant_test.go b/internal/iam/role_grant_test.go index 7e24eee99..7963f3868 100644 --- a/internal/iam/role_grant_test.go +++ b/internal/iam/role_grant_test.go @@ -86,7 +86,7 @@ func TestRoleGrant_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { a := allocRoleGrant(); return &a }(), "1=1") got, err := NewRoleGrant(tt.args.roleId, tt.args.grant, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -191,7 +191,8 @@ func TestRoleGrant_Delete(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocRoleGrant()).Error) + r := allocRoleGrant() + db.TestDeleteWhere(t, conn, &r, "1=1") rg, err := NewRoleGrant(projRole.PublicId, "id=a_bcde;actions=read,update") require.NoError(err) require.NoError(rw.Create(context.Background(), rg)) diff --git a/internal/iam/role_test.go b/internal/iam/role_test.go index 749f9da18..e2b695b56 100644 --- a/internal/iam/role_test.go +++ b/internal/iam/role_test.go @@ -169,7 +169,7 @@ func Test_RoleCreate(t *testing.T) { }(), }, wantErr: true, - wantErrMsg: "db.Create: iam.(Role).VetForWrite: iam.validateScopeForWrite: scope is not found: search issue: error #1100", + wantErrMsg: "iam.validateScopeForWrite: scope is not found: search issue: error #1100", }, } @@ -189,7 +189,7 @@ func Test_RoleCreate(t *testing.T) { err := w.Create(context.Background(), r) if tt.wantErr { require.Error(err) - assert.Equal(tt.wantErrMsg, err.Error()) + assert.Contains(err.Error(), tt.wantErrMsg) return } assert.NoError(err) @@ -251,7 +251,7 @@ func Test_RoleUpdate(t *testing.T) { scopeIdOverride: org.PublicId, }, wantErr: true, - wantErrMsg: "db.Update: iam.(Role).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", + wantErrMsg: "iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", }, { name: "proj-scope-id-not-in-mask", @@ -423,7 +423,7 @@ func Test_RoleUpdate(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, updatedRows) - assert.Equal(tt.wantErrMsg, err.Error()) + assert.Contains(err.Error(), tt.wantErrMsg) err = db.TestVerifyOplog(t, rw, role.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second)) require.Error(err) assert.Contains(err.Error(), "record not found") @@ -474,7 +474,7 @@ func Test_RoleUpdate(t *testing.T) { updatedRows, err := rw.Update(context.Background(), &updateRole, []string{"ScopeId"}, nil, db.WithSkipVetForWrite(true)) require.Error(err) assert.Equal(0, updatedRows) - assert.Equal("db.Update: immutable column: iam_role.scope_id: integrity violation: error #1003", err.Error()) + assert.Contains(err.Error(), "immutable column: iam_role.scope_id: integrity violation: error #1003") }) } diff --git a/internal/iam/scope.go b/internal/iam/scope.go index e173f3794..a2101ef37 100644 --- a/internal/iam/scope.go +++ b/internal/iam/scope.go @@ -185,11 +185,11 @@ func (s *Scope) GetScope(ctx context.Context, r db.Reader) (*Scope, error) { // for all scopes which are not global, and the global case was // handled at HANDLE_GLOBAL where := "public_id in (select parent_id from iam_scope where public_id = ?)" - if err := r.LookupWhere(ctx, &p, where, s.PublicId); err != nil { + if err := r.LookupWhere(ctx, &p, where, []interface{}{s.PublicId}); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup parent public id from public id")) } default: - if err := r.LookupWhere(ctx, &p, "public_id = ?", s.ParentId); err != nil { + if err := r.LookupWhere(ctx, &p, "public_id = ?", []interface{}{s.ParentId}); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup parent from public id")) } } diff --git a/internal/iam/user_test.go b/internal/iam/user_test.go index 8e00e4541..d58991ca6 100644 --- a/internal/iam/user_test.go +++ b/internal/iam/user_test.go @@ -123,7 +123,7 @@ func Test_UserCreate(t *testing.T) { user.PublicId = id err = w.Create(context.Background(), user) require.Error(err) - assert.Equal("db.Create: iam.(User).VetForWrite: iam.validateScopeForWrite: scope is not found: search issue: error #1100", err.Error()) + assert.Equal("db.Create: dbw.Create: error before write: iam.(User).VetForWrite: iam.validateScopeForWrite: scope is not found: search issue: error #1100", err.Error()) }) } @@ -170,7 +170,7 @@ func Test_UserUpdate(t *testing.T) { ScopeId: proj.PublicId, }, wantErr: true, - wantErrMsg: "db.Update: iam.(User).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", + wantErrMsg: "db.Update: dbw.Update: error before write: iam.(User).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100", }, { name: "proj-scope-id-not-in-mask", @@ -212,7 +212,7 @@ func Test_UserUpdate(t *testing.T) { dbOpts: []db.Option{db.WithSkipVetForWrite(true)}, }, wantErr: true, - wantErrMsg: `db.Update: immutable column: iam_user.scope_id: integrity violation: error #1003`, + wantErrMsg: "integrity violation: error #1003", }, } for _, tt := range tests { @@ -237,7 +237,7 @@ func Test_UserUpdate(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, updatedRows) - assert.Equal(tt.wantErrMsg, err.Error()) + assert.Contains(err.Error(), tt.wantErrMsg) return } require.NoError(err) diff --git a/internal/kms/audit_key_test.go b/internal/kms/audit_key_test.go index c6ab7f8c2..2037a4ae2 100644 --- a/internal/kms/audit_key_test.go +++ b/internal/kms/audit_key_test.go @@ -22,7 +22,7 @@ func TestAuditKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -60,7 +60,7 @@ func TestAuditKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocAuditKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") got, err := kms.NewAuditKey(testCtx, tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -91,9 +91,10 @@ func TestAuditKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocAuditKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") tests := []struct { name string @@ -154,7 +155,8 @@ func TestAuditKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestAuditKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -164,7 +166,7 @@ func TestAuditKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestAuditKey(t, conn, rk.PrivateId) diff --git a/internal/kms/audit_key_version_test.go b/internal/kms/audit_key_version_test.go index 80fd88a62..431f617d8 100644 --- a/internal/kms/audit_key_version_test.go +++ b/internal/kms/audit_key_version_test.go @@ -22,7 +22,7 @@ func TestAuditKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -90,7 +90,7 @@ func TestAuditKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocAuditKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") got, err := kms.NewAuditKeyVersion(testCtx, tt.args.AuditKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -123,12 +123,12 @@ func TestAuditKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestAuditKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocAuditKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -188,7 +188,7 @@ func TestAuditKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -202,7 +202,7 @@ func TestAuditKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/database_key_test.go b/internal/kms/database_key_test.go index 77eba15d6..340a562b7 100644 --- a/internal/kms/database_key_test.go +++ b/internal/kms/database_key_test.go @@ -21,7 +21,7 @@ func TestDatabaseKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -59,7 +59,7 @@ func TestDatabaseKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocDatabaseKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") got, err := kms.NewDatabaseKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -90,9 +90,9 @@ func TestDatabaseKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocDatabaseKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") tests := []struct { name string @@ -153,7 +153,7 @@ func TestDatabaseKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestDatabaseKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -163,7 +163,7 @@ func TestDatabaseKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestDatabaseKey(t, conn, rk.PrivateId) diff --git a/internal/kms/database_key_version_test.go b/internal/kms/database_key_version_test.go index bc43c5374..a879b6997 100644 --- a/internal/kms/database_key_version_test.go +++ b/internal/kms/database_key_version_test.go @@ -21,7 +21,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -89,7 +89,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocDatabaseKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") got, err := kms.NewDatabaseKeyVersion(tt.args.databaseKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -122,12 +122,12 @@ func TestDatabaseKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocDatabaseKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -187,7 +187,7 @@ func TestDatabaseKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -201,7 +201,7 @@ func TestDatabaseKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/immutable_fields_test.go b/internal/kms/immutable_fields_test.go index bc4528ae8..cbba96bd5 100644 --- a/internal/kms/immutable_fields_test.go +++ b/internal/kms/immutable_fields_test.go @@ -23,8 +23,8 @@ func TestOplogKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOplogKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -91,7 +91,7 @@ func TestOplogKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -189,8 +189,8 @@ func TestTokenKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocTokenKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -257,7 +257,7 @@ func TestTokenKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -355,8 +355,8 @@ func TestSessionKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocSessionKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -423,7 +423,7 @@ func TestSessionKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -521,8 +521,8 @@ func TestRootKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -609,7 +609,7 @@ func TestRootKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") new := kms.TestRootKey(t, conn, org.PublicId) tests := []struct { @@ -675,8 +675,8 @@ func TestDatabaseKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocDatabaseKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -743,7 +743,7 @@ func TestDatabaseKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -841,8 +841,8 @@ func TestOidcKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOidcKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -909,7 +909,7 @@ func TestOidcKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -1007,8 +1007,8 @@ func TestAuditKey_ImmutableFields(t *testing.T) { wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocAuditKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestAuditKey(t, conn, rk.PrivateId) @@ -1075,10 +1075,9 @@ func TestAuditKeyVersion_ImmutableFields(t *testing.T) { ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - conn.Debug(true) dk := kms.TestAuditKey(t, conn, rk.PrivateId) new := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")) diff --git a/internal/kms/kms_ext_test.go b/internal/kms/kms_ext_test.go index dcfe4acae..5cfa3b81a 100644 --- a/internal/kms/kms_ext_test.go +++ b/internal/kms/kms_ext_test.go @@ -170,7 +170,7 @@ func TestKms_ReconcileKeys(t *testing.T) { kms: kms.TestKms(t, conn, wrapper), reader: rand.Reader, setup: func() { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocAuditKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") }, wantErr: false, }, @@ -179,7 +179,7 @@ func TestKms_ReconcileKeys(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) // start with no keys... - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") _, err := kms.CreateKeysTx(context.Background(), rw, rw, wrapper, rand.Reader, scope.Global.String()) require.NoError(err) diff --git a/internal/kms/oidc_key_test.go b/internal/kms/oidc_key_test.go index 9117d63bd..00430a9aa 100644 --- a/internal/kms/oidc_key_test.go +++ b/internal/kms/oidc_key_test.go @@ -21,7 +21,7 @@ func TestOidcKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -59,7 +59,7 @@ func TestOidcKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOidcKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") got, err := kms.NewOidcKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -90,9 +90,9 @@ func TestOidcKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOidcKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") tests := []struct { name string @@ -153,7 +153,7 @@ func TestOidcKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestOidcKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -163,7 +163,7 @@ func TestOidcKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestOidcKey(t, conn, rk.PrivateId) diff --git a/internal/kms/oidc_key_version_test.go b/internal/kms/oidc_key_version_test.go index d1ad93e81..5fc6fd0d1 100644 --- a/internal/kms/oidc_key_version_test.go +++ b/internal/kms/oidc_key_version_test.go @@ -21,7 +21,7 @@ func TestOidcKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -89,7 +89,7 @@ func TestOidcKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOidcKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") got, err := kms.NewOidcKeyVersion(tt.args.OidcKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -122,12 +122,12 @@ func TestOidcKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOidcKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -187,7 +187,7 @@ func TestOidcKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -201,7 +201,7 @@ func TestOidcKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/oplog_key_test.go b/internal/kms/oplog_key_test.go index 852d20df0..e1a1048e2 100644 --- a/internal/kms/oplog_key_test.go +++ b/internal/kms/oplog_key_test.go @@ -21,7 +21,7 @@ func TestOplogKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -59,7 +59,7 @@ func TestOplogKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOplogKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") got, err := kms.NewOplogKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -90,9 +90,9 @@ func TestOplogKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOplogKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") tests := []struct { name string @@ -153,7 +153,7 @@ func TestOplogKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestOplogKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -163,7 +163,7 @@ func TestOplogKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestOplogKey(t, conn, rk.PrivateId) diff --git a/internal/kms/oplog_key_version_test.go b/internal/kms/oplog_key_version_test.go index d51864525..c4f413a3d 100644 --- a/internal/kms/oplog_key_version_test.go +++ b/internal/kms/oplog_key_version_test.go @@ -21,7 +21,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -89,7 +89,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOplogKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") got, err := kms.NewOplogKeyVersion(tt.args.oplogKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -122,12 +122,12 @@ func TestOplogKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) opk := kms.TestOplogKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocOplogKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -187,7 +187,7 @@ func TestOplogKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -201,7 +201,7 @@ func TestOplogKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/repository_audit_key_test.go b/internal/kms/repository_audit_key_test.go index 5ee2ccd4e..4397eaf69 100644 --- a/internal/kms/repository_audit_key_test.go +++ b/internal/kms/repository_audit_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateAuditKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteAuditKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -275,12 +275,12 @@ func TestRepository_ListAuditKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestAuditKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_audit_key_version_test.go b/internal/kms/repository_audit_key_version_test.go index 843c686d2..71078e13f 100644 --- a/internal/kms/repository_audit_key_version_test.go +++ b/internal/kms/repository_audit_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateAuditKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestAuditKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteAuditKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestAuditKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestAuditKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestAuditKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestAuditKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocAuditKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") testKeys := []*kms.AuditKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test audit key")) @@ -275,7 +275,7 @@ func TestRepository_ListAuditKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestAuditKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListAuditKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocAuditKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.AuditKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")) diff --git a/internal/kms/repository_database_key_test.go b/internal/kms/repository_database_key_test.go index 12eb6cb7f..9f260d4c7 100644 --- a/internal/kms/repository_database_key_test.go +++ b/internal/kms/repository_database_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateDatabaseKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteDatabaseKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -275,12 +275,12 @@ func TestRepository_ListDatabaseKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestDatabaseKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_database_key_version_test.go b/internal/kms/repository_database_key_version_test.go index e5babcece..9f1128bc5 100644 --- a/internal/kms/repository_database_key_version_test.go +++ b/internal/kms/repository_database_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteDatabaseKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestDatabaseKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestDatabaseKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocDatabaseKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") testKeys := []*kms.DatabaseKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test database key")) @@ -275,7 +275,7 @@ func TestRepository_ListDatabaseKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListDatabaseKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocDatabaseKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.DatabaseKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")) diff --git a/internal/kms/repository_oidc_key_test.go b/internal/kms/repository_oidc_key_test.go index ce5372789..74d8aabf9 100644 --- a/internal/kms/repository_oidc_key_test.go +++ b/internal/kms/repository_oidc_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateOidcKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteOidcKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -275,12 +275,12 @@ func TestRepository_ListOidcKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestOidcKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_oidc_key_version_test.go b/internal/kms/repository_oidc_key_version_test.go index 967dd45b2..22db8a0a2 100644 --- a/internal/kms/repository_oidc_key_version_test.go +++ b/internal/kms/repository_oidc_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateOidcKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteOidcKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestOidcKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestOidcKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOidcKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") testKeys := []*kms.OidcKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test oidc key")) @@ -275,7 +275,7 @@ func TestRepository_ListOidcKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOidcKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListOidcKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOidcKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.OidcKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oidc key")) diff --git a/internal/kms/repository_oplog_key_test.go b/internal/kms/repository_oplog_key_test.go index c585efd10..f65a1cf16 100644 --- a/internal/kms/repository_oplog_key_test.go +++ b/internal/kms/repository_oplog_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteOplogKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -275,12 +275,12 @@ func TestRepository_ListOplogKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestOplogKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_oplog_key_version_test.go b/internal/kms/repository_oplog_key_version_test.go index e6b47ecf6..120e25425 100644 --- a/internal/kms/repository_oplog_key_version_test.go +++ b/internal/kms/repository_oplog_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateOplogKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteOplogKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestOplogKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestOplogKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOplogKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); ; return &i }(), "1=1") testKeys := []*kms.OplogKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test oplog key")) @@ -275,7 +275,7 @@ func TestRepository_ListOplogKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListOplogKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocOplogKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.OplogKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oplog key")) diff --git a/internal/kms/repository_root_key_test.go b/internal/kms/repository_root_key_test.go index a14e44a28..21fd8a976 100644 --- a/internal/kms/repository_root_key_test.go +++ b/internal/kms/repository_root_key_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateRootKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") type args struct { scopeId string @@ -127,7 +127,7 @@ func TestRepository_DeleteRootKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") type args struct { key *kms.RootKey @@ -252,7 +252,7 @@ func TestRepository_ListRootKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { diff --git a/internal/kms/repository_root_key_version_test.go b/internal/kms/repository_root_key_version_test.go index ba7f4a366..c714dd610 100644 --- a/internal/kms/repository_root_key_version_test.go +++ b/internal/kms/repository_root_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateRootKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -110,7 +110,7 @@ func TestRepository_DeleteRootKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -200,7 +200,7 @@ func TestRepository_LatestRootKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) tests := []struct { @@ -243,7 +243,7 @@ func TestRepository_LatestRootKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") testKeys := []*kms.RootKeyVersion{} for i := 0; i < tt.createCnt; i++ { k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -273,7 +273,7 @@ func TestRepository_ListRootKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -344,7 +344,7 @@ func TestRepository_ListRootKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") testRootKeyVersions := []*kms.RootKeyVersion{} for i := 0; i < tt.createCnt; i++ { k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/repository_session_key_test.go b/internal/kms/repository_session_key_test.go index a8623dbb9..4fcd8adb5 100644 --- a/internal/kms/repository_session_key_test.go +++ b/internal/kms/repository_session_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteSessionKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -276,12 +276,12 @@ func TestRepository_ListSessionKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestSessionKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_session_key_version_test.go b/internal/kms/repository_session_key_version_test.go index 9b12404a2..434757541 100644 --- a/internal/kms/repository_session_key_version_test.go +++ b/internal/kms/repository_session_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateSessionKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) sk := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteSessionKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) sk := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestSessionKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) sk := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestSessionKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocSessionKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") testKeys := []*kms.SessionKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestSessionKeyVersion(t, conn, rkvWrapper, sk.PrivateId, []byte("test key")) @@ -275,7 +275,7 @@ func TestRepository_ListSessionKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) sk := kms.TestSessionKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListSessionKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocSessionKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.SessionKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestSessionKeyVersion(t, conn, rkvWrapper, sk.PrivateId, []byte("session key")) diff --git a/internal/kms/repository_test.go b/internal/kms/repository_test.go index 31090ca3e..d11b106fd 100644 --- a/internal/kms/repository_test.go +++ b/internal/kms/repository_test.go @@ -86,7 +86,7 @@ func TestCreateKeysTx(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") type args struct { ctx context.Context diff --git a/internal/kms/repository_token_key_test.go b/internal/kms/repository_token_key_test.go index 85841921e..e4c04c1b1 100644 --- a/internal/kms/repository_token_key_test.go +++ b/internal/kms/repository_token_key_test.go @@ -25,7 +25,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -149,7 +149,7 @@ func TestRepository_DeleteTokenKey(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -275,12 +275,12 @@ func TestRepository_ListTokenKeys(t *testing.T) { }, } for _, tt := range tests { - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) for i := 0; i < tt.createCnt; i++ { org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("scope_id in(?)", []interface{}{"global", org.PublicId, proj.PublicId}).Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) rk := kms.TestRootKey(t, conn, proj.PublicId) kms.TestTokenKey(t, conn, rk.PrivateId) require.NoError(err) diff --git a/internal/kms/repository_token_key_version_test.go b/internal/kms/repository_token_key_version_test.go index d2ae50bfb..6a9c761f1 100644 --- a/internal/kms/repository_token_key_version_test.go +++ b/internal/kms/repository_token_key_version_test.go @@ -24,7 +24,7 @@ func TestRepository_CreateTokenKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -111,7 +111,7 @@ func TestRepository_DeleteTokenKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -200,7 +200,7 @@ func TestRepository_LatestTokenKeyVersion(t *testing.T) { repo, err := kms.NewRepository(rw, rw) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -245,7 +245,7 @@ func TestRepository_LatestTokenKeyVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocTokenKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") testKeys := []*kms.TokenKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test key")) @@ -275,7 +275,7 @@ func TestRepository_ListTokenKeyVersions(t *testing.T) { repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) require.NoError(t, err) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -348,7 +348,7 @@ func TestRepository_ListTokenKeyVersions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocTokenKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") keyVersions := []*kms.TokenKeyVersion{} for i := 0; i < tt.createCnt; i++ { k := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("token key")) diff --git a/internal/kms/root_key_test.go b/internal/kms/root_key_test.go index e5f038357..d364cd627 100644 --- a/internal/kms/root_key_test.go +++ b/internal/kms/root_key_test.go @@ -68,7 +68,7 @@ func TestRootKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") got, err := kms.NewRootKey(tt.args.scopeId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -99,7 +99,7 @@ func TestRootKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") tests := []struct { name string @@ -160,7 +160,7 @@ func TestRootKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) cp := k.Clone() assert.True(proto.Equal(cp.(*kms.RootKey).RootKey, k.RootKey)) @@ -169,7 +169,7 @@ func TestRootKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) k2 := kms.TestRootKey(t, conn, org2.PublicId) diff --git a/internal/kms/root_key_version_test.go b/internal/kms/root_key_version_test.go index f77988657..36a2a6c1e 100644 --- a/internal/kms/root_key_version_test.go +++ b/internal/kms/root_key_version_test.go @@ -22,7 +22,7 @@ func TestRootKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rootKey := kms.TestRootKey(t, conn, org.PublicId) type args struct { rootId string @@ -72,7 +72,7 @@ func TestRootKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") got, err := kms.NewRootKeyVersion(tt.args.rootId, tt.args.key, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -106,7 +106,7 @@ func TestRootKeyVersion_Delete(t *testing.T) { wrapper := db.TestWrapper(t) rw := db.New(conn) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) tests := []struct { @@ -167,7 +167,7 @@ func TestRootKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) cp := k.Clone() @@ -176,7 +176,7 @@ func TestRootKeyVersion_Clone(t *testing.T) { t.Run("not-equal", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) k2, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/session_key_test.go b/internal/kms/session_key_test.go index 7fc0d9127..b5c5b8e95 100644 --- a/internal/kms/session_key_test.go +++ b/internal/kms/session_key_test.go @@ -21,7 +21,7 @@ func TestSessionKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -59,7 +59,7 @@ func TestSessionKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocSessionKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") got, err := kms.NewSessionKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -90,9 +90,9 @@ func TestSessionKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocSessionKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") tests := []struct { name string @@ -153,7 +153,7 @@ func TestSessionKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestSessionKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -163,7 +163,7 @@ func TestSessionKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestSessionKey(t, conn, rk.PrivateId) diff --git a/internal/kms/session_key_version_test.go b/internal/kms/session_key_version_test.go index 6567c66af..df75baceb 100644 --- a/internal/kms/session_key_version_test.go +++ b/internal/kms/session_key_version_test.go @@ -21,7 +21,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -89,7 +89,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocSessionKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") got, err := kms.NewSessionKeyVersion(tt.args.sessionKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -122,12 +122,12 @@ func TestSessionKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) tk := kms.TestSessionKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocSessionKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -187,7 +187,7 @@ func TestSessionKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -201,7 +201,7 @@ func TestSessionKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/kms/testing.go b/internal/kms/testing.go index 8f668a7b8..745888c76 100644 --- a/internal/kms/testing.go +++ b/internal/kms/testing.go @@ -13,8 +13,8 @@ import ( func TestRootKey(t *testing.T, conn *db.DB, scopeId string) *RootKey { t.Helper() require := require.New(t) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocRootKey(); return &i }(), "scope_id = ?", scopeId) rw := db.New(conn) - require.NoError(conn.Where("scope_id = ?", scopeId).Delete(AllocRootKey()).Error) k, err := NewRootKey(scopeId) require.NoError(err) id, err := newRootKeyId() @@ -64,7 +64,7 @@ func TestDatabaseKey(t *testing.T, conn *db.DB, rootKeyId string) *DatabaseKey { t.Helper() require := require.New(t) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocDatabaseKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocDatabaseKey(); return &i }(), "root_key_id = ?", rootKeyId) k, err := NewDatabaseKey(rootKeyId) require.NoError(err) id, err := newDatabaseKeyId() @@ -98,7 +98,7 @@ func TestOplogKey(t *testing.T, conn *db.DB, rootKeyId string) *OplogKey { t.Helper() require := require.New(t) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocOplogKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocOplogKey(); return &i }(), "root_key_id = ?", rootKeyId) k, err := NewOplogKey(rootKeyId) require.NoError(err) id, err := newOplogKeyId() @@ -131,8 +131,8 @@ func TestOplogKeyVersion(t *testing.T, conn *db.DB, rootKeyVersionWrapper wrappi func TestTokenKey(t *testing.T, conn *db.DB, rootKeyId string) *TokenKey { t.Helper() require := require.New(t) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocTokenKey(); return &i }(), "root_key_id = ?", rootKeyId) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocTokenKey()).Error) k, err := NewTokenKey(rootKeyId) require.NoError(err) id, err := newTokenKeyId() @@ -165,8 +165,8 @@ func TestTokenKeyVersion(t *testing.T, conn *db.DB, rootKeyVersionWrapper wrappi func TestSessionKey(t *testing.T, conn *db.DB, rootKeyId string) *SessionKey { t.Helper() require := require.New(t) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSessionKey(); return &i }(), "root_key_id = ?", rootKeyId) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocSessionKey()).Error) k, err := NewSessionKey(rootKeyId) require.NoError(err) id, err := newSessionKeyId() @@ -199,8 +199,8 @@ func TestSessionKeyVersion(t *testing.T, conn *db.DB, rootKeyVersionWrapper wrap func TestOidcKey(t *testing.T, conn *db.DB, rootKeyId string) *OidcKey { t.Helper() require := require.New(t) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocOidcKey(); return &i }(), "root_key_id = ?", rootKeyId) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocOidcKey()).Error) k, err := NewOidcKey(rootKeyId) require.NoError(err) id, err := newOidcKeyId() @@ -234,8 +234,8 @@ func TestAuditKey(t *testing.T, conn *db.DB, rootKeyId string) *AuditKey { t.Helper() ctx := context.Background() require := require.New(t) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocAuditKey(); return &i }(), "root_key_id = ?", rootKeyId) rw := db.New(conn) - require.NoError(conn.Where("root_key_id = ?", rootKeyId).Delete(AllocAuditKey()).Error) k, err := NewAuditKey(ctx, rootKeyId) require.NoError(err) id, err := newAuditKeyId(ctx) diff --git a/internal/kms/testing_test.go b/internal/kms/testing_test.go index dde5795dc..30ef305a2 100644 --- a/internal/kms/testing_test.go +++ b/internal/kms/testing_test.go @@ -15,7 +15,7 @@ func Test_TestRootKey(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) require.NotNil(k) assert.NotEmpty(k.PrivateId) @@ -26,7 +26,7 @@ func Test_TestRootKeyVersion(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) require.NotNil(k) @@ -38,7 +38,7 @@ func Test_TestDatabaseKey(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) require.NotNil(k) assert.NotEmpty(k.PrivateId) @@ -53,7 +53,7 @@ func Test_TestDatabaseKeyVersion(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") kmsWrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) @@ -67,7 +67,7 @@ func Test_TestOplogKey(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) require.NotNil(k) assert.NotEmpty(k.PrivateId) @@ -82,7 +82,7 @@ func Test_TestOplogKeyVersion(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") kmsWrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) opk := kms.TestOplogKey(t, conn, rk.PrivateId) @@ -96,7 +96,7 @@ func Test_TestTokenKey(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) require.NotNil(k) assert.NotEmpty(k.PrivateId) @@ -111,7 +111,7 @@ func Test_TestTokenKeyVersion(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") kmsWrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) tk := kms.TestTokenKey(t, conn, rk.PrivateId) @@ -125,7 +125,7 @@ func Test_TestSessionKey(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") k := kms.TestRootKey(t, conn, org.PublicId) require.NotNil(k) assert.NotEmpty(k.PrivateId) @@ -140,7 +140,7 @@ func Test_TestSessionKeyVersion(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") kmsWrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - require.NoError(conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) sk := kms.TestSessionKey(t, conn, rk.PrivateId) diff --git a/internal/kms/token_key_test.go b/internal/kms/token_key_test.go index 0aefbe1c4..9f1b8a4fa 100644 --- a/internal/kms/token_key_test.go +++ b/internal/kms/token_key_test.go @@ -21,7 +21,7 @@ func TestTokenKey_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) type args struct { @@ -59,7 +59,7 @@ func TestTokenKey_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocTokenKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") got, err := kms.NewTokenKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -90,9 +90,9 @@ func TestTokenKey_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocTokenKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") tests := []struct { name string @@ -153,7 +153,7 @@ func TestTokenKey_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) k := kms.TestTokenKey(t, conn, rk.PrivateId) cp := k.Clone() @@ -163,7 +163,7 @@ func TestTokenKey_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) k := kms.TestTokenKey(t, conn, rk.PrivateId) diff --git a/internal/kms/token_key_version_test.go b/internal/kms/token_key_version_test.go index dfa2c942b..6e02ed71d 100644 --- a/internal/kms/token_key_version_test.go +++ b/internal/kms/token_key_version_test.go @@ -21,7 +21,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -89,7 +89,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(kms.AllocTokenKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") got, err := kms.NewTokenKeyVersion(tt.args.tokenKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) @@ -122,12 +122,12 @@ func TestTokenKeyVersion_Delete(t *testing.T) { rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) tk := kms.TestTokenKey(t, conn, rk.PrivateId) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocTokenKeyVersion()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") tests := []struct { name string @@ -187,7 +187,7 @@ func TestTokenKeyVersion_Clone(t *testing.T) { t.Run("valid", func(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) @@ -201,7 +201,7 @@ func TestTokenKeyVersion_Clone(t *testing.T) { assert := assert.New(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") rk := kms.TestRootKey(t, conn, org.PublicId) rk2 := kms.TestRootKey(t, conn, org2.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) diff --git a/internal/oplog/any_operation.pb.go b/internal/oplog/any_operation.pb.go index 1824371fd..4bd79205a 100644 --- a/internal/oplog/any_operation.pb.go +++ b/internal/oplog/any_operation.pb.go @@ -10,6 +10,8 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" + structpb "google.golang.org/protobuf/types/known/structpb" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -34,6 +36,10 @@ const ( OpType_OP_TYPE_UPDATE OpType = 2 // OP_TYPE_DELETE defines a delete operation. OpType_OP_TYPE_DELETE OpType = 3 + // OP_TYPE_CREATE_ITEMS defines a create operation for multiple items. + OpType_OP_TYPE_CREATE_ITEMS OpType = 4 + // OP_TYPE_DELETE_ITEMS defines a delete operation for multiple items. + OpType_OP_TYPE_DELETE_ITEMS OpType = 5 ) // Enum value maps for OpType. @@ -43,12 +49,16 @@ var ( 1: "OP_TYPE_CREATE", 2: "OP_TYPE_UPDATE", 3: "OP_TYPE_DELETE", + 4: "OP_TYPE_CREATE_ITEMS", + 5: "OP_TYPE_DELETE_ITEMS", } OpType_value = map[string]int32{ - "OP_TYPE_UNSPECIFIED": 0, - "OP_TYPE_CREATE": 1, - "OP_TYPE_UPDATE": 2, - "OP_TYPE_DELETE": 3, + "OP_TYPE_UNSPECIFIED": 0, + "OP_TYPE_CREATE": 1, + "OP_TYPE_UPDATE": 2, + "OP_TYPE_DELETE": 3, + "OP_TYPE_CREATE_ITEMS": 4, + "OP_TYPE_DELETE_ITEMS": 5, } ) @@ -96,6 +106,9 @@ type AnyOperation struct { FieldMask *fieldmaskpb.FieldMask `protobuf:"bytes,4,opt,name=field_mask,json=fieldMask,proto3" json:"field_mask,omitempty"` // null_mask is the mask of fields to set to null. NullMask *fieldmaskpb.FieldMask `protobuf:"bytes,5,opt,name=null_mask,json=nullMask,proto3" json:"null_mask,omitempty"` + // Options for the operations (see dbw package for definition/documentation of + // options) + Options *OperationOptions `protobuf:"bytes,6,opt,name=options,proto3" json:"options,omitempty"` } func (x *AnyOperation) Reset() { @@ -165,6 +178,566 @@ func (x *AnyOperation) GetNullMask() *fieldmaskpb.FieldMask { return nil } +func (x *AnyOperation) GetOptions() *OperationOptions { + if x != nil { + return x.Options + } + return nil +} + +// OperationOptions represent operations options which can/will affect the oplog write +// operation. These options are a subset of the dbw.Options. We will not try to +// keep the docs in-sync from the dbw package, so if you need more information +// on what the option does please see the dbw package docs. +type OperationOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // with_version (see dbw package for docs) + WithVersion *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=with_version,json=withVersion,proto3" json:"with_version,omitempty"` + // with_skip_vet_for_write (see dbw package for docs) + WithSkipVetForWrite bool `protobuf:"varint,2,opt,name=with_skip_vet_for_write,json=withSkipVetForWrite,proto3" json:"with_skip_vet_for_write,omitempty"` + // with_where_clause (see dbw package for docs) + WithWhereClause string `protobuf:"bytes,3,opt,name=with_where_clause,json=withWhereClause,proto3" json:"with_where_clause,omitempty"` + // with_where_clause_args (see dbw package for docs) + WithWhereClauseArgs []*structpb.Value `protobuf:"bytes,4,rep,name=with_where_clause_args,json=withWhereClauseArgs,proto3" json:"with_where_clause_args,omitempty"` + // with_on_conflict (see dbw package for docs) + WithOnConflict *WithOnConflict `protobuf:"bytes,5,opt,name=with_on_conflict,json=withOnConflict,proto3" json:"with_on_conflict,omitempty"` +} + +func (x *OperationOptions) Reset() { + *x = OperationOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OperationOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OperationOptions) ProtoMessage() {} + +func (x *OperationOptions) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OperationOptions.ProtoReflect.Descriptor instead. +func (*OperationOptions) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{1} +} + +func (x *OperationOptions) GetWithVersion() *wrapperspb.UInt32Value { + if x != nil { + return x.WithVersion + } + return nil +} + +func (x *OperationOptions) GetWithSkipVetForWrite() bool { + if x != nil { + return x.WithSkipVetForWrite + } + return false +} + +func (x *OperationOptions) GetWithWhereClause() string { + if x != nil { + return x.WithWhereClause + } + return "" +} + +func (x *OperationOptions) GetWithWhereClauseArgs() []*structpb.Value { + if x != nil { + return x.WithWhereClauseArgs + } + return nil +} + +func (x *OperationOptions) GetWithOnConflict() *WithOnConflict { + if x != nil { + return x.WithOnConflict + } + return nil +} + +// WithOnConflict defines the parameters needed for an sql "on conflict clause" +type WithOnConflict struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // target defines the on conflict target + // + // Types that are assignable to Target: + // *WithOnConflict_Constraint + // *WithOnConflict_Columns + Target isWithOnConflict_Target `protobuf_oneof:"target"` + // action defines the on conflict action + // + // Types that are assignable to Action: + // *WithOnConflict_DoNothing + // *WithOnConflict_UpdateAll + // *WithOnConflict_ColumnValues + Action isWithOnConflict_Action `protobuf_oneof:"action"` +} + +func (x *WithOnConflict) Reset() { + *x = WithOnConflict{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithOnConflict) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithOnConflict) ProtoMessage() {} + +func (x *WithOnConflict) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WithOnConflict.ProtoReflect.Descriptor instead. +func (*WithOnConflict) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{2} +} + +func (m *WithOnConflict) GetTarget() isWithOnConflict_Target { + if m != nil { + return m.Target + } + return nil +} + +func (x *WithOnConflict) GetConstraint() string { + if x, ok := x.GetTarget().(*WithOnConflict_Constraint); ok { + return x.Constraint + } + return "" +} + +func (x *WithOnConflict) GetColumns() *Columns { + if x, ok := x.GetTarget().(*WithOnConflict_Columns); ok { + return x.Columns + } + return nil +} + +func (m *WithOnConflict) GetAction() isWithOnConflict_Action { + if m != nil { + return m.Action + } + return nil +} + +func (x *WithOnConflict) GetDoNothing() bool { + if x, ok := x.GetAction().(*WithOnConflict_DoNothing); ok { + return x.DoNothing + } + return false +} + +func (x *WithOnConflict) GetUpdateAll() bool { + if x, ok := x.GetAction().(*WithOnConflict_UpdateAll); ok { + return x.UpdateAll + } + return false +} + +func (x *WithOnConflict) GetColumnValues() *ColumnValues { + if x, ok := x.GetAction().(*WithOnConflict_ColumnValues); ok { + return x.ColumnValues + } + return nil +} + +type isWithOnConflict_Target interface { + isWithOnConflict_Target() +} + +type WithOnConflict_Constraint struct { + // constraint is the on conflict constraint + Constraint string `protobuf:"bytes,10,opt,name=constraint,proto3,oneof"` +} + +type WithOnConflict_Columns struct { + // columns are the on conflict columns + Columns *Columns `protobuf:"bytes,11,opt,name=columns,proto3,oneof"` +} + +func (*WithOnConflict_Constraint) isWithOnConflict_Target() {} + +func (*WithOnConflict_Columns) isWithOnConflict_Target() {} + +type isWithOnConflict_Action interface { + isWithOnConflict_Action() +} + +type WithOnConflict_DoNothing struct { + // do_nothing defines an on conflict action of do nothing + DoNothing bool `protobuf:"varint,50,opt,name=do_nothing,json=doNothing,proto3,oneof"` +} + +type WithOnConflict_UpdateAll struct { + // update_all defines an on conflict action of updating all the columns + UpdateAll bool `protobuf:"varint,51,opt,name=update_all,json=updateAll,proto3,oneof"` +} + +type WithOnConflict_ColumnValues struct { + // column_values defines on conflict action with the columns to update + ColumnValues *ColumnValues `protobuf:"bytes,52,opt,name=column_values,json=columnValues,proto3,oneof"` +} + +func (*WithOnConflict_DoNothing) isWithOnConflict_Action() {} + +func (*WithOnConflict_UpdateAll) isWithOnConflict_Action() {} + +func (*WithOnConflict_ColumnValues) isWithOnConflict_Action() {} + +// Columns defines a set of column properties +type Columns struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the columns + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` +} + +func (x *Columns) Reset() { + *x = Columns{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Columns) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Columns) ProtoMessage() {} + +func (x *Columns) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Columns.ProtoReflect.Descriptor instead. +func (*Columns) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{3} +} + +func (x *Columns) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +// ColumnValue defines a column value +type ColumnValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the column + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // value of the column + // + // Types that are assignable to Value: + // *ColumnValue_Raw + // *ColumnValue_ExprValue + // *ColumnValue_Column + Value isColumnValue_Value `protobuf_oneof:"value"` +} + +func (x *ColumnValue) Reset() { + *x = ColumnValue{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ColumnValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ColumnValue) ProtoMessage() {} + +func (x *ColumnValue) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ColumnValue.ProtoReflect.Descriptor instead. +func (*ColumnValue) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{4} +} + +func (x *ColumnValue) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (m *ColumnValue) GetValue() isColumnValue_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *ColumnValue) GetRaw() *structpb.Value { + if x, ok := x.GetValue().(*ColumnValue_Raw); ok { + return x.Raw + } + return nil +} + +func (x *ColumnValue) GetExprValue() *ExprValue { + if x, ok := x.GetValue().(*ColumnValue_ExprValue); ok { + return x.ExprValue + } + return nil +} + +func (x *ColumnValue) GetColumn() *Column { + if x, ok := x.GetValue().(*ColumnValue_Column); ok { + return x.Column + } + return nil +} + +type isColumnValue_Value interface { + isColumnValue_Value() +} + +type ColumnValue_Raw struct { + Raw *structpb.Value `protobuf:"bytes,2,opt,name=raw,proto3,oneof"` +} + +type ColumnValue_ExprValue struct { + ExprValue *ExprValue `protobuf:"bytes,3,opt,name=expr_value,json=exprValue,proto3,oneof"` +} + +type ColumnValue_Column struct { + Column *Column `protobuf:"bytes,4,opt,name=column,proto3,oneof"` +} + +func (*ColumnValue_Raw) isColumnValue_Value() {} + +func (*ColumnValue_ExprValue) isColumnValue_Value() {} + +func (*ColumnValue_Column) isColumnValue_Value() {} + +// ColumnValues defines a set of column value properies +type ColumnValues struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // values are the values of the columns + Values []*ColumnValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *ColumnValues) Reset() { + *x = ColumnValues{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ColumnValues) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ColumnValues) ProtoMessage() {} + +func (x *ColumnValues) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ColumnValues.ProtoReflect.Descriptor instead. +func (*ColumnValues) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{5} +} + +func (x *ColumnValues) GetValues() []*ColumnValue { + if x != nil { + return x.Values + } + return nil +} + +// ExprValue defines an expr value that can be used as a column value +type ExprValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sql is the sql clause of the expr + Sql string `protobuf:"bytes,1,opt,name=sql,proto3" json:"sql,omitempty"` + // args are the sql args of the expr + Args []*structpb.Value `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"` +} + +func (x *ExprValue) Reset() { + *x = ExprValue{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExprValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExprValue) ProtoMessage() {} + +func (x *ExprValue) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExprValue.ProtoReflect.Descriptor instead. +func (*ExprValue) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{6} +} + +func (x *ExprValue) GetSql() string { + if x != nil { + return x.Sql + } + return "" +} + +func (x *ExprValue) GetArgs() []*structpb.Value { + if x != nil { + return x.Args + } + return nil +} + +// Column represents a table Column +type Column struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name of the column + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // table name of the column + Table string `protobuf:"bytes,2,opt,name=table,proto3" json:"table,omitempty"` +} + +func (x *Column) Reset() { + *x = Column{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Column) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Column) ProtoMessage() {} + +func (x *Column) ProtoReflect() protoreflect.Message { + mi := &file_controller_storage_oplog_v1_any_operation_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Column.ProtoReflect.Descriptor instead. +func (*Column) Descriptor() ([]byte, []int) { + return file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP(), []int{7} +} + +func (x *Column) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Column) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + var File_controller_storage_oplog_v1_any_operation_proto protoreflect.FileDescriptor var file_controller_storage_oplog_v1_any_operation_proto_rawDesc = []byte{ @@ -175,33 +748,113 @@ var file_controller_storage_oplog_v1_any_operation_proto_rawDesc = []byte{ 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x81, 0x02, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, - 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a, 0x09, 0x6e, - 0x75, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x08, 0x6e, 0x75, 0x6c, 0x6c, - 0x4d, 0x61, 0x73, 0x6b, 0x2a, 0x5d, 0x0a, 0x06, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, - 0x0a, 0x13, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4f, - 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, - 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, - 0x45, 0x10, 0x03, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x70, - 0x6c, 0x6f, 0x67, 0x3b, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xca, + 0x02, 0x0a, 0x0c, 0x41, 0x6e, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, + 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x39, + 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x09, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a, 0x09, 0x6e, 0x75, 0x6c, + 0x6c, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x08, 0x6e, 0x75, 0x6c, 0x6c, 0x4d, 0x61, + 0x73, 0x6b, 0x12, 0x47, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd9, 0x02, 0x0a, 0x10, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x3f, 0x0a, 0x0c, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x34, 0x0a, 0x17, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, + 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x13, 0x77, 0x69, 0x74, 0x68, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x74, 0x46, + 0x6f, 0x72, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x77, 0x69, 0x74, 0x68, 0x5f, + 0x77, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x57, 0x68, 0x65, 0x72, 0x65, 0x43, 0x6c, 0x61, + 0x75, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x16, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x68, 0x65, 0x72, + 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x77, 0x69, 0x74, + 0x68, 0x57, 0x68, 0x65, 0x72, 0x65, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x41, 0x72, 0x67, 0x73, + 0x12, 0x55, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x6c, 0x69, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, + 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x4f, 0x6e, 0x43, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x0e, 0x77, 0x69, 0x74, 0x68, 0x4f, 0x6e, 0x43, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x22, 0x9c, 0x02, 0x0a, 0x0e, 0x57, 0x69, 0x74, 0x68, + 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x07, + 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x1f, + 0x0a, 0x0a, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x18, 0x32, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x01, 0x52, 0x09, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x12, + 0x1f, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x18, 0x33, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x6c, + 0x12, 0x50, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x48, 0x01, 0x52, 0x0c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x42, 0x08, 0x0a, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1f, 0x0a, 0x07, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xde, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x72, + 0x61, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x48, 0x00, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, 0x47, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x70, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x3d, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x42, + 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x50, 0x0a, 0x0c, 0x43, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, + 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x09, 0x45, 0x78, + 0x70, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x71, 0x6c, 0x12, 0x2a, 0x0a, 0x04, 0x61, 0x72, 0x67, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0x32, 0x0a, 0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2a, 0x91, 0x01, 0x0a, 0x06, 0x4f, 0x70, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, + 0x0e, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, + 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x50, 0x44, + 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x54, 0x45, 0x4d, + 0x53, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x49, 0x54, 0x45, 0x4d, 0x53, 0x10, 0x05, 0x42, 0x34, 0x5a, + 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x3b, 0x6f, 0x70, + 0x6c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -217,21 +870,41 @@ func file_controller_storage_oplog_v1_any_operation_proto_rawDescGZIP() []byte { } var file_controller_storage_oplog_v1_any_operation_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_controller_storage_oplog_v1_any_operation_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_controller_storage_oplog_v1_any_operation_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_controller_storage_oplog_v1_any_operation_proto_goTypes = []interface{}{ - (OpType)(0), // 0: controller.storage.oplog.v1.OpType - (*AnyOperation)(nil), // 1: controller.storage.oplog.v1.AnyOperation - (*fieldmaskpb.FieldMask)(nil), // 2: google.protobuf.FieldMask + (OpType)(0), // 0: controller.storage.oplog.v1.OpType + (*AnyOperation)(nil), // 1: controller.storage.oplog.v1.AnyOperation + (*OperationOptions)(nil), // 2: controller.storage.oplog.v1.OperationOptions + (*WithOnConflict)(nil), // 3: controller.storage.oplog.v1.WithOnConflict + (*Columns)(nil), // 4: controller.storage.oplog.v1.Columns + (*ColumnValue)(nil), // 5: controller.storage.oplog.v1.ColumnValue + (*ColumnValues)(nil), // 6: controller.storage.oplog.v1.ColumnValues + (*ExprValue)(nil), // 7: controller.storage.oplog.v1.ExprValue + (*Column)(nil), // 8: controller.storage.oplog.v1.Column + (*fieldmaskpb.FieldMask)(nil), // 9: google.protobuf.FieldMask + (*wrapperspb.UInt32Value)(nil), // 10: google.protobuf.UInt32Value + (*structpb.Value)(nil), // 11: google.protobuf.Value } var file_controller_storage_oplog_v1_any_operation_proto_depIdxs = []int32{ - 0, // 0: controller.storage.oplog.v1.AnyOperation.operation_type:type_name -> controller.storage.oplog.v1.OpType - 2, // 1: controller.storage.oplog.v1.AnyOperation.field_mask:type_name -> google.protobuf.FieldMask - 2, // 2: controller.storage.oplog.v1.AnyOperation.null_mask:type_name -> google.protobuf.FieldMask - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 0, // 0: controller.storage.oplog.v1.AnyOperation.operation_type:type_name -> controller.storage.oplog.v1.OpType + 9, // 1: controller.storage.oplog.v1.AnyOperation.field_mask:type_name -> google.protobuf.FieldMask + 9, // 2: controller.storage.oplog.v1.AnyOperation.null_mask:type_name -> google.protobuf.FieldMask + 2, // 3: controller.storage.oplog.v1.AnyOperation.options:type_name -> controller.storage.oplog.v1.OperationOptions + 10, // 4: controller.storage.oplog.v1.OperationOptions.with_version:type_name -> google.protobuf.UInt32Value + 11, // 5: controller.storage.oplog.v1.OperationOptions.with_where_clause_args:type_name -> google.protobuf.Value + 3, // 6: controller.storage.oplog.v1.OperationOptions.with_on_conflict:type_name -> controller.storage.oplog.v1.WithOnConflict + 4, // 7: controller.storage.oplog.v1.WithOnConflict.columns:type_name -> controller.storage.oplog.v1.Columns + 6, // 8: controller.storage.oplog.v1.WithOnConflict.column_values:type_name -> controller.storage.oplog.v1.ColumnValues + 11, // 9: controller.storage.oplog.v1.ColumnValue.raw:type_name -> google.protobuf.Value + 7, // 10: controller.storage.oplog.v1.ColumnValue.expr_value:type_name -> controller.storage.oplog.v1.ExprValue + 8, // 11: controller.storage.oplog.v1.ColumnValue.column:type_name -> controller.storage.oplog.v1.Column + 5, // 12: controller.storage.oplog.v1.ColumnValues.values:type_name -> controller.storage.oplog.v1.ColumnValue + 11, // 13: controller.storage.oplog.v1.ExprValue.args:type_name -> google.protobuf.Value + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_controller_storage_oplog_v1_any_operation_proto_init() } @@ -252,6 +925,102 @@ func file_controller_storage_oplog_v1_any_operation_proto_init() { return nil } } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OperationOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithOnConflict); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Columns); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ColumnValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ColumnValues); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExprValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Column); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*WithOnConflict_Constraint)(nil), + (*WithOnConflict_Columns)(nil), + (*WithOnConflict_DoNothing)(nil), + (*WithOnConflict_UpdateAll)(nil), + (*WithOnConflict_ColumnValues)(nil), + } + file_controller_storage_oplog_v1_any_operation_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*ColumnValue_Raw)(nil), + (*ColumnValue_ExprValue)(nil), + (*ColumnValue_Column)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -259,7 +1028,7 @@ func file_controller_storage_oplog_v1_any_operation_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_storage_oplog_v1_any_operation_proto_rawDesc, NumEnums: 1, - NumMessages: 1, + NumMessages: 8, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/oplog/docs.go b/internal/oplog/docs.go index b707f273f..461cafa4b 100644 --- a/internal/oplog/docs.go +++ b/internal/oplog/docs.go @@ -1,3 +1,4 @@ -// oplog is a package for writing operational log (oplog) entries for the purpose of replication and verification of the data stored in the Boundary RDBMS. -// please see README.md in this directory for more information. +// Package oplog is a package for writing operational log (oplog) entries for +// the purpose of replication and verification of the data stored in the +// Boundary RDBMS. please see README.md in this directory for more information. package oplog diff --git a/internal/oplog/immutable_fields_test.go b/internal/oplog/immutable_fields_test.go index ace4912b7..cec5811bd 100644 --- a/internal/oplog/immutable_fields_test.go +++ b/internal/oplog/immutable_fields_test.go @@ -9,17 +9,18 @@ import ( "github.com/hashicorp/boundary/internal/db/timestamp" "github.com/hashicorp/boundary/internal/oplog/oplog_test" "github.com/hashicorp/boundary/internal/oplog/store" + "github.com/hashicorp/go-dbw" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" ) func Test_ImmutableFields(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + testCtx := context.Background() + db := setup(t) cipherer := testWrapper(t) - writer := &GormWriter{db} + writer := &Writer{db} id := testId(t) u := oplog_test.TestUser{ Name: "foo-" + id, @@ -32,13 +33,14 @@ func Test_ImmutableFields(t *testing.T) { } t.Log(&u2) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(t, err) - ticket, err := ticketer.GetTicket("default") + ticket, err := ticketer.GetTicket(testCtx, "default") require.NoError(t, err) new, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -49,7 +51,7 @@ func Test_ImmutableFields(t *testing.T) { ticketer, ) require.NoError(t, err) - err = new.WriteEntryWith(context.Background(), writer, ticket, + err = new.WriteEntryWith(testCtx, writer, ticket, &Message{Message: &u, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, &Message{Message: &u2, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}) require.NoError(t, err) @@ -119,16 +121,13 @@ func Test_ImmutableFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := testCloneEntry(new) - err = db.First(orig).Error - require.NoError(err) + require.NoError(dbw.New(db).LookupBy(testCtx, orig)) - err := writer.Update(tt.update, tt.fieldMask, nil) + _, err := dbw.New(writer.DB).Update(testCtx, tt.update, tt.fieldMask, nil) require.Error(err) after := testCloneEntry(new) - err = db.First(&after).Error - require.NoError(err) - + require.NoError(dbw.New(db).LookupBy(testCtx, after)) assert.True(proto.Equal(orig, after)) }) } diff --git a/internal/oplog/oplog.go b/internal/oplog/oplog.go index aa6c0a2a1..f4d82a9e0 100644 --- a/internal/oplog/oplog.go +++ b/internal/oplog/oplog.go @@ -6,23 +6,31 @@ import ( "fmt" "io" + "github.com/golang/protobuf/ptypes/wrappers" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog/store" + "github.com/hashicorp/go-dbw" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/structwrapping" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/structpb" ) -// Version of oplog entries (among other things, it's used to manage upgrade compatibility when replicating) -const Version = "v1" +// Version of oplog entries (among other things, it's used to manage upgrade +// compatibility when replicating) +// v1: initial version +// v2: adds the new Message.Opts +const Version = "v2" -// Message wraps a proto.Message and adds a operation type (Create, Update, Delete) +// Message wraps a proto.Message with some other bits like operation type, +// paths and options. type Message struct { proto.Message TypeName string OpType OpType FieldMaskPaths []string SetToNullPaths []string + Opts []dbw.Option } // Entry represents an oplog entry @@ -36,7 +44,7 @@ type Entry struct { type Metadata map[string][]string // NewEntry creates a new Entry -func NewEntry(aggregateName string, metadata Metadata, cipherer wrapping.Wrapper, ticketer Ticketer) (*Entry, error) { +func NewEntry(ctx context.Context, aggregateName string, metadata Metadata, cipherer wrapping.Wrapper, ticketer Ticketer) (*Entry, error) { const op = "oplog.NewEntry" entry := Entry{ Entry: &store.Entry{ @@ -60,40 +68,40 @@ func NewEntry(aggregateName string, metadata Metadata, cipherer wrapping.Wrapper } entry.Metadata = storeMD } - if err := entry.validate(); err != nil { - return nil, errors.WrapDeprecated(err, op) + if err := entry.validate(ctx); err != nil { + return nil, errors.Wrap(ctx, err, op) } return &entry, nil } -func (e *Entry) validate() error { +func (e *Entry) validate(ctx context.Context) error { const op = "oplog.(Entry).validate" if e.Cipherer == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil cipherer") + return errors.New(ctx, errors.InvalidParameter, op, "nil cipherer") } if e.Ticketer == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil ticketer") + return errors.New(ctx, errors.InvalidParameter, op, "nil ticketer") } if e.Entry == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil entry") + return errors.New(ctx, errors.InvalidParameter, op, "nil entry") } if e.Entry.Version == "" { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing entry version") + return errors.New(ctx, errors.InvalidParameter, op, "missing entry version") } if e.Entry.AggregateName == "" { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing entry aggregate name") + return errors.New(ctx, errors.InvalidParameter, op, "missing entry aggregate name") } return nil } // UnmarshalData the data attribute from []byte (treated as a FIFO QueueBuffer) to a []proto.Message -func (e *Entry) UnmarshalData(types *TypeCatalog) ([]Message, error) { +func (e *Entry) UnmarshalData(ctx context.Context, types *TypeCatalog) ([]Message, error) { const op = "oplog.(Entry).UnmarshalData" if types == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "nil type catalog") + return nil, errors.New(ctx, errors.InvalidParameter, op, "nil type catalog") } if len(e.Data) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing data") + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing data") } msgs := []Message{} queue := Queue{ @@ -101,30 +109,200 @@ func (e *Entry) UnmarshalData(types *TypeCatalog) ([]Message, error) { Catalog: types, } for { - m, typ, fieldMaskPaths, nullPaths, err := queue.Remove() + item, err := queue.remove(ctx) if err == io.EOF { break } if err != nil { - return nil, errors.WrapDeprecated(err, op, errors.WithMsg("error removing item from queue")) + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error removing item from queue")) } - name, err := types.GetTypeName(m) + name, err := types.GetTypeName(ctx, item.msg) if err != nil { - return nil, errors.WrapDeprecated(err, op) + return nil, errors.Wrap(ctx, err, op) } - msgs = append(msgs, Message{Message: m, TypeName: name, OpType: typ, FieldMaskPaths: fieldMaskPaths, SetToNullPaths: nullPaths}) + dbwOpts, err := convertToDbwOpts(ctx, item.operationOptions) + if err != nil { + } + msgs = append(msgs, Message{ + Message: item.msg, + TypeName: name, + OpType: item.opType, + FieldMaskPaths: item.fieldMask, + SetToNullPaths: item.setToNullPaths, + Opts: dbwOpts, + }) } return msgs, nil } +func convertToDbwOpts(ctx context.Context, opts *OperationOptions) ([]dbw.Option, error) { + const op = "oplog.convertToDbwOpts" + if opts == nil { + return []dbw.Option{}, nil + } + dbwOpts := []dbw.Option{ + dbw.WithSkipVetForWrite(opts.GetWithSkipVetForWrite()), + } + if opts.GetWithVersion() != nil { + dbwOpts = append(dbwOpts, dbw.WithVersion(&opts.GetWithVersion().Value)) + } + if opts.GetWithOnConflict() != nil { + c := &dbw.OnConflict{} + + switch targetType := opts.GetWithOnConflict().GetTarget().(type) { + case *WithOnConflict_Columns: + c.Target = dbw.Columns(opts.GetWithOnConflict().GetColumns().GetNames()) + case *WithOnConflict_Constraint: + c.Target = dbw.Constraint(opts.GetWithOnConflict().GetConstraint()) + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a supported target type: %T", targetType)) + } + + switch actionType := opts.GetWithOnConflict().GetAction().(type) { + case *WithOnConflict_DoNothing: + c.Action = dbw.DoNothing(opts.GetWithOnConflict().GetDoNothing()) + case *WithOnConflict_UpdateAll: + c.Action = dbw.UpdateAll(opts.GetWithOnConflict().GetUpdateAll()) + case *WithOnConflict_ColumnValues: + cvAction := make([]dbw.ColumnValue, 0, len(actionType.ColumnValues.GetValues())) + for _, cv := range actionType.ColumnValues.GetValues() { + newColVal := dbw.ColumnValue{ + Column: cv.GetName(), + } + switch pbVal := cv.Value.(type) { + case *ColumnValue_Raw: + newColVal.Value = pbVal.Raw.AsInterface() + case *ColumnValue_ExprValue: + expr := dbw.ExprValue{ + Sql: pbVal.ExprValue.GetSql(), + } + args := make([]interface{}, 0, len(pbVal.ExprValue.GetArgs())) + for _, a := range pbVal.ExprValue.GetArgs() { + args = append(args, a.AsInterface()) + } + newColVal.Value = expr + case *ColumnValue_Column: + newColVal.Value = dbw.Column{ + Name: pbVal.Column.GetName(), + Table: pbVal.Column.GetTable(), + } + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a supported column value type: %T", pbVal)) + } + cvAction = append(cvAction, newColVal) + } + c.Action = cvAction + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a supported action type: %T", actionType)) + } + dbwOpts = append(dbwOpts, dbw.WithOnConflict(c)) + } + if opts.GetWithWhereClause() != "" { + sql := opts.GetWithWhereClause() + args := make([]interface{}, 0, len(opts.GetWithWhereClauseArgs())) + for _, a := range opts.GetWithWhereClauseArgs() { + args = append(args, a.AsInterface()) + } + dbwOpts = append(dbwOpts, dbw.WithWhere(sql, args...)) + + } + return dbwOpts, nil +} + +// convertFromDbwOpts converts dbw options to an OperationalOptions for an Entry +func convertFromDbwOpts(ctx context.Context, opts dbw.Options) (*OperationOptions, error) { + const op = "oplog.convertFromDbwOptions" + pbOpts := &OperationOptions{ + WithSkipVetForWrite: opts.WithSkipVetForWrite, + WithWhereClause: opts.WithWhereClause, + } + if opts.WithVersion != nil { + pbOpts.WithVersion = &wrappers.UInt32Value{Value: *opts.WithVersion} + } + + clauseValues := make([]*structpb.Value, 0, len(opts.WithWhereClauseArgs)) + for _, arg := range opts.WithWhereClauseArgs { + v, err := structpb.NewValue(arg) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + clauseValues = append(clauseValues, v) + } + pbOpts.WithWhereClauseArgs = clauseValues + + if opts.WithOnConflict != nil { + c := &WithOnConflict{} + switch target := opts.WithOnConflict.Target.(type) { + case dbw.Constraint: + c.Target = &WithOnConflict_Constraint{string(target)} + case dbw.Columns: + c.Target = &WithOnConflict_Columns{ + &Columns{ + Names: []string(target), + }, + } + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a supported target type: %T", target)) + } + switch action := opts.WithOnConflict.Action.(type) { + case dbw.DoNothing: + c.Action = &WithOnConflict_DoNothing{bool(action)} + case dbw.UpdateAll: + c.Action = &WithOnConflict_UpdateAll{bool(action)} + case []dbw.ColumnValue: + colVals := make([]*ColumnValue, 0, len(action)) + for _, cv := range action { + pbColVal := &ColumnValue{ + Name: cv.Column, + } + switch cvVal := cv.Value.(type) { + case dbw.ExprValue: + args := make([]*structpb.Value, 0, len(cvVal.Vars)) + for _, vv := range cvVal.Vars { + pbVar, err := structpb.NewValue(vv) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create expr arg")) + } + args = append(args, pbVar) + } + pbColVal.Value = &ColumnValue_ExprValue{&ExprValue{ + Sql: cvVal.Sql, + Args: args, + }} + case dbw.Column: + pbColVal.Value = &ColumnValue_Column{ + &Column{ + Name: cvVal.Name, + Table: cvVal.Table, + }, + } + default: + exprVal, err := structpb.NewValue(cv.Value) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create column value")) + } + pbColVal.Value = &ColumnValue_Raw{exprVal} + } + colVals = append(colVals, pbColVal) + } + c.Action = &WithOnConflict_ColumnValues{ColumnValues: &ColumnValues{Values: colVals}} + default: + return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("not a valid supported action: %T", action)) + } + + pbOpts.WithOnConflict = c + } + return pbOpts, nil +} + // WriteEntryWith the []proto.Message marshaled into the entry data as a FIFO QueueBuffer // if Cipherer != nil then the data is authentication encrypted -func (e *Entry) WriteEntryWith(ctx context.Context, tx Writer, ticket *store.Ticket, msgs ...*Message) error { +func (e *Entry) WriteEntryWith(ctx context.Context, tx *Writer, ticket *store.Ticket, msgs ...*Message) error { const op = "oplog.(Entry).WriteEntryWith" if tx == nil { return errors.New(ctx, errors.InvalidParameter, op, "nil writer") } - if err := e.validate(); err != nil { + if err := e.validate(ctx); err != nil { return errors.Wrap(ctx, err, op) } if ticket == nil { @@ -138,21 +316,22 @@ func (e *Entry) WriteEntryWith(ctx context.Context, tx Writer, ticket *store.Tic if m == nil { return errors.New(ctx, errors.InvalidParameter, op, "nil message") } - if err := queue.Add(m.Message, m.TypeName, m.OpType, WithFieldMaskPaths(m.FieldMaskPaths), WithSetToNullPaths(m.SetToNullPaths)); err != nil { + if err := queue.add(ctx, m.Message, m.TypeName, m.OpType, WithOperationOptions(m.Opts...), WithFieldMaskPaths(m.FieldMaskPaths), WithSetToNullPaths(m.SetToNullPaths)); err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("error adding message to queue")) } } e.Data = append(e.Data, queue.Bytes()...) if e.Cipherer != nil { - if err := e.EncryptData(ctx); err != nil { + if err := e.encryptData(ctx); err != nil { return errors.Wrap(ctx, err, op) } } - if err := tx.Create(e); err != nil { + rw := dbw.New(tx.DB) + if err := rw.Create(ctx, e); err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("error writing data to storage")) } - if err := e.Ticketer.Redeem(ticket); err != nil { + if err := e.Ticketer.Redeem(ctx, ticket); err != nil { return errors.Wrap(ctx, err, op) } return nil @@ -160,9 +339,9 @@ func (e *Entry) WriteEntryWith(ctx context.Context, tx Writer, ticket *store.Tic // Write the entry as is with whatever it has for e.Data marshaled into a FIFO QueueBuffer // Cipherer != nil then the data is authentication encrypted -func (e *Entry) Write(ctx context.Context, tx Writer, ticket *store.Ticket) error { +func (e *Entry) Write(ctx context.Context, tx *Writer, ticket *store.Ticket) error { const op = "oplog.(Entry).Write" - if err := e.validate(); err != nil { + if err := e.validate(ctx); err != nil { return errors.Wrap(ctx, err, op) } if ticket == nil { @@ -172,21 +351,22 @@ func (e *Entry) Write(ctx context.Context, tx Writer, ticket *store.Ticket) erro return errors.New(ctx, errors.InvalidParameter, op, "missing ticket version") } if e.Cipherer != nil { - if err := e.EncryptData(ctx); err != nil { + if err := e.encryptData(ctx); err != nil { return errors.Wrap(ctx, err, op) } } - if err := tx.Create(e); err != nil { + rw := dbw.New(tx.DB) + if err := rw.Create(ctx, e); err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("error writing data to storage")) } - if err := e.Ticketer.Redeem(ticket); err != nil { + if err := e.Ticketer.Redeem(ctx, ticket); err != nil { return errors.Wrap(ctx, err, op) } return nil } -// EncryptData the entry's data using its Cipherer (wrapping.Wrapper) -func (e *Entry) EncryptData(ctx context.Context) error { +// encryptData the entry's data using its Cipherer (wrapping.Wrapper) +func (e *Entry) encryptData(ctx context.Context) error { const op = "oplog.(Entry).EncryptData" // structwrapping doesn't support embedding, so we'll pass in the store.Entry directly if err := structwrapping.WrapStruct(ctx, e.Cipherer, e.Entry, nil); err != nil { @@ -207,9 +387,9 @@ func (e *Entry) DecryptData(ctx context.Context) error { // Replay provides the ability to replay an entry. you must initialize any new tables ending with the tableSuffix before // calling Replay, otherwise you'll get "a table doesn't exist" error. -func (e *Entry) Replay(ctx context.Context, tx Writer, types *TypeCatalog, tableSuffix string) error { +func (e *Entry) Replay(ctx context.Context, tx *Writer, types *TypeCatalog, tableSuffix string) error { const op = "oplog.(Entry).Replay" - msgs, err := e.UnmarshalData(types) + msgs, err := e.UnmarshalData(ctx, types) if err != nil { return errors.Wrap(ctx, err, op) } @@ -223,34 +403,62 @@ func (e *Entry) Replay(ctx context.Context, tx Writer, types *TypeCatalog, table /* how replay will be implemented for snapshots is still very much under discussion. - when we go to implement snapshots we may very well need to refactor this create table - choice... there are many issues with doing the "create" in this manner: + when we go to implement snapshots we may very well need to refactor + this create table choice... there are many issues with doing the + "create" in this manner: * the perms needed to create a table and possible security issues - * the fk references would be to the original tables, not the new replay tables. - It may be a better choice to just create separate schemas for replay named blue and green - since we need at min of two replay tables definitions. if we went with separate schemas they - could be create with a boundary cli cmd that had appropriate privs (reducing security issues) - and the separate schemas wouldn't have the fk reference issues mentioned above. + * the fk references would be to the original tables, not the new + replay tables. + * we need a way to create a replay table that contains the existing + named constraints. Currently, on conflicts using a constraint + target won't work. + It may be a better choice to just create separate schemas for replay + named blue and green since we need at min of two replay tables + definitions. if we went with separate schemas they could be create + with a boundary cli cmd that had appropriate privs (reducing + security issues) and the separate schemas wouldn't have the fk + reference issues mentioned above. + + */ replayTable := origTableName + tableSuffix - if !tx.hasTable(replayTable) { - if err := tx.createTableLike(origTableName, replayTable); err != nil { + hasTable, err := tx.hasTable(ctx, replayTable) + if err != nil { + return errors.Wrap(ctx, err, op) + } + if !hasTable { + if err := tx.createTableLike(ctx, origTableName, replayTable); err != nil { return errors.Wrap(ctx, err, op) } } + rw := dbw.New(tx.DB) - em.SetTableName(replayTable) + m.Opts = append(m.Opts, dbw.WithTable(replayTable)) switch m.OpType { case OpType_OP_TYPE_CREATE: - if err := tx.Create(m.Message); err != nil { + if err := rw.Create(ctx, m.Message, m.Opts...); err != nil { + return errors.Wrap(ctx, err, op) + } + case OpType_OP_TYPE_CREATE_ITEMS: + // TODO: jimlambrt 12/2021 -> while this will work for + // CreateItems(...) it's hardly efficient. We'll need to refactor + // oplog quite a bit to support a multi-message operation. + if err := rw.CreateItems(ctx, []interface{}{m.Message}, m.Opts...); err != nil { return errors.Wrap(ctx, err, op) } case OpType_OP_TYPE_UPDATE: - if err := tx.Update(m.Message, m.FieldMaskPaths, m.SetToNullPaths); err != nil { + if _, err := rw.Update(ctx, m.Message, m.FieldMaskPaths, m.SetToNullPaths, m.Opts...); err != nil { return errors.Wrap(ctx, err, op) } case OpType_OP_TYPE_DELETE: - if err := tx.Delete(m.Message); err != nil { + if _, err := rw.Delete(ctx, m.Message, m.Opts...); err != nil { + return errors.Wrap(ctx, err, op) + } + case OpType_OP_TYPE_DELETE_ITEMS: + // TODO: jimlambrt 12/2021 -> while this will work for + // DeleteItems(...) it's hardly efficient. We'll need to refactor + // oplog quite a bit to support a multi-message operation. + if _, err := rw.DeleteItems(ctx, []interface{}{m.Message}, m.Opts...); err != nil { return errors.Wrap(ctx, err, op) } default: diff --git a/internal/oplog/oplog_test.go b/internal/oplog/oplog_test.go index a022ccbf7..e5cd4d3ca 100644 --- a/internal/oplog/oplog_test.go +++ b/internal/oplog/oplog_test.go @@ -6,77 +6,40 @@ import ( "testing" dbassert "github.com/hashicorp/dbassert/gorm" + "github.com/hashicorp/go-dbw" "github.com/hashicorp/boundary/internal/oplog/oplog_test" "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" ) -// setup the tests (initialize the database one-time and intialized testDatabaseURL) -func setup(t *testing.T) (func() error, *gorm.DB) { - t.Helper() - require := require.New(t) - cleanup, url, err := testInitDbInDocker(t) - require.NoError(err) - 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{}) - 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) - defer testCleanup(t, cleanup, db) + db := setup(t) + testCtx := context.Background() t.Run("EncryptData/DecryptData/UnmarshalData", func(t *testing.T) { assert, require := assert.New(t), require.New(t) cipherer := testWrapper(t) // now let's us optimistic locking via a ticketing system for a serialized oplog - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(err) queue := Queue{Catalog: types} id := testId(t) user := testUser(t, db, "foo-"+id, "", "") - err = queue.Add(user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) l, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -89,26 +52,26 @@ func Test_BasicOplog(t *testing.T) { require.NoError(err) l.Data = queue.Bytes() - err = l.EncryptData(context.Background()) + err = l.encryptData(context.Background()) require.NoError(err) - err = db.Create(&l).Error + err = dbw.New(db).Create(testCtx, &l) require.NoError(err) assert.NotNil(l.CreateTime) assert.NotNil(l.UpdateTime) entryId := l.Id var foundEntry Entry - err = db.Where("id = ?", entryId).First(&foundEntry).Error + err = dbw.New(db).LookupWhere(testCtx, &foundEntry, "id = ?", []interface{}{entryId}) require.NoError(err) foundEntry.Cipherer = cipherer err = foundEntry.DecryptData(context.Background()) require.NoError(err) - foundUsers, err := foundEntry.UnmarshalData(types) + foundUsers, err := foundEntry.UnmarshalData(testCtx, types) require.NoError(err) assert.Equal(foundUsers[0].Message.(*oplog_test.TestUser).Name, user.Name) - foundUsers, err = foundEntry.UnmarshalData(types) + foundUsers, err = foundEntry.UnmarshalData(testCtx, types) require.NoError(err) assert.Equal(foundUsers[0].Message.(*oplog_test.TestUser).Name, user.Name) }) @@ -118,25 +81,24 @@ func Test_BasicOplog(t *testing.T) { cipherer := testWrapper(t) // now let's us optimistic locking via a ticketing system for a serialized oplog - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(err) queue := Queue{Catalog: types} id := testId(t) user := testUser(t, db, "foo-"+id, "", "") - - ticket, err := ticketer.GetTicket("default") + ticket, err := ticketer.GetTicket(testCtx, "default") require.NoError(err) - queue = Queue{} - err = queue.Add(user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -148,7 +110,7 @@ func Test_BasicOplog(t *testing.T) { ) require.NoError(err) newLogEntry.Data = queue.Bytes() - err = newLogEntry.Write(context.Background(), &GormWriter{db}, ticket) + err = newLogEntry.Write(context.Background(), &Writer{db}, ticket) require.NoError(err) assert.NotEmpty(newLogEntry.Id) }) @@ -156,16 +118,17 @@ func Test_BasicOplog(t *testing.T) { // Test_NewEntry provides some basic unit tests for NewEntry func Test_NewEntry(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) + testCtx := context.Background() t.Run("valid", func(t *testing.T) { require := require.New(t) cipherer := testWrapper(t) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) _, err = NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -180,10 +143,11 @@ func Test_NewEntry(t *testing.T) { t.Run("no metadata success", func(t *testing.T) { require := require.New(t) cipherer := testWrapper(t) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) _, err = NewEntry( + testCtx, "test-users", nil, cipherer, @@ -194,10 +158,11 @@ func Test_NewEntry(t *testing.T) { t.Run("no aggregateName", func(t *testing.T) { assert, require := assert.New(t), require.New(t) cipherer := testWrapper(t) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) _, err = NewEntry( + testCtx, "", Metadata{ "key-only": nil, @@ -212,10 +177,11 @@ func Test_NewEntry(t *testing.T) { }) t.Run("bad cipherer", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) _, err = NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -232,6 +198,7 @@ func Test_NewEntry(t *testing.T) { assert, require := assert.New(t), require.New(t) cipherer := testWrapper(t) _, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -247,16 +214,16 @@ func Test_NewEntry(t *testing.T) { } func Test_UnmarshalData(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) cipherer := testWrapper(t) + testCtx := context.Background() // now let's us optimistic locking via a ticketing system for a serialized oplog - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(t, err) - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(t, err) id := testId(t) @@ -268,9 +235,10 @@ func Test_UnmarshalData(t *testing.T) { user := oplog_test.TestUser{ Name: "foo-" + id, } - err = queue.Add(&user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, &user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) entry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -282,11 +250,11 @@ func Test_UnmarshalData(t *testing.T) { ) require.NoError(err) entry.Data = queue.Bytes() - marshaledUsers, err := entry.UnmarshalData(types) + marshaledUsers, err := entry.UnmarshalData(testCtx, types) require.NoError(err) assert.Equal(marshaledUsers[0].Message.(*oplog_test.TestUser).Name, user.Name) - take2marshaledUsers, err := entry.UnmarshalData(types) + take2marshaledUsers, err := entry.UnmarshalData(testCtx, types) require.NoError(err) assert.Equal(take2marshaledUsers[0].Message.(*oplog_test.TestUser).Name, user.Name) }) @@ -295,6 +263,7 @@ func Test_UnmarshalData(t *testing.T) { assert, require := assert.New(t), require.New(t) queue := Queue{Catalog: types} entry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -306,7 +275,7 @@ func Test_UnmarshalData(t *testing.T) { ) require.NoError(err) entry.Data = queue.Bytes() - _, err = entry.UnmarshalData(types) + _, err = entry.UnmarshalData(testCtx, types) require.Error(err) assert.Equal("oplog.(Entry).UnmarshalData: missing data: parameter violation: error #100", err.Error()) }) @@ -318,9 +287,10 @@ func Test_UnmarshalData(t *testing.T) { user := oplog_test.TestUser{ Name: "foo-" + id, } - err = queue.Add(&user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, &user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) entry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -331,7 +301,7 @@ func Test_UnmarshalData(t *testing.T) { ticketer, ) require.NoError(err) - _, err = entry.UnmarshalData(nil) + _, err = entry.UnmarshalData(testCtx, nil) require.Error(err) assert.Equal("oplog.(Entry).UnmarshalData: nil type catalog: parameter violation: error #100", err.Error()) }) @@ -343,9 +313,10 @@ func Test_UnmarshalData(t *testing.T) { user := oplog_test.TestUser{ Name: "foo-" + id, } - err = queue.Add(&user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, &user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) entry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -357,9 +328,9 @@ func Test_UnmarshalData(t *testing.T) { ) require.NoError(err) entry.Data = queue.Bytes() - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "not-valid-name"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "not-valid-name"}) require.NoError(err) - _, err = entry.UnmarshalData(types) + _, err = entry.UnmarshalData(testCtx, types) require.Error(err) assert.Equal("oplog.(Entry).UnmarshalData: error removing item from queue: oplog.(Queue).Remove: error getting the TypeName: user: oplog.(TypeCatalog).Get: type name not found: integrity violation: error #105", err.Error()) }) @@ -367,29 +338,30 @@ func Test_UnmarshalData(t *testing.T) { // Test_Replay provides some basic unit tests for replaying entries func Test_Replay(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) + testCtx := context.Background() cipherer := testWrapper(t) id := testId(t) // setup new tables for replay tableSuffix := "_" + id - writer := GormWriter{Tx: db} + writer := Writer{db} userModel := &oplog_test.TestUser{} replayUserTable := fmt.Sprintf("%s%s", userModel.TableName(), tableSuffix) - defer func() { require.NoError(t, writer.dropTableIfExists(replayUserTable)) }() + defer func() { require.NoError(t, writer.dropTableIfExists(testCtx, replayUserTable)) }() - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(t, err) - t.Run("replay:create/update", func(t *testing.T) { + t.Run("replay:create/update/createitems", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - ticket, err := ticketer.GetTicket("default") + ticket, err := ticketer.GetTicket(testCtx, "default") require.NoError(err) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -401,7 +373,7 @@ func Test_Replay(t *testing.T) { ) require.NoError(err) - tx := db + tx := dbw.New(db) loginName := "foo-" + testId(t) userCreate := testUser(t, db, loginName, "", "") userSave := oplog_test.TestUser{ @@ -409,51 +381,62 @@ func Test_Replay(t *testing.T) { Name: userCreate.Name, Email: loginName + "@hashicorp.com", } - err = tx.Save(&userSave).Error + version := uint32(1) + rowsUpdated, err := tx.Update(testCtx, &userSave, []string{"Email"}, nil, dbw.WithVersion(&version), dbw.WithWhere("name = ?", loginName)) require.NoError(err) + require.Equal(1, rowsUpdated) userUpdate := oplog_test.TestUser{ - Id: userCreate.Id, + Id: userCreate.Id, + PhoneNumber: "867-5309", } - err = tx.Model(&userUpdate).Updates(map[string]interface{}{"PhoneNumber": "867-5309", "Name": gorm.Expr("NULL")}).Error + + tx.Update(testCtx, &userUpdate, []string{"PhoneNumber"}, []string{"Name"}) require.NoError(err) - underlyingDB, err := tx.DB() + underlyingDB, err := tx.DB().SqlDB(testCtx) require.NoError(err) - dbassert := dbassert.New(t, underlyingDB, tx.Dialector.Name()) + _, dialectName, err := tx.DB().DbType() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB, dialectName) dbassert.IsNull(&userUpdate, "Name") - foundCreateUser := testFindUser(t, tx, userCreate.Id) + foundCreateUser := testFindUser(t, tx.DB(), userCreate.Id) require.Equal(foundCreateUser.Id, userCreate.Id) require.Equal(foundCreateUser.Name, "") require.Equal(foundCreateUser.PhoneNumber, userUpdate.PhoneNumber) - err = newLogEntry.WriteEntryWith(context.Background(), &GormWriter{tx}, ticket, + userCreateItems := &oplog_test.TestUser{ + Name: "foo-" + testId(t), + } + require.NoError(dbw.New(db).CreateItems(context.Background(), []interface{}{userCreateItems})) + + err = newLogEntry.WriteEntryWith(context.Background(), &Writer{tx.DB()}, ticket, &Message{Message: userCreate, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, - &Message{Message: &userSave, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, FieldMaskPaths: []string{"Name", "Email"}}, + &Message{Message: &userSave, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, FieldMaskPaths: []string{"Email"}, SetToNullPaths: nil, Opts: []dbw.Option{dbw.WithVersion(&version), dbw.WithWhere("name = ?", loginName)}}, &Message{Message: &userSave, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, FieldMaskPaths: []string{"Name", "Email"}, SetToNullPaths: nil}, &Message{Message: &userUpdate, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, SetToNullPaths: []string{"Name"}}, &Message{Message: &userUpdate, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, FieldMaskPaths: nil, SetToNullPaths: []string{"Name"}}, &Message{Message: &userUpdate, TypeName: "user", OpType: OpType_OP_TYPE_UPDATE, FieldMaskPaths: []string{"PhoneNumber"}, SetToNullPaths: []string{"Name"}}, + &Message{Message: userCreateItems, TypeName: "user", OpType: OpType_OP_TYPE_CREATE_ITEMS}, ) require.NoError(err) - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(err) var foundEntry Entry - err = tx.Where("id = ?", newLogEntry.Id).First(&foundEntry).Error - require.NoError(err) + require.NoError(tx.LookupWhere(testCtx, &foundEntry, "id = ?", []interface{}{newLogEntry.Id})) foundEntry.Cipherer = cipherer err = foundEntry.DecryptData(context.Background()) require.NoError(err) - err = foundEntry.Replay(context.Background(), &GormWriter{tx}, types, tableSuffix) + err = foundEntry.Replay(context.Background(), &Writer{tx.DB()}, types, tableSuffix) require.NoError(err) - foundUser := testFindUser(t, tx, userCreate.Id) + foundUser := testFindUser(t, tx.DB(), userCreate.Id) var foundReplayedUser oplog_test.TestUser foundReplayedUser.Table = foundReplayedUser.TableName() + tableSuffix - err = tx.Where("id = ?", userCreate.Id).First(&foundReplayedUser).Error + require.NoError(tx.LookupWhere(testCtx, &foundReplayedUser, "id = ?", []interface{}{userCreate.Id})) require.NoError(err) assert.Equal(foundUser.Id, foundReplayedUser.Id) @@ -462,15 +445,20 @@ func Test_Replay(t *testing.T) { assert.Equal(foundReplayedUser.PhoneNumber, "867-5309") assert.Equal(foundUser.Email, foundReplayedUser.Email) assert.Equal(foundReplayedUser.Email, loginName+"@hashicorp.com") + + foundReplayedUser.Id = 0 + require.NoError(tx.LookupWhere(testCtx, &foundReplayedUser, "id = ?", []interface{}{userCreateItems.Id}, dbw.WithDebug(true))) + require.NoError(err) }) t.Run("replay:delete", func(t *testing.T) { assert, require := assert.New(t), require.New(t) // we need to test delete replays now... - tx2 := db.Begin() - defer tx2.Commit() + tx2, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx2.Commit(testCtx) - ticket2, err := ticketer.GetTicket("default") + ticket2, err := ticketer.GetTicket(testCtx, "default") require.NoError(err) id4 := testId(t) @@ -479,16 +467,17 @@ func Test_Replay(t *testing.T) { userCreate2 := oplog_test.TestUser{ Name: loginName2, } - err = tx2.Create(&userCreate2).Error + err = tx2.Create(testCtx, &userCreate2) require.NoError(err) deleteUser2 := oplog_test.TestUser{ Id: userCreate2.Id, } - err = tx2.Delete(&deleteUser2).Error + _, err = tx2.Delete(testCtx, &deleteUser2) require.NoError(err) newLogEntry2, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -499,39 +488,103 @@ func Test_Replay(t *testing.T) { ticketer, ) require.NoError(err) - err = newLogEntry2.WriteEntryWith(context.Background(), &GormWriter{tx2}, ticket2, + err = newLogEntry2.WriteEntryWith(context.Background(), &Writer{tx2.DB()}, ticket2, &Message{Message: &userCreate2, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, &Message{Message: &deleteUser2, TypeName: "user", OpType: OpType_OP_TYPE_DELETE}, ) require.NoError(err) var foundEntry2 Entry - err = tx2.Where("id = ?", newLogEntry2.Id).First(&foundEntry2).Error + err = tx2.LookupWhere(testCtx, &foundEntry2, "id = ?", []interface{}{newLogEntry2.Id}) require.NoError(err) foundEntry2.Cipherer = cipherer err = foundEntry2.DecryptData(context.Background()) require.NoError(err) - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(err) - err = foundEntry2.Replay(context.Background(), &GormWriter{tx2}, types, tableSuffix) + err = foundEntry2.Replay(context.Background(), &Writer{tx2.DB()}, types, tableSuffix) require.NoError(err) var foundUser2 oplog_test.TestUser - err = tx2.Where("id = ?", userCreate2.Id).First(&foundUser2).Error - assert.Equal(gorm.ErrRecordNotFound, err, err.Error()) + err = tx2.LookupWhere(testCtx, &foundUser2, "id = ?", []interface{}{userCreate2.Id}) + assert.ErrorIs(err, dbw.ErrRecordNotFound) var foundReplayedUser2 oplog_test.TestUser - err = tx2.Where("id = ?", userCreate2.Id).First(&foundReplayedUser2).Error - assert.Equal(gorm.ErrRecordNotFound, err, err.Error()) + err = tx2.LookupWhere(testCtx, &foundReplayedUser2, "id = ?", []interface{}{userCreate2.Id}) + assert.ErrorIs(err, dbw.ErrRecordNotFound) + }) + t.Run("replay:deleteitems", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + // we need to test delete replays now... + tx2, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx2.Commit(testCtx) + + ticket2, err := ticketer.GetTicket(testCtx, "default") + require.NoError(err) + + id4 := testId(t) + loginName2 := "foo-" + id4 + // create a user that's replayable + userCreate2 := oplog_test.TestUser{ + Name: loginName2, + } + err = tx2.Create(testCtx, &userCreate2) + require.NoError(err) + + deleteUser2 := oplog_test.TestUser{ + Id: userCreate2.Id, + } + _, err = tx2.DeleteItems(testCtx, []interface{}{&deleteUser2}) + require.NoError(err) + + newLogEntry2, err := NewEntry( + testCtx, + "test-users", + Metadata{ + "key-only": nil, + "deployment": []string{"amex"}, + "project": []string{"central-info-systems", "local-info-systems"}, + }, + cipherer, + ticketer, + ) + require.NoError(err) + err = newLogEntry2.WriteEntryWith(context.Background(), &Writer{tx2.DB()}, ticket2, + &Message{Message: &userCreate2, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, + &Message{Message: &deleteUser2, TypeName: "user", OpType: OpType_OP_TYPE_DELETE_ITEMS}, + ) + require.NoError(err) + + var foundEntry2 Entry + err = tx2.LookupWhere(testCtx, &foundEntry2, "id = ?", []interface{}{newLogEntry2.Id}) + require.NoError(err) + foundEntry2.Cipherer = cipherer + err = foundEntry2.DecryptData(context.Background()) + require.NoError(err) + + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) + require.NoError(err) + + err = foundEntry2.Replay(context.Background(), &Writer{tx2.DB()}, types, tableSuffix) + require.NoError(err) + + var foundUser2 oplog_test.TestUser + err = tx2.LookupWhere(testCtx, &foundUser2, "id = ?", []interface{}{userCreate2.Id}) + assert.ErrorIs(err, dbw.ErrRecordNotFound) + + var foundReplayedUser2 oplog_test.TestUser + err = tx2.LookupWhere(testCtx, &foundReplayedUser2, "id = ?", []interface{}{userCreate2.Id}) + assert.ErrorIs(err, dbw.ErrRecordNotFound) }) } // Test_WriteEntryWith provides unit tests for oplog.WriteEntryWith func Test_WriteEntryWith(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) + testCtx := context.Background() cipherer := testWrapper(t) id := testId(t) @@ -546,15 +599,16 @@ func Test_WriteEntryWith(t *testing.T) { } t.Log(&u2) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(t, err) - ticket, err := ticketer.GetTicket("default") + ticket, err := ticketer.GetTicket(testCtx, "default") require.NoError(t, err) t.Run("successful", func(t *testing.T) { assert, require := assert.New(t), require.New(t) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -565,26 +619,27 @@ func Test_WriteEntryWith(t *testing.T) { ticketer, ) require.NoError(err) - err = newLogEntry.WriteEntryWith(context.Background(), &GormWriter{db}, ticket, + err = newLogEntry.WriteEntryWith(context.Background(), &Writer{db}, ticket, &Message{Message: &u, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, &Message{Message: &u2, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}) require.NoError(err) var foundEntry Entry - err = db.Where("id = ?", newLogEntry.Id).First(&foundEntry).Error + require.NoError(dbw.New(db).LookupWhere(testCtx, &foundEntry, "id = ?", []interface{}{newLogEntry.Id})) require.NoError(err) foundEntry.Cipherer = cipherer - types, err := NewTypeCatalog(Type{new(oplog_test.TestUser), "user"}) + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) require.NoError(err) err = foundEntry.DecryptData(context.Background()) require.NoError(err) - foundUsers, err := foundEntry.UnmarshalData(types) + foundUsers, err := foundEntry.UnmarshalData(testCtx, types) require.NoError(err) assert.Equal(foundUsers[0].Message.(*oplog_test.TestUser).Name, u.Name) }) t.Run("nil writer", func(t *testing.T) { assert, require := assert.New(t), require.New(t) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -604,6 +659,7 @@ func Test_WriteEntryWith(t *testing.T) { t.Run("nil ticket", func(t *testing.T) { assert, require := assert.New(t), require.New(t) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -614,7 +670,7 @@ func Test_WriteEntryWith(t *testing.T) { ticketer, ) require.NoError(err) - err = newLogEntry.WriteEntryWith(context.Background(), &GormWriter{db}, nil, + err = newLogEntry.WriteEntryWith(context.Background(), &Writer{db}, nil, &Message{Message: &u, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}, &Message{Message: &u2, TypeName: "user", OpType: OpType_OP_TYPE_CREATE}) require.Error(err) @@ -623,6 +679,7 @@ func Test_WriteEntryWith(t *testing.T) { t.Run("nil ticket", func(t *testing.T) { assert, require := assert.New(t), require.New(t) newLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -633,38 +690,255 @@ func Test_WriteEntryWith(t *testing.T) { ticketer, ) require.NoError(err) - err = newLogEntry.WriteEntryWith(context.Background(), &GormWriter{db}, ticket, nil) + err = newLogEntry.WriteEntryWith(context.Background(), &Writer{db}, ticket, nil) require.Error(err) assert.Equal("oplog.(Entry).WriteEntryWith: nil message: parameter violation: error #100", err.Error()) }) } +func TestEntry_WriteEntryWith(t *testing.T) { + testCtx := context.Background() + db := setup(t) + cipherer := testWrapper(t) + db.Debug(true) + + // setup new tables for replay + id := testId(t) + tableSuffix := "_" + id + + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) + require.NoError(t, err) + + newEntryFn := func() *Entry { + testEntry, err := NewEntry( + testCtx, + "test-users", + Metadata{ + "key-only": nil, + "deployment": []string{"amex"}, + "project": []string{"central-info-systems", "local-info-systems"}, + }, + cipherer, + ticketer, + ) + require.NoError(t, err) + return testEntry + } + + tests := []struct { + name string + e *Entry + w *Writer + msg *Message + wantErr bool + wantErrContains string + }{ + { + name: "on-conflict-columns-do-nothing", + e: newEntryFn(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + Opts: []dbw.Option{ + dbw.WithOnConflict(&dbw.OnConflict{ + Target: dbw.Columns{"name"}, + Action: dbw.DoNothing(true), + }), + }, + }, + }, + { + name: "on-conflict-columns-update-all", + e: newEntryFn(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + Opts: []dbw.Option{ + dbw.WithOnConflict(&dbw.OnConflict{ + Target: dbw.Columns{"name"}, + Action: dbw.UpdateAll(true), + }), + }, + }, + }, + { + name: "on-conflict-columns-set-col-value-with-expr", + e: newEntryFn(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + Opts: []dbw.Option{ + dbw.WithOnConflict(&dbw.OnConflict{ + Target: dbw.Columns{"name"}, + Action: dbw.SetColumnValues(map[string]interface{}{"name": dbw.Expr("NULL")}), + }), + }, + }, + }, + { + name: "on-conflict-columns-set-col-value", + e: newEntryFn(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + Opts: []dbw.Option{ + dbw.WithOnConflict(&dbw.OnConflict{ + Target: dbw.Columns{"name"}, + Action: dbw.SetColumnValues(map[string]interface{}{"name": testId(t)}), + }), + }, + }, + }, + { + name: "on-conflict-columns-set-col-value", + e: newEntryFn(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + Opts: []dbw.Option{ + dbw.WithOnConflict(&dbw.OnConflict{ + Target: dbw.Columns{"name"}, + Action: dbw.SetColumns([]string{"email"}), + }), + }, + }, + }, + { + name: "missing-entry", + e: func() *Entry { e := newEntryFn(); e.Entry = nil; return e }(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + }, + wantErr: true, + wantErrContains: "nil entry", + }, + { + name: "missing-entry-version", + e: func() *Entry { e := newEntryFn(); e.Entry.Version = ""; return e }(), + w: &Writer{db}, + msg: &Message{ + Message: testUser(t, db, "foo-"+testId(t), "", ""), + TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + }, + wantErr: true, + wantErrContains: "missing entry version", + }, + // TODO: jimlambrt (Dec 2021) - we need a way to create a replay table + // that contains the existing named constraints. Once that done, we can + // enable this test and write more. This is just an example of the type + // test we need to create using a constraint target + // { + // name: "on-conflict-column-value", + // e: testEntry, + // w: &Writer{db}, + // msg: &Message{ + // Message: testUser(t, db, "foo-"+testId(t), "", ""), + // TypeName: "user", OpType: OpType_OP_TYPE_CREATE, + // Opts: []dbw.Option{ + // dbw.WithOnConflict(&dbw.OnConflict{ + // Target: dbw.Constraint{"oplog_test_user_name_uq"}, + // Action: dbw.SetColumnValues(map[string]interface{}{"name": dbw.Expr("NULL")}), + // })}, + // }, + // }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + ticket, err := ticketer.GetTicket(testCtx, "default") + require.NoError(err) + err = tt.e.WriteEntryWith( + testCtx, + tt.w, + ticket, + tt.msg, + ) + if tt.wantErr { + require.Error(err) + if tt.wantErrContains != "" { + assert.Contains(err.Error(), tt.wantErrContains) + } + return + } + require.NoError(err) + var foundEntry Entry + require.NoError(dbw.New(db).LookupWhere(testCtx, &foundEntry, "id = ?", []interface{}{tt.e.Id})) + require.NoError(err) + foundEntry.Cipherer = cipherer + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}) + require.NoError(err) + err = foundEntry.DecryptData(context.Background()) + require.NoError(err) + msgs, err := foundEntry.UnmarshalData(testCtx, types) + require.NoError(err) + require.Equal(1, len(msgs)) + entry := msgs[0] + entryUser := entry.Message.(*oplog_test.TestUser) + assert.Equal(entryUser.Name, tt.msg.Message.(*oplog_test.TestUser).Name) + assert.Equal(entry.FieldMaskPaths, tt.msg.FieldMaskPaths) + assert.Equal(entry.SetToNullPaths, tt.msg.SetToNullPaths) + assert.Equal(entry.OpType, tt.msg.OpType) + assert.Equal(entry.TypeName, tt.msg.TypeName) + + entryOpts := dbw.GetOpts(entry.Opts...) + testMsgOpts := dbw.GetOpts(tt.msg.Opts...) + assert.Equal(entryOpts, testMsgOpts) + + foundEntry.Cipherer = cipherer + err = foundEntry.DecryptData(context.Background()) + require.NoError(err) + err = foundEntry.Replay(context.Background(), tt.w, types, tableSuffix) + require.NoError(err) + foundUser := testFindUser(t, tt.w.DB, entryUser.Id) + + var foundReplayedUser oplog_test.TestUser + foundReplayedUser.Table = foundReplayedUser.TableName() + tableSuffix + require.NoError(dbw.New(tt.w.DB).LookupWhere(testCtx, &foundReplayedUser, "id = ?", []interface{}{entryUser.Id})) + require.NoError(err) + + assert.Equal(foundUser.Id, foundReplayedUser.Id) + assert.Equal(foundUser.Name, foundReplayedUser.Name) + assert.Equal(foundUser.PhoneNumber, foundReplayedUser.PhoneNumber) + assert.Equal(foundUser.Email, foundReplayedUser.Email) + }) + } +} + // Test_TicketSerialization provides unit tests for making sure oplog.Tickets properly serialize writes to oplog entries func Test_TicketSerialization(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) assert, require := assert.New(t), require.New(t) + testCtx := context.Background() - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) require.NoError(err) cipherer := testWrapper(t) id := testId(t) - firstTx := db.Begin() + firstTx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) firstUser := oplog_test.TestUser{ Name: "foo-" + id, } - err = firstTx.Create(&firstUser).Error + err = firstTx.Create(testCtx, &firstUser) require.NoError(err) - firstTicket, err := ticketer.GetTicket("default") + firstTicket, err := ticketer.GetTicket(testCtx, "default") require.NoError(err) firstQueue := Queue{} - err = firstQueue.Add(&firstUser, "user", OpType_OP_TYPE_CREATE) + err = firstQueue.add(testCtx, &firstUser, "user", OpType_OP_TYPE_CREATE) require.NoError(err) firstLogEntry, err := NewEntry( + testCtx, "test-users", Metadata{ "key-only": nil, @@ -678,20 +952,22 @@ func Test_TicketSerialization(t *testing.T) { firstLogEntry.Data = firstQueue.Bytes() id2 := testId(t) - secondTx := db.Begin() + secondTx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) secondUser := oplog_test.TestUser{ Name: "foo-" + id2, } - err = secondTx.Create(&secondUser).Error + err = secondTx.Create(testCtx, &secondUser) require.NoError(err) - secondTicket, err := ticketer.GetTicket("default") + secondTicket, err := ticketer.GetTicket(testCtx, "default") require.NoError(err) secondQueue := Queue{} - err = secondQueue.Add(&secondUser, "user", OpType_OP_TYPE_CREATE) + err = secondQueue.add(testCtx, &secondUser, "user", OpType_OP_TYPE_CREATE) require.NoError(err) secondLogEntry, err := NewEntry( + testCtx, "foobar", Metadata{ "key-only": nil, @@ -704,20 +980,20 @@ func Test_TicketSerialization(t *testing.T) { require.NoError(err) secondLogEntry.Data = secondQueue.Bytes() - err = secondLogEntry.Write(context.Background(), &GormWriter{secondTx}, secondTicket) + err = secondLogEntry.Write(context.Background(), &Writer{secondTx.DB()}, secondTicket) require.NoError(err) assert.NotEmpty(secondLogEntry.Id, 0) assert.NotNil(secondLogEntry.CreateTime) assert.NotNil(secondLogEntry.UpdateTime) - err = secondTx.Commit().Error + err = secondTx.Commit(testCtx) require.NoError(err) assert.NotNil(secondLogEntry.Id) - err = firstLogEntry.Write(context.Background(), &GormWriter{firstTx}, firstTicket) + err = firstLogEntry.Write(context.Background(), &Writer{firstTx.DB()}, firstTicket) if err != nil { - firstTx.Rollback() + firstTx.Rollback(testCtx) } else { - firstTx.Commit() + firstTx.Commit(testCtx) t.Error("should have failed to write firstLogEntry") } } diff --git a/internal/oplog/oplog_test/db.go b/internal/oplog/oplog_test/db.go index f3a6ea4b6..9f3bc77fa 100644 --- a/internal/oplog/oplog_test/db.go +++ b/internal/oplog/oplog_test/db.go @@ -1,7 +1,13 @@ // Package oplog_test provides some gorm helper funcs for testing oplog database integrations package oplog_test -import "gorm.io/gorm" +import ( + "context" + "testing" + + "github.com/hashicorp/go-dbw" + "github.com/stretchr/testify/require" +) const ( defaultTestUserTableName = "oplog_test_user" @@ -10,19 +16,71 @@ const ( ) // Init will use gorm migrations to init tables for test models -func Init(db *gorm.DB) { - db.AutoMigrate(&TestUser{}) - db.AutoMigrate(&TestCar{}) - db.AutoMigrate(&TestRental{}) +func Init(t *testing.T, db *dbw.DB) { + const testQueryCreateTables = ` + begin; + + -- create test tables used in the unit tests for the oplog package + -- these tables (oplog_test_user, oplog_test_car, oplog_test_rental) are + -- not part of the boundary domain model... they are simply used for testing + -- the oplog package + create table if not exists oplog_test_user ( + id bigserial primary key, + name text + constraint oplog_test_user_name_uq unique, + phone_number text, + email text, + version wt_version + ); + + create or replace function + oplog_test_version_column() + returns trigger + as $$ + begin + if pg_trigger_depth() = 1 then + if row(new.*) is distinct from row(old.*) then + if tg_nargs = 0 then + execute format('update %I set version = $1 where id = $2', tg_relid::regclass) using old.version+1, new.id; + new.version = old.version + 1; + return new; + end if; + end if; + end if; + return new; + end; + $$ language plpgsql; + + create trigger + update_version_column + after update on oplog_test_user + for each row execute procedure oplog_test_version_column(); + + create table if not exists oplog_test_car ( + id bigserial primary key, + name text unique, + model text, + mpg smallint + ); + + create table if not exists oplog_test_rental ( + user_id bigint not null references oplog_test_user(id), + car_id bigint not null references oplog_test_car(id) + ); + + + commit; + ` + _, err := dbw.New(db).Exec(context.Background(), testQueryCreateTables, nil) + require.NoError(t, err) } // Reinit will use gorm to drop then init tables for test models -func Reinit(db *gorm.DB) { - // Migrator.DropTable is actually "drop table if exists" - _ = db.Migrator().DropTable(&TestUser{}) - _ = db.Migrator().DropTable(&TestCar{}) - _ = db.Migrator().DropTable(&TestRental{}) - Init(db) +func Reinit(t *testing.T, db *dbw.DB) { + const sql = `` + _, err := dbw.New(db).Exec(context.Background(), sql, nil) + require.NoError(t, err) + Init(t, db) } // TableName overrides the table name for TestUser diff --git a/internal/oplog/oplog_test/oplog_test.pb.go b/internal/oplog/oplog_test/oplog_test.pb.go index 9174e8d52..a46a61ece 100644 --- a/internal/oplog/oplog_test/oplog_test.pb.go +++ b/internal/oplog/oplog_test/oplog_test.pb.go @@ -33,6 +33,8 @@ type TestUser struct { Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` PhoneNumber string `protobuf:"bytes,5,opt,name=phone_number,json=phoneNumber,proto3" json:"phone_number,omitempty"` Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"` + // @inject_tag: gorm:"default:null" + Version uint32 `protobuf:"varint,9,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"` // @inject_tag: gorm:"-" json:"-" Table string `protobuf:"bytes,7,opt,name=table,proto3" json:"-" gorm:"-"` } @@ -97,6 +99,13 @@ func (x *TestUser) GetEmail() string { return "" } +func (x *TestUser) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + func (x *TestUser) GetTable() string { if x != nil { return x.Table @@ -324,38 +333,39 @@ var file_controller_storage_oplog_test_v1_oplog_test_proto_rawDesc = []byte{ 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x22, 0x7d, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, - 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x22, 0x57, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x72, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x70, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x03, 0x6d, 0x70, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x52, 0x0a, - 0x0a, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x63, 0x61, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x61, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x22, 0x74, 0x0a, 0x15, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, - 0x61, 0x79, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x2f, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, - 0x73, 0x74, 0x3b, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x22, 0x97, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x68, + 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, + 0x57, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x70, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, + 0x70, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x52, 0x0a, 0x0a, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x15, 0x0a, 0x06, 0x63, 0x61, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x63, 0x61, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x74, 0x0a, 0x15, + 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x61, 0x62, 0x6c, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x68, 0x6f, + 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x70, 0x6c, + 0x6f, 0x67, 0x2f, 0x6f, 0x70, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x3b, 0x6f, 0x70, + 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/oplog/options.go b/internal/oplog/options.go index fbb6c4fda..62809e36d 100644 --- a/internal/oplog/options.go +++ b/internal/oplog/options.go @@ -1,10 +1,14 @@ package oplog +import "github.com/hashicorp/go-dbw" + // GetOpts - iterate the inbound Options and return a struct func GetOpts(opt ...Option) Options { opts := getDefaultOptions() for _, o := range opt { - o(opts) + if o != nil { + o(opts) + } } return opts } @@ -17,9 +21,20 @@ type Options map[string]interface{} func getDefaultOptions() Options { return Options{ - optionWithFieldMaskPaths: []string{}, - optionWithSetToNullPaths: []string{}, - optionWithAggregateNames: false, + optionWithFieldMaskPaths: []string{}, + optionWithSetToNullPaths: []string{}, + optionWithAggregateNames: false, + optionWithOperationOptions: []dbw.Option{}, + } +} + +const optionWithOperationOptions = "optionWithOptions" + +// WithOperationOptions represents an optional set dbw.Options. (see the dbw +// package for more info on the options) +func WithOperationOptions(opt ...dbw.Option) Option { + return func(o Options) { + o[optionWithOperationOptions] = opt } } diff --git a/internal/oplog/queue.go b/internal/oplog/queue.go index 10155a8ab..0d30623bc 100644 --- a/internal/oplog/queue.go +++ b/internal/oplog/queue.go @@ -2,6 +2,7 @@ package oplog import ( "bytes" + "context" "encoding/binary" "fmt" "io" @@ -9,6 +10,7 @@ import ( "github.com/hashicorp/boundary/internal/db/common" "github.com/hashicorp/boundary/internal/errors" + "github.com/hashicorp/go-dbw" "google.golang.org/genproto/protobuf/field_mask" "google.golang.org/protobuf/proto" ) @@ -24,29 +26,30 @@ type Queue struct { mx sync.Mutex } -// Add message to queue. typeName defines the type of message added to the +// add message to queue. typeName defines the type of message added to the // queue and allows the msg to be removed using a TypeCatalog with a // coresponding typeName entry. OpType defines the msg's operation (create, add, // update, etc). If OpType == OpType_OP_TYPE_UPDATE, the WithFieldMaskPaths() // and SetToNullPaths() options are supported. -func (q *Queue) Add(m proto.Message, typeName string, t OpType, opt ...Option) error { +func (q *Queue) add(ctx context.Context, m proto.Message, typeName string, t OpType, opt ...Option) error { const op = "oplog.(Queue).Add" // we're not checking the Catalog for nil, since it's not used // when Adding messages to the queue opts := GetOpts(opt...) withFieldMasks := opts[optionWithFieldMaskPaths].([]string) withNullPaths := opts[optionWithSetToNullPaths].([]string) + withOperationOptions := opts[optionWithOperationOptions].([]dbw.Option) if _, ok := m.(ReplayableMessage); !ok { - return errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprintf("%T is not a replayable message", m)) + return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%T is not a replayable message", m)) } value, err := proto.Marshal(m) if err != nil { - return errors.NewDeprecated(errors.Encode, op, "error marshaling add parameter", errors.WithWrap(err)) + return errors.New(ctx, errors.Encode, op, "error marshaling add parameter", errors.WithWrap(err)) } if t == OpType_OP_TYPE_UPDATE { if len(withFieldMasks) == 0 && len(withNullPaths) == 0 { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing field masks or null paths for update") + return errors.New(ctx, errors.InvalidParameter, op, "missing field masks or null paths for update") } fMasks := withFieldMasks if fMasks == nil { @@ -58,12 +61,19 @@ func (q *Queue) Add(m proto.Message, typeName string, t OpType, opt ...Option) e } i, _, _, err := common.Intersection(fMasks, nullPaths) if err != nil { - return errors.WrapDeprecated(err, op) + return errors.Wrap(ctx, err, op) } if len(i) != 0 { - return errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprintf("field masks and null paths intersect with: %s", i)) + return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("field masks and null paths intersect with: %s", i)) + } + } + var operationOpts *OperationOptions + if len(withOperationOptions) > 0 { + dbwOptions := dbw.GetOpts(withOperationOptions...) + operationOpts, err = convertFromDbwOpts(ctx, dbwOptions) + if err != nil { + return errors.Wrap(ctx, err, op) } - } msg := &AnyOperation{ TypeName: typeName, @@ -71,61 +81,70 @@ func (q *Queue) Add(m proto.Message, typeName string, t OpType, opt ...Option) e OperationType: t, FieldMask: &field_mask.FieldMask{Paths: withFieldMasks}, NullMask: &field_mask.FieldMask{Paths: withNullPaths}, + Options: operationOpts, } data, err := proto.Marshal(msg) if err != nil { - return errors.NewDeprecated(errors.Encode, op, "error marshaling message", errors.WithWrap(err)) + return errors.New(ctx, errors.Encode, op, "error marshaling message", errors.WithWrap(err)) } q.mx.Lock() defer q.mx.Unlock() err = binary.Write(q, binary.LittleEndian, uint32(len(data))) if err != nil { - return errors.NewDeprecated(errors.Io, op, "binary write error", errors.WithWrap(err)) + return errors.New(ctx, errors.Io, op, "binary write error", errors.WithWrap(err)) } n, err := q.Write(data) if err != nil { - return errors.NewDeprecated(errors.Io, op, "error writing to queue buffer", errors.WithWrap(err)) + return errors.New(ctx, errors.Io, op, "error writing to queue buffer", errors.WithWrap(err)) } if n != len(data) { - return errors.NewDeprecated(errors.Io, op, fmt.Sprintf("error writing to queue buffer (incorrect number of bytes %d of %d)", n, len(data))) + return errors.New(ctx, errors.Io, op, fmt.Sprintf("error writing to queue buffer (incorrect number of bytes %d of %d)", n, len(data))) } return nil } -// Remove pb message from the queue and EOF if empty. It also returns the OpType +type queueEntry struct { + msg proto.Message + opType OpType + fieldMask []string + setToNullPaths []string + operationOptions *OperationOptions +} + +// remove pb message from the queue and EOF if empty. It also returns the OpType // for the msg and if it's OpType_OP_TYPE_UPDATE, the it will also return the // fieldMask and setToNullPaths for the update operation. -func (q *Queue) Remove() (proto.Message, OpType, []string, []string, error) { +func (q *Queue) remove(ctx context.Context) (*queueEntry, error) { const op = "oplog.(Queue).Remove" if q.Catalog == nil { - return nil, OpType_OP_TYPE_UNSPECIFIED, nil, nil, errors.NewDeprecated(errors.InvalidParameter, op, "nil catalog") + return nil, errors.New(ctx, errors.InvalidParameter, op, "nil catalog") } q.mx.Lock() defer q.mx.Unlock() var n uint32 err := binary.Read(q, binary.LittleEndian, &n) if err == io.EOF { - return nil, 0, nil, nil, err // intentionally not wrapping error, return io.EOF so client can handle it correctly + return nil, err // intentionally not wrapping error, return io.EOF so client can handle it correctly } if err != nil { - return nil, 0, nil, nil, errors.NewDeprecated(errors.Io, op, "binary read error", errors.WithWrap(err)) + return nil, errors.New(ctx, errors.Io, op, "binary read error", errors.WithWrap(err)) } data := q.Next(int(n)) msg := new(AnyOperation) err = proto.Unmarshal(data, msg) if err != nil { - return nil, 0, nil, nil, errors.NewDeprecated(errors.Decode, op, "error unmarshaling message", errors.WithWrap(err)) + return nil, errors.New(ctx, errors.Decode, op, "error unmarshaling message", errors.WithWrap(err)) } if msg.Value == nil { - return nil, 0, nil, nil, nil + return nil, nil } - any, err := q.Catalog.Get(msg.TypeName) + any, err := q.Catalog.Get(ctx, msg.TypeName) if err != nil { - return nil, 0, nil, nil, errors.WrapDeprecated(err, op, errors.WithMsg(fmt.Sprintf("error getting the TypeName: %s", msg.TypeName))) + return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error getting the TypeName: %s", msg.TypeName))) } pm := any.(proto.Message) if err = proto.Unmarshal(msg.Value, pm); err != nil { - return nil, 0, nil, nil, errors.NewDeprecated(errors.Decode, op, "error unmarshaling value", errors.WithWrap(err)) + return nil, errors.New(ctx, errors.Decode, op, "error unmarshaling value", errors.WithWrap(err)) } var masks, nullPaths []string if msg.OperationType == OpType_OP_TYPE_UPDATE { @@ -136,9 +155,14 @@ func (q *Queue) Remove() (proto.Message, OpType, []string, []string, error) { nullPaths = msg.NullMask.GetPaths() } if len(masks) == 0 && len(nullPaths) == 0 { - return nil, 0, nil, nil, errors.NewDeprecated(errors.InvalidParameter, op, "field mask or null paths is required") + return nil, errors.New(ctx, errors.InvalidParameter, op, "field mask or null paths is required") } - } - return pm, msg.OperationType, masks, nullPaths, nil + return &queueEntry{ + msg: pm, + opType: msg.OperationType, + fieldMask: masks, + setToNullPaths: nullPaths, + operationOptions: msg.GetOptions(), + }, nil } diff --git a/internal/oplog/queue_test.go b/internal/oplog/queue_test.go index 093a9e296..3c5b2e599 100644 --- a/internal/oplog/queue_test.go +++ b/internal/oplog/queue_test.go @@ -1,6 +1,7 @@ package oplog import ( + "context" "testing" "github.com/hashicorp/boundary/internal/oplog/oplog_test" @@ -12,7 +13,8 @@ import ( // Test_Queue provides basic tests for the Queue type func Test_Queue(t *testing.T) { t.Parallel() - types, err := NewTypeCatalog( + testCtx := context.Background() + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, Type{new(oplog_test.TestCar), "car"}, Type{new(oplog_test.TestRental), "rental"}, @@ -48,61 +50,61 @@ func Test_Queue(t *testing.T) { } t.Run("add/remove", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - err = queue.Add(user, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, user, "user", OpType_OP_TYPE_CREATE) require.NoError(err) - err = queue.Add(car, "car", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, car, "car", OpType_OP_TYPE_CREATE) require.NoError(err) - err = queue.Add(rental, "rental", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, rental, "rental", OpType_OP_TYPE_CREATE) require.NoError(err) - err = queue.Add(userUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name", "Email"})) + err = queue.add(testCtx, userUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name", "Email"})) require.NoError(err) - err = queue.Add(userNilUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name"}), WithSetToNullPaths([]string{"Email"})) + err = queue.add(testCtx, userNilUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name"}), WithSetToNullPaths([]string{"Email"})) require.NoError(err) - queuedUser, ty, fm, nm, err := queue.Remove() + queuedUser, err := queue.remove(testCtx) require.NoError(err) - assert.True(proto.Equal(user, queuedUser)) - assert.Equal(ty, OpType_OP_TYPE_CREATE) - assert.Nil(fm) - assert.Nil(nm) + assert.True(proto.Equal(user, queuedUser.msg)) + assert.Equal(queuedUser.opType, OpType_OP_TYPE_CREATE) + assert.Nil(queuedUser.fieldMask) + assert.Nil(queuedUser.setToNullPaths) - queuedCar, ty, fm, nm, err := queue.Remove() + queuedCar, err := queue.remove(testCtx) require.NoError(err) - assert.True(proto.Equal(car, queuedCar)) - assert.Equal(ty, OpType_OP_TYPE_CREATE) - assert.Nil(fm) - assert.Nil(nm) + assert.True(proto.Equal(car, queuedCar.msg)) + assert.Equal(queuedCar.opType, OpType_OP_TYPE_CREATE) + assert.Nil(queuedCar.fieldMask) + assert.Nil(queuedCar.setToNullPaths) - queuedRental, ty, fm, nm, err := queue.Remove() + queuedRental, err := queue.remove(testCtx) require.NoError(err) - assert.True(proto.Equal(rental, queuedRental)) - assert.Equal(ty, OpType_OP_TYPE_CREATE) - assert.Nil(fm) - assert.Nil(nm) + assert.True(proto.Equal(rental, queuedRental.msg)) + assert.Equal(queuedRental.opType, OpType_OP_TYPE_CREATE) + assert.Nil(queuedRental.fieldMask) + assert.Nil(queuedRental.setToNullPaths) - queuedUserUpdate, ty, fm, nm, err := queue.Remove() + queuedUserUpdate, err := queue.remove(testCtx) require.NoError(err) - assert.True(proto.Equal(userUpdate, queuedUserUpdate)) - assert.Equal(ty, OpType_OP_TYPE_UPDATE) - assert.Equal(fm, []string{"Name", "Email"}) - assert.Nil(nm) + assert.True(proto.Equal(userUpdate, queuedUserUpdate.msg)) + assert.Equal(queuedUserUpdate.opType, OpType_OP_TYPE_UPDATE) + assert.Equal(queuedUserUpdate.fieldMask, []string{"Name", "Email"}) + assert.Nil(queuedUserUpdate.setToNullPaths) - queuedUserNilUpdate, ty, fm, nm, err := queue.Remove() + queuedUserNilUpdate, err := queue.remove(testCtx) require.NoError(err) - assert.True(proto.Equal(userNilUpdate, queuedUserNilUpdate)) - assert.Equal(ty, OpType_OP_TYPE_UPDATE) - assert.Equal(fm, []string{"Name"}) - assert.Equal(nm, []string{"Email"}) + assert.True(proto.Equal(userNilUpdate, queuedUserNilUpdate.msg)) + assert.Equal(queuedUserNilUpdate.opType, OpType_OP_TYPE_UPDATE) + assert.Equal(queuedUserNilUpdate.fieldMask, []string{"Name"}) + assert.Equal(queuedUserNilUpdate.setToNullPaths, []string{"Email"}) }) t.Run("valid with nil type catalog", func(t *testing.T) { require := require.New(t) queue := Queue{} - require.NoError(queue.Add(user, "user", OpType_OP_TYPE_CREATE)) + require.NoError(queue.add(testCtx, user, "user", OpType_OP_TYPE_CREATE)) }) t.Run("error with nil type catalog", func(t *testing.T) { assert, require := assert.New(t), require.New(t) queue := Queue{} - _, _, _, _, err = queue.Remove() + _, err = queue.remove(testCtx) require.Error(err) assert.Equal("oplog.(Queue).Remove: nil catalog: parameter violation: error #100", err.Error()) }) @@ -113,20 +115,20 @@ func Test_Queue(t *testing.T) { PhoneNumber: "867-5309", Email: "alice@bob.com", } - err = queue.Add(u, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, u, "user", OpType_OP_TYPE_CREATE) require.Error(err) assert.Equal("oplog.(Queue).Add: *oplog_test.TestNonReplayableUser is not a replayable message: parameter violation: error #100", err.Error()) }) t.Run("nil message", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - err = queue.Add(nil, "user", OpType_OP_TYPE_CREATE) + err = queue.add(testCtx, nil, "user", OpType_OP_TYPE_CREATE) require.Error(err) assert.Equal("oplog.(Queue).Add: is not a replayable message: parameter violation: error #100", err.Error()) }) t.Run("missing both field mask and null paths for update", func(t *testing.T) { - require.Error(t, queue.Add(userUpdate, "user", OpType_OP_TYPE_UPDATE)) + require.Error(t, queue.add(testCtx, userUpdate, "user", OpType_OP_TYPE_UPDATE)) }) t.Run("intersecting field masks and null paths", func(t *testing.T) { - require.Error(t, queue.Add(userNilUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name"}), WithSetToNullPaths([]string{"Name"}))) + require.Error(t, queue.add(testCtx, userNilUpdate, "user", OpType_OP_TYPE_UPDATE, WithFieldMaskPaths([]string{"Name"}), WithSetToNullPaths([]string{"Name"}))) }) } diff --git a/internal/oplog/replayable.go b/internal/oplog/replayable.go index b403167c4..7299a3f0c 100644 --- a/internal/oplog/replayable.go +++ b/internal/oplog/replayable.go @@ -1,8 +1,10 @@ package oplog -// Replayable defines an interface for messages that can be replayed from the oplog entries. we need to be -// able to replay into different table names. +// ReplayableMessage defines an interface for messages that can be replayed from +// the oplog entries. we need to be able to replay into different table names. type ReplayableMessage interface { + // TableName returns the table name of the resource TableName() string + // SetTableName sets the table name of the resource SetTableName(name string) } diff --git a/internal/oplog/testing.go b/internal/oplog/testing.go index ec677026f..2a94993b6 100644 --- a/internal/oplog/testing.go +++ b/internal/oplog/testing.go @@ -9,60 +9,79 @@ import ( "github.com/hashicorp/boundary/internal/db/schema" "github.com/hashicorp/boundary/internal/oplog/oplog_test" "github.com/hashicorp/boundary/testing/dbtest" + "github.com/hashicorp/go-dbw" wrapping "github.com/hashicorp/go-kms-wrapping" "github.com/hashicorp/go-kms-wrapping/wrappers/aead" - "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gorm.io/gorm" + "gorm.io/driver/postgres" ) -func testCleanup(t *testing.T, cleanupFunc func() error, db *gorm.DB) { +// setup the tests (initialize the database one-time and intialized testDatabaseURL) +func setup(t *testing.T) *dbw.DB { t.Helper() - err := cleanupFunc() - assert.NoError(t, err) - sqlDB, err := db.DB() - assert.NoError(t, err) - err = sqlDB.Close() - assert.NoError(t, err) + require := require.New(t) + cleanup, url, err := testInitDbInDocker(t) + require.NoError(err) + db := testOpen(t, "postgres", url) + require.NoError(err) + oplog_test.Init(t, db) + t.Cleanup(func() { + assert.NoError(t, db.Close(context.Background())) + assert.NoError(t, cleanup()) + }) + return db } -func testUser(t *testing.T, db *gorm.DB, name, phoneNumber, email string) *oplog_test.TestUser { +func testOpen(t *testing.T, dbType string, connectionUrl string) *dbw.DB { + t.Helper() + require := require.New(t) + var dialect dbw.Dialector + switch dbType { + case "postgres": + dialect = postgres.New(postgres.Config{ + DSN: connectionUrl, + }, + ) + default: + t.Errorf("unable to open %s database type", dbType) + t.FailNow() + } + db, err := dbw.OpenWith(dialect) + require.NoError(err) + return db +} + +func testUser(t *testing.T, db *dbw.DB, name, phoneNumber, email string) *oplog_test.TestUser { t.Helper() u := &oplog_test.TestUser{ Name: name, PhoneNumber: phoneNumber, Email: email, } - w := GormWriter{db} - - err := w.Create(&u) - require.NoError(t, err) + require.NoError(t, dbw.New(db).Create(context.Background(), u)) return u } -func testFindUser(t *testing.T, db *gorm.DB, userId uint32) *oplog_test.TestUser { +func testFindUser(t *testing.T, db *dbw.DB, userId uint32) *oplog_test.TestUser { t.Helper() var foundUser oplog_test.TestUser - err := db.Where("id = ?", userId).First(&foundUser).Error - require.NoError(t, err) + require.NoError(t, dbw.New(db).LookupWhere(context.Background(), &foundUser, "id = ?", []interface{}{userId})) return &foundUser } func testId(t *testing.T) string { t.Helper() - id, err := uuid.GenerateUUID() + id, err := dbw.NewId("i") require.NoError(t, err) return id } func testInitDbInDocker(t *testing.T) (cleanup func() error, retURL string, err error) { t.Helper() - + require := require.New(t) cleanup, retURL, _, err = dbtest.StartUsingTemplate(dbtest.Postgres) - if err != nil { - t.Fatal(err) - } + require.NoError(err) testInitStore(t, cleanup, retURL) return } @@ -92,3 +111,42 @@ func testInitStore(t *testing.T, cleanup func() error, url string) { require.NoError(t, err) require.NoError(t, sm.ApplyMigrations(ctx)) } + +type constraintResults struct { + Name string + TableName string +} + +func testListConstraints(t *testing.T, db *dbw.DB, tableName string) []constraintResults { + t.Helper() + require := require.New(t) + testCtx := context.Background() + const constraintSql = `select pgc.conname as name, + ccu.table_schema as table_schema, + ccu.table_name, + ccu.column_name, + pgc.consrc as definition +from pg_constraint pgc +join pg_namespace nsp on nsp.oid = pgc.connamespace +join pg_class cls on pgc.conrelid = cls.oid +left join information_schema.constraint_column_usage ccu + on pgc.conname = ccu.constraint_name + and nsp.nspname = ccu.constraint_schema +-- where contype ='c' +order by ccu.table_name,pgc.conname ` + + rw := dbw.New(db) + rows, err := rw.Query(testCtx, constraintSql, []interface{}{tableName}) + require.NoError(err) + type result struct { + Name string + TableName string + } + results := []constraintResults{} + for rows.Next() { + var r constraintResults + rw.ScanRows(rows, &r) + results = append(results, r) + } + return results +} diff --git a/internal/oplog/testing_test.go b/internal/oplog/testing_test.go index 3478813b6..8be897067 100644 --- a/internal/oplog/testing_test.go +++ b/internal/oplog/testing_test.go @@ -8,19 +8,9 @@ import ( "github.com/stretchr/testify/require" ) -func Test_testCleanup(t *testing.T) { - assert := assert.New(t) - cleanup, db := setup(t) - testCleanup(t, cleanup, db) - - err := db.Begin().Error - assert.Equal("sql: database is closed", err.Error()) -} - func Test_testUser(t *testing.T) { assert, require := assert.New(t), require.New(t) - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) id := testId(t) @@ -33,8 +23,7 @@ func Test_testUser(t *testing.T) { func Test_testFindUser(t *testing.T) { assert, require := assert.New(t), require.New(t) - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) + db := setup(t) id := testId(t) u := testUser(t, db, id, id, id) require.NotNil(u) @@ -85,3 +74,10 @@ select count(*) from information_schema."tables" t where table_name = 'boundary_ require.NoError(err) assert.Equal(1, cnt) } + +func Test_testListConstraints(t *testing.T) { + assert := assert.New(t) + db := setup(t) + constraints := testListConstraints(t, db, "oplog_test_user") + assert.NotEmpty(constraints) +} diff --git a/internal/oplog/ticketer.go b/internal/oplog/ticketer.go index 744096a91..6bb82e09c 100644 --- a/internal/oplog/ticketer.go +++ b/internal/oplog/ticketer.go @@ -1,9 +1,11 @@ package oplog import ( + "context" + "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog/store" - "gorm.io/gorm" + "github.com/hashicorp/go-dbw" ) const DefaultAggregateName = "global" @@ -16,63 +18,65 @@ type Ticketer interface { // db migrations script. Requiring this insert as part of migrations ensures that the tickets are initialized in // a separate transaction from when a client calls GetTicket(aggregateName) which is critical for the optimized locking // pattern to work properly - GetTicket(aggregateName string) (*store.Ticket, error) + GetTicket(ctx context.Context, aggregateName string) (*store.Ticket, error) // Redeem ticket will attempt to redeem the ticket and ensure it's serialized with other tickets using the same // aggregate name - Redeem(ticket *store.Ticket) error + Redeem(ctx context.Context, ticket *store.Ticket) error } -// GormTicketer uses a gorm DB connection for ticket storage -type GormTicketer struct { - tx *gorm.DB +// DbwTicketer defines a ticketer that uses the dbw pkg for database operations. +type DbwTicketer struct { + tx *dbw.DB withAggregateNames bool } -// NewGormTicketer creates a new ticketer that uses gorm for storage -func NewGormTicketer(tx *gorm.DB, opt ...Option) (*GormTicketer, error) { - const op = "oplog.NewGormTicketer" +// NewTicketer creates a new ticketer that uses dbw for storage +func NewTicketer(ctx context.Context, tx *dbw.DB, opt ...Option) (*DbwTicketer, error) { + const op = "oplog.NewDbwTicketer" if tx == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "nil tx") + return nil, errors.New(ctx, errors.InvalidParameter, op, "nil tx") } opts := GetOpts(opt...) enableAggregateNames := opts[optionWithAggregateNames].(bool) - return &GormTicketer{tx: tx, withAggregateNames: enableAggregateNames}, nil + return &DbwTicketer{tx: tx, withAggregateNames: enableAggregateNames}, nil } // GetTicket returns a ticket for the specified name. You MUST GetTicket in the same transaction // that you're using to write to the database tables. Names allow us to shard tickets around domain root names -func (ticketer *GormTicketer) GetTicket(aggregateName string) (*store.Ticket, error) { +func (ticketer *DbwTicketer) GetTicket(ctx context.Context, aggregateName string) (*store.Ticket, error) { const op = "oplog.(GormTicketer).GetTicket" if aggregateName == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing ticket name") + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing ticket name") } name := DefaultAggregateName if ticketer.withAggregateNames { name = aggregateName } ticket := store.Ticket{} - if err := ticketer.tx.First(&ticket, store.Ticket{Name: name}).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, errors.NewDeprecated(errors.TicketNotFound, op, "ticket not found") + if err := dbw.New(ticketer.tx).LookupWhere(ctx, &ticket, "name = ?", []interface{}{name}); err != nil { + if errors.Is(err, dbw.ErrRecordNotFound) { + return nil, errors.New(ctx, errors.TicketNotFound, op, "ticket not found") } - return nil, errors.WrapDeprecated(err, op, errors.WithMsg("error retrieving ticket from storage")) + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error retrieving ticket from storage")) } return &ticket, nil } // Redeem will attempt to redeem the ticket. If the ticket version has already been used, then an error is returned -func (ticketer *GormTicketer) Redeem(t *store.Ticket) error { +func (ticketer *DbwTicketer) Redeem(ctx context.Context, t *store.Ticket) error { const op = "oplog.(GormTicketer).Redeem" if t == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil ticket") + return errors.New(ctx, errors.InvalidParameter, op, "nil ticket") } - tx := ticketer.tx.Model(t).Where("version = ?", t.Version).Update("version", t.Version+1) - if tx.Error != nil { - return errors.WrapDeprecated(tx.Error, op, errors.WithMsg("error trying to redeem ticket")) + currentVersion := t.Version + t.Version = t.Version + 1 + rowsUpdated, err := dbw.New(ticketer.tx).Update(ctx, t, []string{"Version"}, nil, dbw.WithVersion(¤tVersion)) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("error trying to redeem ticket")) } - if tx.RowsAffected != 1 { - return errors.NewDeprecated(errors.TicketAlreadyRedeemed, op, "ticket already redeemed") + if rowsUpdated != 1 { + return errors.New(ctx, errors.TicketAlreadyRedeemed, op, "ticket already redeemed") } return nil } diff --git a/internal/oplog/ticketer_gorm_test.go b/internal/oplog/ticketer_gorm_test.go deleted file mode 100644 index 9852645dd..000000000 --- a/internal/oplog/ticketer_gorm_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package oplog - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// Test_NewGormTicketer provides unit tests for creating a Gorm ticketer -func Test_NewGormTicketer(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) - - t.Run("valid", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) - require.NoError(err) - assert.NotNil(ticketer) - }) - t.Run("bad db", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - _, err := NewGormTicketer(nil, WithAggregateNames(true)) - require.Error(err) - assert.Equal("oplog.NewGormTicketer: nil tx: parameter violation: error #100", err.Error()) - }) -} - -// Test_GetTicket provides unit tests for getting oplog.Tickets -func Test_GetTicket(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) - - ticketer, err := NewGormTicketer(db, WithAggregateNames(true)) - require.NoError(t, err) - - t.Run("valid", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - ticket, err := ticketer.GetTicket("default") - require.NoError(err) - assert.Equal(ticket.Name, "default") - assert.NotEqual(ticket.Version, 0) - }) - - t.Run("no name", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - ticket, err := ticketer.GetTicket("") - require.Error(err) - assert.Equal("oplog.(GormTicketer).GetTicket: missing ticket name: parameter violation: error #100", err.Error()) - assert.Nil(ticket) - }) -} - -// Test_Redeem provides unit tests for redeeming tickets -func Test_Redeem(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) - - t.Run("valid", func(t *testing.T) { - require := require.New(t) - - tx := db.Begin() - defer tx.Commit() - ticketer, err := NewGormTicketer(tx, WithAggregateNames(true)) - require.NoError(err) - - ticket, err := ticketer.GetTicket("default") - require.NoError(err) - - err = ticketer.Redeem(ticket) - require.NoError(err) - }) - t.Run("nil ticket", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - tx := db.Begin() - defer tx.Commit() - - ticketer, err := NewGormTicketer(tx, WithAggregateNames(true)) - require.NoError(err) - err = ticketer.Redeem(nil) - require.Error(err) - assert.Equal("oplog.(GormTicketer).Redeem: nil ticket: parameter violation: error #100", err.Error()) - }) - - t.Run("detect two redemptions in separate concurrent transactions", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - tx := db.Begin() - ticketer, err := NewGormTicketer(tx, WithAggregateNames(true)) - require.NoError(err) - - ticket, err := ticketer.GetTicket("default") - require.NoError(err) - - secondTx := db.Begin() - secondTicketer, err := NewGormTicketer(secondTx, WithAggregateNames(true)) - require.NoError(err) - secondTicket, err := secondTicketer.GetTicket("default") - require.NoError(err) - - err = ticketer.Redeem(ticket) - require.NoError(err) - tx.Commit() - - err = secondTicketer.Redeem(secondTicket) - assert.Equal("oplog.(GormTicketer).Redeem: ticket already redeemed: integrity violation: error #106", err.Error()) - }) -} diff --git a/internal/oplog/ticketer_test.go b/internal/oplog/ticketer_test.go new file mode 100644 index 000000000..82fae96bb --- /dev/null +++ b/internal/oplog/ticketer_test.go @@ -0,0 +1,115 @@ +package oplog + +import ( + "context" + "testing" + + "github.com/hashicorp/go-dbw" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// Test_NewGormTicketer provides unit tests for creating a Gorm ticketer +func Test_NewTicketer(t *testing.T) { + db := setup(t) + testCtx := context.Background() + + t.Run("valid", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) + require.NoError(err) + assert.NotNil(ticketer) + }) + t.Run("bad db", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + _, err := NewTicketer(testCtx, nil, WithAggregateNames(true)) + require.Error(err) + assert.Contains(err.Error(), "nil tx: parameter violation: error #100") + }) +} + +// Test_GetTicket provides unit tests for getting oplog.Tickets +func Test_GetTicket(t *testing.T) { + db := setup(t) + testCtx := context.Background() + + ticketer, err := NewTicketer(testCtx, db, WithAggregateNames(true)) + require.NoError(t, err) + + t.Run("valid", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + ticket, err := ticketer.GetTicket(testCtx, "default") + require.NoError(err) + assert.Equal(ticket.Name, "default") + assert.NotEqual(ticket.Version, 0) + }) + + t.Run("no name", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + ticket, err := ticketer.GetTicket(testCtx, "") + require.Error(err) + assert.Contains(err.Error(), "missing ticket name: parameter violation: error #100") + assert.Nil(ticket) + }) +} + +// Test_Redeem provides unit tests for redeeming tickets +func Test_Redeem(t *testing.T) { + db := setup(t) + testCtx := context.Background() + + t.Run("valid", func(t *testing.T) { + require := require.New(t) + + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Commit(testCtx) + ticketer, err := NewTicketer(testCtx, tx.DB(), WithAggregateNames(true)) + require.NoError(err) + + ticket, err := ticketer.GetTicket(testCtx, "default") + require.NoError(err) + + err = ticketer.Redeem(testCtx, ticket) + require.NoError(err) + }) + t.Run("nil ticket", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Commit(testCtx) + + ticketer, err := NewTicketer(testCtx, tx.DB(), WithAggregateNames(true)) + require.NoError(err) + err = ticketer.Redeem(testCtx, nil) + require.Error(err) + assert.Contains(err.Error(), "nil ticket: parameter violation: error #100") + }) + + t.Run("detect two redemptions in separate concurrent transactions", func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + ticketer, err := NewTicketer(testCtx, tx.DB(), WithAggregateNames(true)) + require.NoError(err) + + ticket, err := ticketer.GetTicket(testCtx, "default") + require.NoError(err) + + secondTx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + secondTicketer, err := NewTicketer(testCtx, secondTx.DB(), WithAggregateNames(true)) + require.NoError(err) + secondTicket, err := secondTicketer.GetTicket(testCtx, "default") + require.NoError(err) + + err = ticketer.Redeem(testCtx, ticket) + require.NoError(err) + tx.Commit(testCtx) + + err = secondTicketer.Redeem(testCtx, secondTicket) + assert.Contains(err.Error(), "ticket already redeemed: integrity violation: error #106") + }) +} diff --git a/internal/oplog/type_catalog.go b/internal/oplog/type_catalog.go index dede168a2..7300ab9fe 100644 --- a/internal/oplog/type_catalog.go +++ b/internal/oplog/type_catalog.go @@ -1,6 +1,7 @@ package oplog import ( + "context" "fmt" "reflect" @@ -21,28 +22,28 @@ type Type struct { } // NewTypeCatalog creates a catalog with the types you pass in -func NewTypeCatalog(withTypes ...Type) (*TypeCatalog, error) { +func NewTypeCatalog(ctx context.Context, withTypes ...Type) (*TypeCatalog, error) { const op = "oplog.NewTypeCatalog" reg := TypeCatalog{} for _, t := range withTypes { if t == (Type{}) { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "error type is {}") + return nil, errors.New(ctx, errors.InvalidParameter, op, "error type is {}") } - if err := reg.Set(t.Interface, t.Name); err != nil { - return nil, errors.WrapDeprecated(err, op, errors.WithMsg("error setting the type")) + if err := reg.Set(ctx, t.Interface, t.Name); err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error setting the type")) } } return ®, nil } // GetTypeName returns the interface's name from the catalog -func (t *TypeCatalog) GetTypeName(i interface{}) (string, error) { +func (t *TypeCatalog) GetTypeName(ctx context.Context, i interface{}) (string, error) { const op = "oplog.(TypeCatalog).GetTypeName" if i == nil { - return "", errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") + return "", errors.New(ctx, errors.InvalidParameter, op, "nil interface") } if reflect.ValueOf(i).Kind() != reflect.Ptr { - return "", errors.NewDeprecated(errors.InvalidParameter, op, "interface must to be a pointer") + return "", errors.New(ctx, errors.InvalidParameter, op, "interface must to be a pointer") } interfaceType := reflect.TypeOf(i) for name, t := range *t { @@ -50,33 +51,33 @@ func (t *TypeCatalog) GetTypeName(i interface{}) (string, error) { return name, nil } } - return "", errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprintf("unknown name for interface: %T", i)) + return "", errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unknown name for interface: %T", i)) } // Set creates an entry in the catalog for the interface -func (t TypeCatalog) Set(i interface{}, typeName string) error { +func (t TypeCatalog) Set(ctx context.Context, i interface{}, typeName string) error { const op = "oplog.(TypeCatalog).Set" if i == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") + return errors.New(ctx, errors.InvalidParameter, op, "nil interface") } if reflect.ValueOf(i).Kind() != reflect.Ptr { - return errors.NewDeprecated(errors.InvalidParameter, op, "interface must to be a pointer") + return errors.New(ctx, errors.InvalidParameter, op, "interface must to be a pointer") } if typeName == "" { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing type name") + return errors.New(ctx, errors.InvalidParameter, op, "missing type name") } t[typeName] = reflect.TypeOf(i) return nil } // Get retrieves the interface via a name -func (t TypeCatalog) Get(typeName string) (interface{}, error) { +func (t TypeCatalog) Get(ctx context.Context, typeName string) (interface{}, error) { const op = "oplog.(TypeCatalog).Get" if typeName == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing type name") + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing type name") } if typ, ok := t[typeName]; ok { return reflect.New(typ.Elem()).Elem().Addr().Interface(), nil } - return nil, errors.NewDeprecated(errors.KeyNotFound, op, "type name not found") + return nil, errors.New(ctx, errors.KeyNotFound, op, "type name not found") } diff --git a/internal/oplog/type_catalog_test.go b/internal/oplog/type_catalog_test.go index a406f1076..a9d13c253 100644 --- a/internal/oplog/type_catalog_test.go +++ b/internal/oplog/type_catalog_test.go @@ -1,6 +1,7 @@ package oplog import ( + "context" "reflect" "testing" @@ -13,50 +14,50 @@ import ( func Test_TypeCatalog(t *testing.T) { t.Parallel() assert, require := assert.New(t), require.New(t) - - types, err := NewTypeCatalog( + testCtx := context.Background() + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, Type{new(oplog_test.TestCar), "car"}, Type{new(oplog_test.TestRental), "rental"}, ) require.NoError(err) - name, err := types.GetTypeName(new(oplog_test.TestUser)) + name, err := types.GetTypeName(testCtx, new(oplog_test.TestUser)) require.NoError(err) assert.Equal(name, "user") - _, err = types.GetTypeName(oplog_test.TestUser{}) + _, err = types.GetTypeName(testCtx, oplog_test.TestUser{}) assert.Error(err) s := "string" - _, err = types.GetTypeName(&s) + _, err = types.GetTypeName(testCtx, &s) assert.Error(err) - _, err = types.Get("unknown") + _, err = types.Get(testCtx, "unknown") assert.Error(err) } // Test_NewTypeCatalog provides unit tests for NewTypeCatalog func Test_NewTypeCatalog(t *testing.T) { t.Parallel() - + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, Type{new(oplog_test.TestCar), "car"}, Type{new(oplog_test.TestRental), "rental"}, ) require.NoError(err) - u, err := types.Get("user") + u, err := types.Get(testCtx, "user") require.NoError(err) assert.Equal(reflect.TypeOf(u), reflect.TypeOf(new(oplog_test.TestUser))) }) t.Run("missing Type.Name", func(t *testing.T) { assert := assert.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), ""}, ) assert.Nil(types) @@ -66,7 +67,7 @@ func Test_NewTypeCatalog(t *testing.T) { t.Run("missing Type.Interface", func(t *testing.T) { assert := assert.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{nil, ""}, ) assert.Nil(types) @@ -76,7 +77,7 @@ func Test_NewTypeCatalog(t *testing.T) { t.Run("empty Type", func(t *testing.T) { assert := assert.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{}, ) assert.Nil(types) @@ -88,29 +89,30 @@ func Test_NewTypeCatalog(t *testing.T) { // Test_GetTypeName provides unit tests for GetTypeName func Test_GetTypeName(t *testing.T) { t.Parallel() + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, Type{new(oplog_test.TestCar), "car"}, ) require.NoError(err) - n, err := types.GetTypeName(new(oplog_test.TestUser)) + n, err := types.GetTypeName(testCtx, new(oplog_test.TestUser)) require.NoError(err) assert.Equal(n, "user") }) t.Run("bad name", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, ) require.NoError(err) - n, err := types.GetTypeName(new(oplog_test.TestCar)) + n, err := types.GetTypeName(testCtx, new(oplog_test.TestCar)) require.Error(err) assert.Equal(n, "") assert.Equal("oplog.(TypeCatalog).GetTypeName: unknown name for interface: *oplog_test.TestCar: parameter violation: error #100", err.Error()) @@ -118,12 +120,12 @@ func Test_GetTypeName(t *testing.T) { t.Run("nil interface", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, ) require.NoError(err) - n, err := types.GetTypeName(nil) + n, err := types.GetTypeName(testCtx, nil) require.Error(err) assert.Equal(n, "") assert.Equal("oplog.(TypeCatalog).GetTypeName: nil interface: parameter violation: error #100", err.Error()) @@ -133,29 +135,29 @@ func Test_GetTypeName(t *testing.T) { // Test_Get provides unit tests for Get func Test_Get(t *testing.T) { t.Parallel() - + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, Type{new(oplog_test.TestCar), "car"}, ) require.NoError(err) - u, err := types.Get("user") + u, err := types.Get(testCtx, "user") require.NoError(err) assert.Equal(reflect.TypeOf(u), reflect.TypeOf(new(oplog_test.TestUser))) }) t.Run("bad name", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, ) require.NoError(err) - n, err := types.Get("car") + n, err := types.Get(testCtx, "car") require.Error(err) assert.Equal(n, nil) assert.Equal("oplog.(TypeCatalog).Get: type name not found: integrity violation: error #105", err.Error()) @@ -163,12 +165,12 @@ func Test_Get(t *testing.T) { t.Run("bad typeName", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog( + types, err := NewTypeCatalog(testCtx, Type{new(oplog_test.TestUser), "user"}, ) require.NoError(err) - n, err := types.Get("") + n, err := types.Get(testCtx, "") require.Error(err) assert.Equal(n, nil) assert.Equal("oplog.(TypeCatalog).Get: missing type name: parameter violation: error #100", err.Error()) @@ -178,24 +180,25 @@ func Test_Get(t *testing.T) { // Test_Set provides unit tests for Set func Test_Set(t *testing.T) { t.Parallel() + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog() + types, err := NewTypeCatalog(testCtx) require.NoError(err) u := new(oplog_test.TestUser) - err = types.Set(u, "user") + err = types.Set(testCtx, u, "user") require.NoError(err) assert.Equal(reflect.TypeOf(u), reflect.TypeOf(new(oplog_test.TestUser))) }) t.Run("bad name", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog() + types, err := NewTypeCatalog(testCtx) require.NoError(err) u := new(oplog_test.TestUser) - err = types.Set(u, "") + err = types.Set(testCtx, u, "") require.Error(err) assert.Equal("oplog.(TypeCatalog).Set: missing type name: parameter violation: error #100", err.Error()) assert.Equal(types, &TypeCatalog{}) @@ -203,9 +206,9 @@ func Test_Set(t *testing.T) { t.Run("bad interface", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - types, err := NewTypeCatalog() + types, err := NewTypeCatalog(testCtx) require.NoError(err) - err = types.Set(nil, "") + err = types.Set(testCtx, nil, "") require.Error(err) assert.Equal("oplog.(TypeCatalog).Set: nil interface: parameter violation: error #100", err.Error()) assert.Equal(types, &TypeCatalog{}) diff --git a/internal/oplog/writer.go b/internal/oplog/writer.go index d175ce7f6..4fe321ea5 100644 --- a/internal/oplog/writer.go +++ b/internal/oplog/writer.go @@ -1,133 +1,41 @@ package oplog import ( + "context" "fmt" - "github.com/hashicorp/boundary/internal/db/common" + "github.com/hashicorp/go-dbw" "github.com/hashicorp/boundary/internal/errors" - "gorm.io/gorm" - "gorm.io/gorm/schema" ) -// Writer interface for Entries -type Writer interface { - // Create the entry - Create(interface{}) error - - // Update the entry using the fieldMaskPaths and setNullPaths, which are - // Paths from field_mask.proto. fieldMaskPaths is required. setToNullPaths - // is optional. fieldMaskPaths and setNullPaths cannot instersect and both - // cannot be zero len. - Update(entry interface{}, fieldMaskPaths, setToNullPaths []string) error - - // Delete the entry - Delete(interface{}) error - - // HasTable checks if tableName exists - hasTable(tableName string) bool - - // CreateTableLike will create a newTableName using the existing table as a - // starting point - createTableLike(existingTableName string, newTableName string) error - - // DropTableIfExists will drop the table if it exists - dropTableIfExists(tableName string) error -} - -// GormWriter uses a gorm DB connection for writing -type GormWriter struct { - Tx *gorm.DB -} - -// Create an object in storage -func (w *GormWriter) Create(i interface{}) error { - const op = "oplog.(GormWriter).Create" - if w.Tx == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil tx") - } - if i == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") - } - - 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 -} - -// Update the entry using the fieldMaskPaths and setNullPaths, which are -// Paths from field_mask.proto. fieldMaskPaths and setNullPaths cannot -// intersect and both cannot be zero len. -func (w *GormWriter) Update(i interface{}, fieldMaskPaths, setToNullPaths []string) error { - const op = "oplog.(GormWriter).Update" - if w.Tx == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil tx") - } - if i == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") - } - if len(fieldMaskPaths) == 0 && len(setToNullPaths) == 0 { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing field mask paths and set to null paths") - } - // common.UpdateFields will also check to ensure that fieldMaskPaths and - // setToNullPaths do not intersect. - updateFields, err := common.UpdateFields(i, fieldMaskPaths, setToNullPaths) - if err != nil { - return errors.WrapDeprecated(err, op, errors.WithMsg("unable to build update fields")) - } - - 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 -} - -// Deleting an object in storage -func (w *GormWriter) Delete(i interface{}) error { - const op = "oplog.(GormWriter).Delete" - if w.Tx == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil tx") - } - if i == nil { - return errors.NewDeprecated(errors.InvalidParameter, op, "nil interface") - } - 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 +// Writer provides a database writer for oplog operations +type Writer struct { + *dbw.DB } // HasTable checks if tableName exists -func (w *GormWriter) hasTable(tableName string) bool { +func (w *Writer) hasTable(ctx context.Context, tableName string) (bool, error) { + const op = "oplog.(Writer).hasTable" if tableName == "" { - return false + return false, errors.New(ctx, errors.InvalidParameter, op, "missing table name") } - return w.Tx.Migrator().HasTable(tableName) + var count int64 + rw := dbw.New(w.DB) + rows, err := rw.Query(context.Background(), "select count(*) from information_schema.tables where table_name = ? and table_type = ?", []interface{}{tableName, "BASE TABLE"}) + if err != nil { + return false, errors.Wrap(ctx, err, op) + } + if ok := rows.Next(); ok { + rw.ScanRows(rows, &count) + } + return count > 0, nil } // CreateTableLike will create a newTableName like the model's table // the new table should have all things like the existing model's table (defaults, constraints, indexes, etc) -func (w *GormWriter) createTableLike(existingTableName string, newTableName string) error { - const op = "oplog.(GormWriter).createTableLike" +func (w *Writer) createTableLike(ctx context.Context, existingTableName string, newTableName string) error { + const op = "oplog.(Writer).createTableLike" if existingTableName == "" { return errors.NewDeprecated(errors.InvalidParameter, op, "missing existing table name") } @@ -135,41 +43,28 @@ func (w *GormWriter) createTableLike(existingTableName string, newTableName stri return errors.NewDeprecated(errors.InvalidParameter, op, "missing new table name") } - existingTableName = w.Tx.Statement.Quote(existingTableName) - newTableName = w.Tx.Statement.Quote(newTableName) - var sql string - switch w.Tx.Dialector.Name() { - case "postgres": - sql = fmt.Sprintf( - `CREATE TABLE %s ( LIKE %s INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES );`, - newTableName, - existingTableName, - ) - case "mysql": - sql = fmt.Sprintf("CREATE TABLE %s LIKE %s", - newTableName, - existingTableName, - ) - default: - return errors.NewDeprecated(errors.InvalidParameter, op, "unsupported RDBMS") - } - err := w.Tx.Exec(sql).Error + sql := fmt.Sprintf( + `CREATE TABLE "%s" ( LIKE %s INCLUDING ALL );`, + newTableName, + existingTableName, + ) + _, err := dbw.New(w.DB).Exec(ctx, sql, nil) if err != nil { - return errors.WrapDeprecated(err, op) + return errors.Wrap(ctx, err, op) } return nil } // DropTableIfExists will drop the table if it exists -func (w *GormWriter) dropTableIfExists(tableName string) error { - const op = "oplog.(GormWriter).dropTableIfExists" +func (w *Writer) dropTableIfExists(ctx context.Context, tableName string) error { + const op = "oplog.(Writer).dropTableIfExists" if tableName == "" { - return errors.NewDeprecated(errors.InvalidParameter, op, "missing table name") + return errors.New(ctx, errors.InvalidParameter, op, "missing table name") } - // Migrator.DropTable uses an "if exists" clause - err := w.Tx.Migrator().DropTable(tableName) + sql := fmt.Sprintf("drop table if exists %s ", tableName) + _, err := dbw.New(w.DB).Exec(ctx, sql, nil) if err != nil { - return errors.WrapDeprecated(err, op) + return errors.Wrap(ctx, err, op) } return nil } diff --git a/internal/oplog/writer_test.go b/internal/oplog/writer_test.go index f3930d722..ef67f8676 100644 --- a/internal/oplog/writer_test.go +++ b/internal/oplog/writer_test.go @@ -1,194 +1,199 @@ package oplog import ( + "context" "testing" "github.com/hashicorp/boundary/internal/oplog/oplog_test" dbassert "github.com/hashicorp/dbassert/gorm" + "github.com/hashicorp/go-dbw" "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 -func Test_GormWriterCreate(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) +// Test_WriterCreate provides unit tests for Writer Create +func Test_WriterCreate(t *testing.T) { + db := setup(t) + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - tx := db.Begin() - defer tx.Rollback() - w := GormWriter{tx} + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Rollback(testCtx) + w := Writer{tx.DB()} user := oplog_test.TestUser{ Name: "foo-" + testId(t), } - require.NoError(w.Create(&user)) + require.NoError(dbw.New(w.DB).Create(testCtx, &user)) - foundUser := testFindUser(t, tx, user.Id) + foundUser := testFindUser(t, tx.DB(), user.Id) assert.Equal(user.Name, foundUser.Name) }) t.Run("nil tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{nil} + w := Writer{} - err := w.Create(&oplog_test.TestUser{}) + err := dbw.New(w.DB).Create(testCtx, &oplog_test.TestUser{}) require.Error(err) - - assert.Equal("oplog.(GormWriter).Create: nil tx: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), " missing underlying db: invalid parameter") }) t.Run("nil model", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - tx := db.Begin() - defer tx.Rollback() - w := GormWriter{tx} - err := w.Create(nil) + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Rollback(testCtx) + w := Writer{tx.DB()} + err = dbw.New(w.DB).Create(testCtx, nil) require.Error(err) - assert.Equal("oplog.(GormWriter).Create: nil interface: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing interface") }) } -// Test_GormWriterDelete provides unit tests for GormWriter Delete -func Test_GormWriterDelete(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) +// Test_WriterDelete provides unit tests for Writer Delete +func Test_WriterDelete(t *testing.T) { + db := setup(t) + testCtx := context.Background() t.Run("valid", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - tx := db.Begin() - defer tx.Rollback() - w := GormWriter{tx} + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Rollback(testCtx) + w := Writer{tx.DB()} id := testId(t) user := testUser(t, db, "foo-"+id, "", "") foundUser := testFindUser(t, db, user.Id) - require.NoError(w.Delete(&user)) - err := tx.Where("id = ?", user.Id).First(&foundUser).Error + _, err = dbw.New(w.DB).Delete(testCtx, &user) + require.NoError(err) + err = dbw.New(w.DB).LookupWhere(testCtx, &foundUser, "id = ?", []interface{}{user.Id}) require.Error(err) - assert.Equal(gorm.ErrRecordNotFound, err) + assert.ErrorIs(err, dbw.ErrRecordNotFound) }) t.Run("nil tx", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{nil} - err := w.Delete(&oplog_test.TestUser{}) + w := Writer{} + _, err := dbw.New(w.DB).Delete(testCtx, &oplog_test.TestUser{}) require.Error(err) - assert.Equal("oplog.(GormWriter).Delete: nil tx: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing underlying db") }) t.Run("nil model", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - tx := db.Begin() - defer tx.Rollback() - w := GormWriter{tx} - err := w.Delete(nil) + tx, err := dbw.New(db).Begin(testCtx) + require.NoError(err) + defer tx.Rollback(testCtx) + w := Writer{tx.DB()} + _, err = dbw.New(w.DB).Delete(testCtx, nil) require.Error(err) - assert.Equal("oplog.(GormWriter).Delete: nil interface: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing interface") }) } -// Test_GormWriterHasTable provides unit tests for GormWriter HasTable -func Test_GormWriterHasTable(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) - w := GormWriter{Tx: db} +// TestWriter_hasTable provides unit tests for Writer HasTable +func TestWriter_hasTable(t *testing.T) { + db := setup(t) + testCtx := context.Background() + w := Writer{db} t.Run("success", func(t *testing.T) { assert := require.New(t) - ok := w.hasTable("oplog_test_user") - assert.Equal(ok, true) + ok, _ := w.hasTable(testCtx, "oplog_test_user") + assert.Equal(true, ok) }) t.Run("no table", func(t *testing.T) { assert := assert.New(t) badTableName := testId(t) - ok := w.hasTable(badTableName) + ok, _ := w.hasTable(testCtx, badTableName) assert.Equal(ok, false) }) t.Run("blank table name", func(t *testing.T) { assert := assert.New(t) - ok := w.hasTable("") + ok, _ := w.hasTable(testCtx, "") assert.Equal(ok, false) }) } -// Test_GormWriterCreateTable provides unit tests for GormWriter CreateTable -func Test_GormWriterCreateTable(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) +// TestWriter_createTableLike provides unit tests for Writer createTable +func TestWriter_createTableLike(t *testing.T) { + db := setup(t) + testCtx := context.Background() t.Run("success", func(t *testing.T) { assert := assert.New(t) - w := GormWriter{Tx: db} + w := Writer{db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix - defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() - err := w.createTableLike(u.TableName(), newTableName) + defer func() { assert.NoError(w.dropTableIfExists(testCtx, newTableName)) }() + err := w.createTableLike(testCtx, u.TableName(), newTableName) assert.NoError(err) }) t.Run("call twice", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{Tx: db} + w := Writer{db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix - defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() - err := w.createTableLike(u.TableName(), newTableName) + defer func() { assert.NoError(w.dropTableIfExists(testCtx, newTableName)) }() + err := w.createTableLike(testCtx, u.TableName(), newTableName) require.NoError(err) // should be an error to create the same table twice - err = w.createTableLike(u.TableName(), newTableName) + err = w.createTableLike(testCtx, u.TableName(), newTableName) require.Error(err) assert.Error(err, err.Error(), nil) }) t.Run("empty existing", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{Tx: db} + w := Writer{db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix - defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() - err := w.createTableLike("", newTableName) + defer func() { assert.NoError(w.dropTableIfExists(testCtx, newTableName)) }() + err := w.createTableLike(testCtx, "", newTableName) require.Error(err) assert.Error(err, err.Error(), nil) - assert.Equal("oplog.(GormWriter).createTableLike: missing existing table name: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing existing table name") }) t.Run("blank name", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{Tx: db} + w := Writer{db} u := &oplog_test.TestUser{} - err := w.createTableLike(u.TableName(), "") + err := w.createTableLike(testCtx, u.TableName(), "") require.Error(err) assert.Error(err, err.Error(), nil) - assert.Equal("oplog.(GormWriter).createTableLike: missing new table name: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing new table name") }) } -// Test_GormWriterDropTableIfExists provides unit tests for GormWriter DropTableIfExists -func Test_GormWriterDropTableIfExists(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) +// Test_WriterDropTableIfExists provides unit tests for Writer dropTableIfExists +func Test_WriterDropTableIfExists(t *testing.T) { + testCtx := context.Background() + db := setup(t) t.Run("success", func(t *testing.T) { assert := assert.New(t) - w := GormWriter{Tx: db} + w := Writer{db} suffix := testId(t) u := &oplog_test.TestUser{} newTableName := u.TableName() + "_" + suffix - assert.NoError(w.createTableLike(u.TableName(), newTableName)) - defer func() { assert.NoError(w.dropTableIfExists(newTableName)) }() + assert.NoError(w.createTableLike(testCtx, u.TableName(), newTableName)) + defer func() { assert.NoError(w.dropTableIfExists(testCtx, newTableName)) }() }) t.Run("success with blank", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - w := GormWriter{Tx: db} - err := w.dropTableIfExists("") + w := Writer{db} + err := w.dropTableIfExists(testCtx, "") require.Error(err) - assert.Equal("oplog.(GormWriter).dropTableIfExists: missing table name: parameter violation: error #100", err.Error()) + assert.Contains(err.Error(), "missing table name") }) } -func TestGormWriter_Update(t *testing.T) { - cleanup, db := setup(t) - defer testCleanup(t, cleanup, db) +func TestWriter_Update(t *testing.T) { + db := setup(t) id := testId(t) type fields struct { Tx *gorm.DB @@ -200,7 +205,7 @@ func TestGormWriter_Update(t *testing.T) { } tests := []struct { name string - Tx *gorm.DB + Tx *dbw.DB args args wantUser *oplog_test.TestUser wantErr bool @@ -218,6 +223,7 @@ func TestGormWriter_Update(t *testing.T) { Name: "valid-fieldmask", Email: id, PhoneNumber: id, + Version: 2, }, wantErr: false, }, @@ -235,6 +241,7 @@ func TestGormWriter_Update(t *testing.T) { Name: "", Email: id, PhoneNumber: id, + Version: 2, }, wantErr: false, }, @@ -252,6 +259,7 @@ func TestGormWriter_Update(t *testing.T) { Name: "", Email: "valid-setToNull-and-fieldMask", PhoneNumber: id, + Version: 2, }, wantErr: false, }, @@ -292,26 +300,28 @@ func TestGormWriter_Update(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - underlyingDB, err := db.DB() + underlyingDB, err := db.SqlDB(context.Background()) require.NoError(err) - dbassert := dbassert.New(t, underlyingDB, db.Dialector.Name()) + _, name, err := db.DbType() + require.NoError(err) + dbassert := dbassert.New(t, underlyingDB, name) - w := &GormWriter{ - Tx: tt.Tx, + w := &Writer{ + tt.Tx, } - u := testUser(t, db, id, id, id) // intentionally, not relying on tt.Tx + u := testUser(t, db, tt.name+id, id, id) // intentionally, not relying on tt.Tx u.Name = tt.args.user.Name u.Email = tt.args.user.Email u.PhoneNumber = tt.args.user.PhoneNumber - err = w.Update(u, tt.args.fieldMaskPaths, tt.args.setToNullPaths) + _, err = dbw.New(w.DB).Update(context.Background(), u, tt.args.fieldMaskPaths, tt.args.setToNullPaths) if tt.wantErr { require.Error(err) return } require.NoError(err) var foundUser oplog_test.TestUser - err = db.Where("id = ?", u.Id).First(&foundUser).Error - require.NoError(err) + foundUser.Id = u.Id + require.NoError(dbw.New(db).LookupBy(context.Background(), &foundUser)) tt.wantUser.Id = u.Id assert.Equal(tt.wantUser, &foundUser) for _, f := range tt.args.setToNullPaths { @@ -321,8 +331,8 @@ func TestGormWriter_Update(t *testing.T) { } t.Run("nil model", func(t *testing.T) { assert := assert.New(t) - w := GormWriter{db} - err := w.Create(nil) + w := Writer{db} + err := dbw.New(w.DB).Create(context.Background(), nil) assert.Error(err) }) } diff --git a/internal/plugin/host/repository_plugin.go b/internal/plugin/host/repository_plugin.go index 414840465..8babbcc7f 100644 --- a/internal/plugin/host/repository_plugin.go +++ b/internal/plugin/host/repository_plugin.go @@ -112,7 +112,7 @@ func (r *Repository) LookupPluginByName(ctx context.Context, name string, _ ...O } p := allocPlugin() - if err := r.reader.LookupWhere(ctx, p, "name=?", name); err != nil { + if err := r.reader.LookupWhere(ctx, p, "name=?", []interface{}{name}); err != nil { if errors.IsNotFoundError(err) { return nil, nil } diff --git a/internal/proto/local/controller/storage/oplog/test/v1/oplog_test.proto b/internal/proto/local/controller/storage/oplog/test/v1/oplog_test.proto index aa5813e2c..102a2f5ea 100644 --- a/internal/proto/local/controller/storage/oplog/test/v1/oplog_test.proto +++ b/internal/proto/local/controller/storage/oplog/test/v1/oplog_test.proto @@ -11,6 +11,8 @@ message TestUser { string name = 4; string phone_number = 5; string email = 6; + // @inject_tag: gorm:"default:null" + uint32 version = 9; // @inject_tag: gorm:"-" json:"-" string table = 7; } diff --git a/internal/proto/local/controller/storage/oplog/v1/any_operation.proto b/internal/proto/local/controller/storage/oplog/v1/any_operation.proto index fe52fd37c..76fa6943f 100644 --- a/internal/proto/local/controller/storage/oplog/v1/any_operation.proto +++ b/internal/proto/local/controller/storage/oplog/v1/any_operation.proto @@ -1,6 +1,8 @@ syntax = "proto3"; import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; package controller.storage.oplog.v1; option go_package = "github.com/hashicorp/boundary/internal/oplog;oplog"; @@ -19,6 +21,12 @@ enum OpType { // OP_TYPE_DELETE defines a delete operation. OP_TYPE_DELETE = 3; + + // OP_TYPE_CREATE_ITEMS defines a create operation for multiple items. + OP_TYPE_CREATE_ITEMS = 4; + + // OP_TYPE_DELETE_ITEMS defines a delete operation for multiple items. + OP_TYPE_DELETE_ITEMS = 5; } // AnyOperation provides a message for anything and the type of operation it @@ -38,4 +46,95 @@ message AnyOperation { // null_mask is the mask of fields to set to null. google.protobuf.FieldMask null_mask = 5; + + // Options for the operations (see dbw package for definition/documentation of + // options) + OperationOptions options = 6; +} + +// OperationOptions represent operations options which can/will affect the oplog write +// operation. These options are a subset of the dbw.Options. We will not try to +// keep the docs in-sync from the dbw package, so if you need more information +// on what the option does please see the dbw package docs. +message OperationOptions { + // with_version (see dbw package for docs) + google.protobuf.UInt32Value with_version = 1; + + // with_skip_vet_for_write (see dbw package for docs) + bool with_skip_vet_for_write = 2; + + // with_where_clause (see dbw package for docs) + string with_where_clause = 3; + + // with_where_clause_args (see dbw package for docs) + repeated google.protobuf.Value with_where_clause_args = 4; + + // with_on_conflict (see dbw package for docs) + WithOnConflict with_on_conflict = 5; +} + +// WithOnConflict defines the parameters needed for an sql "on conflict clause" +message WithOnConflict { + // target defines the on conflict target + oneof target { + // constraint is the on conflict constraint + string constraint = 10; + + // columns are the on conflict columns + Columns columns = 11; + }; + + // action defines the on conflict action + oneof action { + // do_nothing defines an on conflict action of do nothing + bool do_nothing = 50; + + // update_all defines an on conflict action of updating all the columns + bool update_all = 51; + + // column_values defines on conflict action with the columns to update + ColumnValues column_values = 52; + }; +} + +// Columns defines a set of column properties +message Columns { + // name of the columns + repeated string names = 1; +} + +// ColumnValue defines a column value +message ColumnValue { + // name of the column + string name = 1; + + // value of the column + oneof value { + google.protobuf.Value raw = 2; + ExprValue expr_value = 3; + Column column = 4; + }; +} + +// ColumnValues defines a set of column value properies +message ColumnValues { + // values are the values of the columns + repeated ColumnValue values = 1; +} + +// ExprValue defines an expr value that can be used as a column value +message ExprValue { + // sql is the sql clause of the expr + string sql = 1; + + // args are the sql args of the expr + repeated google.protobuf.Value args = 2; +} + +// Column represents a table Column +message Column { + // name of the column + string name = 1; + // table name of the column + string table = 2; } \ No newline at end of file diff --git a/internal/scheduler/job.go b/internal/scheduler/job.go index a932b3faf..447bcdd9f 100644 --- a/internal/scheduler/job.go +++ b/internal/scheduler/job.go @@ -22,7 +22,7 @@ type Job interface { // is being persisted by the scheduler. If an error is returned, the error will be logged // but the duration returned will still be used in scheduling. If a zero duration is returned // the job will be scheduled to run again immediately. - NextRunIn() (time.Duration, error) + NextRunIn(context.Context) (time.Duration, error) // Name is the unique name of the job. Name() string diff --git a/internal/scheduler/job/repository_job.go b/internal/scheduler/job/repository_job.go index 8ef11d117..3aa642110 100644 --- a/internal/scheduler/job/repository_job.go +++ b/internal/scheduler/job/repository_job.go @@ -51,7 +51,7 @@ func (r *Repository) CreateJob(ctx context.Context, name, description string, op return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job would have been created", errors.WithoutEvent()) } rowCnt++ - err = r.ScanRows(rows, j) + err = r.ScanRows(ctx, rows, j) if err != nil { _ = rows.Close() return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job"), errors.WithoutEvent()) @@ -100,7 +100,7 @@ func (r *Repository) UpdateJobNextRunInAtLeast(ctx context.Context, name string, return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job would have been updated") } rowCnt++ - err = r.ScanRows(rows, j) + err = r.ScanRows(ctx, rows, j) if err != nil { _ = rows.Close() return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows")) diff --git a/internal/scheduler/job/repository_run.go b/internal/scheduler/job/repository_run.go index fb305e5a8..0c630b332 100644 --- a/internal/scheduler/job/repository_run.go +++ b/internal/scheduler/job/repository_run.go @@ -34,7 +34,7 @@ func (r *Repository) RunJobs(ctx context.Context, serverId string, opt ...Option for rows.Next() { run := allocRun() - err = r.ScanRows(rows, run) + err = r.ScanRows(ctx, rows, run) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job run")) } @@ -77,7 +77,7 @@ func (r *Repository) UpdateProgress(ctx context.Context, runId string, completed return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job run would have been updated") } rowCnt++ - err = r.ScanRows(rows, run) + err = r.ScanRows(ctx, rows, run) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job run")) } @@ -141,7 +141,7 @@ func (r *Repository) CompleteRun(ctx context.Context, runId string, nextRunIn ti return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job run would have been updated") } rowCnt++ - err = r.ScanRows(rows, run) + err = r.ScanRows(ctx, rows, run) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job run")) } @@ -171,7 +171,7 @@ func (r *Repository) CompleteRun(ctx context.Context, runId string, nextRunIn ti return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job would have been updated") } rowCnt++ - err = r.ScanRows(rows1, job) + err = r.ScanRows(ctx, rows1, job) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job")) } @@ -221,7 +221,7 @@ func (r *Repository) FailRun(ctx context.Context, runId string, completed, total return errors.New(ctx, errors.MultipleRecords, op, "more than 1 job run would have been updated") } rowCnt++ - err = r.ScanRows(rows, run) + err = r.ScanRows(ctx, rows, run) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job run")) } @@ -281,7 +281,7 @@ func (r *Repository) InterruptRuns(ctx context.Context, interruptThreshold time. for rows.Next() { run := allocRun() - err = r.ScanRows(rows, run) + err = r.ScanRows(ctx, rows, run) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to scan rows for job run")) } diff --git a/internal/scheduler/job/repository_run_test.go b/internal/scheduler/job/repository_run_test.go index 8cd810298..e72022423 100644 --- a/internal/scheduler/job/repository_run_test.go +++ b/internal/scheduler/job/repository_run_test.go @@ -70,7 +70,7 @@ func TestRepository_RunJobs(t *testing.T) { }, wantErr: true, wantErrCode: errors.NotSpecificIntegrity, - wantErrMsg: "job.(Repository).RunJobs: db.DoTx: job.(Repository).RunJobs: insert or update on table \"job_run\" violates foreign key constraint \"server_fkey\": integrity violation: error #1003", + wantErrMsg: "job.(Repository).RunJobs: db.DoTx: job.(Repository).RunJobs: db.Query: insert or update on table \"job_run\" violates foreign key constraint \"server_fkey\": integrity violation: error #1003", }, } for _, tt := range tests { @@ -373,7 +373,7 @@ func TestRepository_UpdateProgress(t *testing.T) { }, wantErr: true, wantErrCode: errors.CheckConstraint, - wantErrMsg: "job.(Repository).UpdateProgress: db.DoTx: job.(Repository).UpdateProgress: job_run_completed_count_less_than_equal_to_total_count constraint failed: check constraint violated: integrity violation: error #1000", + wantErrMsg: "job.(Repository).UpdateProgress: db.DoTx: job.(Repository).UpdateProgress: db.Query: job_run_completed_count_less_than_equal_to_total_count constraint failed: check constraint violated: integrity violation: error #1000", }, } @@ -430,7 +430,7 @@ func TestRepository_UpdateProgress(t *testing.T) { require.Error(err) require.Nil(got) assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "Unexpected error %s", err) - assert.Equal("job.(Repository).UpdateProgress: db.DoTx: job.(Repository).UpdateProgress: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100", err.Error()) + assert.Equal("job.(Repository).UpdateProgress: db.DoTx: job.(Repository).UpdateProgress: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100: dbw.LookupById: record not found", err.Error()) }) } @@ -595,7 +595,7 @@ func TestRepository_CompleteRun(t *testing.T) { require.Error(err) require.Nil(got) assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "Unexpected error %s", err) - assert.Equal("job.(Repository).CompleteRun: db.DoTx: job.(Repository).CompleteRun: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100", err.Error()) + assert.Equal("job.(Repository).CompleteRun: db.DoTx: job.(Repository).CompleteRun: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100: dbw.LookupById: record not found", err.Error()) }) } @@ -747,7 +747,7 @@ func TestRepository_FailRun(t *testing.T) { require.Error(err) require.Nil(got) assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "Unexpected error %s", err) - assert.Equal("job.(Repository).FailRun: db.DoTx: job.(Repository).FailRun: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100", err.Error()) + assert.Equal("job.(Repository).FailRun: db.DoTx: job.(Repository).FailRun: job run \"fake-run-id\" does not exist: db.LookupById: record not found, search issue: error #1100: dbw.LookupById: record not found", err.Error()) }) } diff --git a/internal/scheduler/job/testing.go b/internal/scheduler/job/testing.go index bd192c93e..42af2b007 100644 --- a/internal/scheduler/job/testing.go +++ b/internal/scheduler/job/testing.go @@ -40,8 +40,8 @@ func testRun(conn *db.DB, pluginId, name, cId string) (*Run, error) { ` rw := db.New(conn) run := allocRun() - - rows, err := rw.Query(context.Background(), query, []interface{}{pluginId, name, cId}) + ctx := context.Background() + rows, err := rw.Query(ctx, query, []interface{}{pluginId, name, cId}) if err != nil { return nil, err } @@ -49,7 +49,7 @@ func testRun(conn *db.DB, pluginId, name, cId string) (*Run, error) { return nil, fmt.Errorf("expected to rows") } - err = rw.ScanRows(rows, run) + err = rw.ScanRows(ctx, rows, run) if err != nil { return nil, err } @@ -68,8 +68,8 @@ func testRunWithUpdateTime(conn *db.DB, pluginId, name, cId string, updateTime t ` rw := db.New(conn) run := allocRun() - - rows, err := rw.Query(context.Background(), query, []interface{}{pluginId, name, cId, updateTime}) + ctx := context.Background() + rows, err := rw.Query(ctx, query, []interface{}{pluginId, name, cId, updateTime}) if err != nil { return nil, err } @@ -77,7 +77,7 @@ func testRunWithUpdateTime(conn *db.DB, pluginId, name, cId string, updateTime t return nil, fmt.Errorf("expected to rows") } - err = rw.ScanRows(rows, run) + err = rw.ScanRows(ctx, rows, run) if err != nil { return nil, err } diff --git a/internal/scheduler/job/testing_test.go b/internal/scheduler/job/testing_test.go index 183a8b71a..cd3e6ddd4 100644 --- a/internal/scheduler/job/testing_test.go +++ b/internal/scheduler/job/testing_test.go @@ -23,7 +23,7 @@ func Test_TestJob(t *testing.T) { rw := db.New(conn) var got Job - err := rw.LookupWhere(context.Background(), &got, "name = ?", job.Name) + err := rw.LookupWhere(context.Background(), &got, "name = ?", []interface{}{job.Name}) require.NoError(err) assert.Equal("testJob", got.Name) assert.Equal("testDescription", got.Description) @@ -34,7 +34,7 @@ func Test_TestJob(t *testing.T) { require.NotNil(job1) var got1 Job - err = rw.LookupWhere(context.Background(), &got1, "name = ?", job1.Name) + err = rw.LookupWhere(context.Background(), &got1, "name = ?", []interface{}{job1.Name}) require.NoError(err) assert.Equal("testJob1", got1.Name) assert.Equal("testDescription1", got1.Description) @@ -66,7 +66,7 @@ func Test_TestRun(t *testing.T) { rw := db.New(conn) var got Run - err = rw.LookupWhere(context.Background(), &got, "private_id = ?", run.PrivateId) + err = rw.LookupWhere(context.Background(), &got, "private_id = ?", []interface{}{run.PrivateId}) require.NoError(err) assert.Equal(server.PrivateId, got.ServerId) assert.Equal(job.Name, got.JobName) diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go index 00daa022e..dcc7ecef8 100644 --- a/internal/scheduler/scheduler.go +++ b/internal/scheduler/scheduler.go @@ -238,7 +238,7 @@ func (s *Scheduler) runJob(ctx context.Context, wg *sync.WaitGroup, r *job.Run) case ctx.Err() != nil: // Base context is no longer valid, skip repo updates as they will fail and exit case runErr == nil: - nextRun, inner := j.NextRunIn() + nextRun, inner := j.NextRunIn(ctx) if inner != nil { event.WriteError(ctx, op, inner, event.WithInfoMsg("error getting next run time", "name", j.Name())) } diff --git a/internal/scheduler/scheduler_test.go b/internal/scheduler/scheduler_test.go index ce40b9cc8..6f25524ff 100644 --- a/internal/scheduler/scheduler_test.go +++ b/internal/scheduler/scheduler_test.go @@ -367,7 +367,6 @@ func TestScheduler_Start(t *testing.T) { wantErr bool wantErrContains string }{ - { name: "missing-ctx", wg: &sync.WaitGroup{}, diff --git a/internal/scheduler/testing.go b/internal/scheduler/testing.go index 71646d7d0..34303859a 100644 --- a/internal/scheduler/testing.go +++ b/internal/scheduler/testing.go @@ -84,7 +84,7 @@ func (j testJob) Run(ctx context.Context) error { return j.fn(ctx) } -func (j testJob) NextRunIn() (time.Duration, error) { +func (j testJob) NextRunIn(_ context.Context) (time.Duration, error) { return j.nextRunIn, nil } diff --git a/internal/servers/controller/controller_test.go b/internal/servers/controller/controller_test.go index c6449ee8b..c3bef2e3b 100644 --- a/internal/servers/controller/controller_test.go +++ b/internal/servers/controller/controller_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/kms" "github.com/stretchr/testify/require" ) @@ -26,7 +27,7 @@ func TestController_New(t *testing.T) { require.NoError(err) // this tests a scenario where there is NOT an audit DEK - require.NoError(c.conf.Server.Database.Where("1=1").Delete(kms.AllocAuditKey()).Error) + db.TestDeleteWhere(t, c.conf.Server.Database, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") _, err = New(testCtx, conf) require.NoError(err) }) diff --git a/internal/servers/controller/interceptor.go b/internal/servers/controller/interceptor.go index cd246b99e..6cbca4e28 100644 --- a/internal/servers/controller/interceptor.go +++ b/internal/servers/controller/interceptor.go @@ -150,8 +150,8 @@ func errorInterceptor( return func(interceptorCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - + handler grpc.UnaryHandler) (interface{}, error, + ) { // call the handler... h, handlerErr := handler(interceptorCtx, req) @@ -201,8 +201,8 @@ func statusCodeInterceptor( return func(interceptorCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - + handler grpc.UnaryHandler) (interface{}, error, + ) { // call the handler... h, handlerErr := handler(interceptorCtx, req) @@ -237,8 +237,8 @@ func auditRequestInterceptor( return func(interceptorCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - + handler grpc.UnaryHandler) (interface{}, error, + ) { if msg, ok := req.(proto.Message); ok { if err := event.WriteAudit(interceptorCtx, op, event.WithRequest(&event.Request{Details: msg})); err != nil { return req, status.Errorf(codes.Internal, "unable to write request msg audit: %s", err) @@ -256,8 +256,8 @@ func auditResponseInterceptor( return func(interceptorCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - + handler grpc.UnaryHandler) (interface{}, error, + ) { // call the handler... resp, err := handler(interceptorCtx, req) diff --git a/internal/servers/controller/interceptor_test.go b/internal/servers/controller/interceptor_test.go index 922e762d3..87a23c81f 100644 --- a/internal/servers/controller/interceptor_test.go +++ b/internal/servers/controller/interceptor_test.go @@ -492,7 +492,6 @@ func Test_workerRequestInfoInterceptor(t *testing.T) { wantRequestErrMatch *errors.Template wantRequestErrContains string }{ - { name: "missing-eventer", requestCtx: requestCtx, diff --git a/internal/servers/controller/session_cleanup_job.go b/internal/servers/controller/session_cleanup_job.go index 1eadb5189..a74d92ce3 100644 --- a/internal/servers/controller/session_cleanup_job.go +++ b/internal/servers/controller/session_cleanup_job.go @@ -68,7 +68,9 @@ func (j *sessionCleanupJob) Description() string { // connections as soon as a worker has not reported in for a long // enough time. Only one job will ever run at once, so there is no // reason why it cannot run again immediately. -func (j *sessionCleanupJob) NextRunIn() (time.Duration, error) { return time.Second, nil } +func (j *sessionCleanupJob) NextRunIn(_ context.Context) (time.Duration, error) { + return time.Second, nil +} // Status returns the status of the running job. func (j *sessionCleanupJob) Status() scheduler.JobStatus { diff --git a/internal/session/connection_state_test.go b/internal/session/connection_state_test.go index 32758d3d8..6250abcd2 100644 --- a/internal/session/connection_state_test.go +++ b/internal/session/connection_state_test.go @@ -126,7 +126,7 @@ func TestConnectionState_Delete(t *testing.T) { assert, require := assert.New(t), require.New(t) var initialState ConnectionState - err := rw.LookupWhere(context.Background(), &initialState, "connection_id = ? and state = ?", tt.state.ConnectionId, tt.state.Status) + err := rw.LookupWhere(context.Background(), &initialState, "connection_id = ? and state = ?", []interface{}{tt.state.ConnectionId, tt.state.Status}) require.NoError(err) deleteState := allocConnectionState() @@ -148,7 +148,7 @@ func TestConnectionState_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) foundState := allocConnectionState() - err = rw.LookupWhere(context.Background(), &foundState, "connection_id = ? and start_time = ?", tt.state.ConnectionId, initialState.StartTime) + err = rw.LookupWhere(context.Background(), &foundState, "connection_id = ? and start_time = ?", []interface{}{tt.state.ConnectionId, initialState.StartTime}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) diff --git a/internal/session/immutable_fields_test.go b/internal/session/immutable_fields_test.go index 13ec1d1b4..319fffef8 100644 --- a/internal/session/immutable_fields_test.go +++ b/internal/session/immutable_fields_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" - "gorm.io/gorm/logger" ) func TestSession_ImmutableFields(t *testing.T) { @@ -103,7 +102,7 @@ func TestState_ImmutableFields(t *testing.T) { state := TestState(t, conn, session.PublicId, StatusPending) var new State - err := rw.LookupWhere(context.Background(), &new, "session_id = ? and state = ?", state.SessionId, state.Status) + err := rw.LookupWhere(context.Background(), &new, "session_id = ? and state = ?", []interface{}{state.SessionId, state.Status}) require.NoError(t, err) tests := []struct { @@ -153,7 +152,7 @@ func TestState_ImmutableFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() - err := rw.LookupWhere(context.Background(), orig, "session_id = ? and start_time = ?", new.SessionId, new.StartTime) + err := rw.LookupWhere(context.Background(), orig, "session_id = ? and start_time = ?", []interface{}{new.SessionId, new.StartTime}) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) @@ -161,7 +160,7 @@ func TestState_ImmutableFields(t *testing.T) { assert.Equal(0, rowsUpdated) after := new.Clone() - err = rw.LookupWhere(context.Background(), after, "session_id = ? and start_time = ?", new.SessionId, new.StartTime) + err = rw.LookupWhere(context.Background(), after, "session_id = ? and start_time = ?", []interface{}{new.SessionId, new.StartTime}) require.NoError(err) assert.Equal(orig.(*State), after) }) @@ -250,11 +249,9 @@ func TestConnectionState_ImmutableFields(t *testing.T) { state := TestConnectionState(t, conn, connection.PublicId, StatusConnected) var new ConnectionState - err := rw.LookupWhere(context.Background(), &new, "connection_id = ? and state = ?", state.ConnectionId, state.Status) + err := rw.LookupWhere(context.Background(), &new, "connection_id = ? and state = ?", []interface{}{state.ConnectionId, state.Status}) require.NoError(t, err) - conn.Logger = logger.Default.LogMode(logger.Info) - tests := []struct { name string update *ConnectionState @@ -310,7 +307,7 @@ func TestConnectionState_ImmutableFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() - err := rw.LookupWhere(context.Background(), orig, "connection_id = ? and start_time = ?", new.ConnectionId, new.StartTime) + err := rw.LookupWhere(context.Background(), orig, "connection_id = ? and start_time = ?", []interface{}{new.ConnectionId, new.StartTime}) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) @@ -323,7 +320,7 @@ func TestConnectionState_ImmutableFields(t *testing.T) { assert.Contains(err.Error(), tt.wantErrContains) } after := new.Clone() - err = rw.LookupWhere(context.Background(), after, "connection_id = ? and start_time = ?", new.ConnectionId, new.StartTime) + err = rw.LookupWhere(context.Background(), after, "connection_id = ? and start_time = ?", []interface{}{new.ConnectionId, new.StartTime}) require.NoError(err) assert.Equal(orig.(*ConnectionState), after) }) diff --git a/internal/session/repository_connection.go b/internal/session/repository_connection.go index c86d6297e..856b40d63 100644 --- a/internal/session/repository_connection.go +++ b/internal/session/repository_connection.go @@ -187,7 +187,7 @@ func (r *Repository) CloseConnectionsForDeadWorkers(ctx context.Context, gracePe for rows.Next() { var result CloseConnectionsForDeadWorkersResult - if err := w.ScanRows(rows, &result); err != nil { + if err := w.ScanRows(ctx, rows, &result); err != nil { return errors.Wrap(ctx, err, op) } diff --git a/internal/session/repository_connection_test.go b/internal/session/repository_connection_test.go index 1d51f7df5..7e5753d35 100644 --- a/internal/session/repository_connection_test.go +++ b/internal/session/repository_connection_test.go @@ -82,7 +82,7 @@ func TestRepository_ListConnection(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocConnection()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocConnection(); return &i }(), "1=1") testConnections := []*Connection{} for i := 0; i < tt.createCnt; i++ { c := TestConnection(t, conn, @@ -107,7 +107,7 @@ func TestRepository_ListConnection(t *testing.T) { } t.Run("withOrder", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocConnection()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocConnection(); return &i }(), "1=1") wantCnt := 5 for i := 0; i < wantCnt; i++ { _ = TestConnection(t, conn, diff --git a/internal/session/repository_session.go b/internal/session/repository_session.go index 6c4e9735e..a5d711b5a 100644 --- a/internal/session/repository_session.go +++ b/internal/session/repository_session.go @@ -105,7 +105,7 @@ func (r *Repository) CreateSession(ctx context.Context, sessionWrapper wrapping. defer rows.Close() for rows.Next() { var returnedCred DynamicCredential - w.ScanRows(rows, &returnedCred) + w.ScanRows(ctx, rows, &returnedCred) returnedSession.DynamicCredentials = append(returnedSession.DynamicCredentials, &returnedCred) } } @@ -276,7 +276,7 @@ func (r *Repository) ListSessions(ctx context.Context, opt ...Option) ([]*Sessio var sessionsList []*sessionListView for rows.Next() { var s sessionListView - if err := r.reader.ScanRows(rows, &s); err != nil { + if err := r.reader.ScanRows(ctx, rows, &s); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed")) } sessionsList = append(sessionsList, &s) @@ -504,7 +504,7 @@ func (r *Repository) sessionAuthzSummary(ctx context.Context, sessionId string) return nil, errors.New(ctx, errors.MultipleRecords, op, "query returned more than one row") } info = &ConnectionAuthzSummary{} - if err := r.reader.ScanRows(rows, info); err != nil { + if err := r.reader.ScanRows(ctx, rows, info); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed")) } } diff --git a/internal/session/repository_session_test.go b/internal/session/repository_session_test.go index 946cdac16..b042df6ac 100644 --- a/internal/session/repository_session_test.go +++ b/internal/session/repository_session_test.go @@ -107,7 +107,7 @@ func TestRepository_ListSession(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") testSessions := []*Session{} for i := 0; i < tt.createCnt; i++ { s := TestSession(t, conn, wrapper, composedOf) @@ -142,7 +142,7 @@ func TestRepository_ListSession(t *testing.T) { } t.Run("withOrder", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") wantCnt := 5 for i := 0; i < wantCnt; i++ { _ = TestSession(t, conn, wrapper, composedOf) @@ -159,7 +159,7 @@ func TestRepository_ListSession(t *testing.T) { }) t.Run("withUserId", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") wantCnt := 5 for i := 0; i < wantCnt; i++ { _ = TestSession(t, conn, wrapper, composedOf) @@ -172,7 +172,7 @@ func TestRepository_ListSession(t *testing.T) { }) t.Run("withUserIdAndwithScopeId", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") wantCnt := 5 for i := 0; i < wantCnt; i++ { // Scope 1 User 1 @@ -195,7 +195,7 @@ func TestRepository_ListSession(t *testing.T) { }) t.Run("WithSessionIds", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") testSessions := []*Session{} for i := 0; i < 10; i++ { s := TestSession(t, conn, wrapper, composedOf) @@ -212,7 +212,7 @@ func TestRepository_ListSession(t *testing.T) { }) t.Run("withServerId", func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") for i := 0; i < 6; i++ { if i%2 == 0 { TestWorker(t, conn, wrapper, WithServerId(fmt.Sprintf("server-%d", i/2))) @@ -248,7 +248,7 @@ func TestRepository_ListSessions_Multiple_Scopes(t *testing.T) { repo, err := NewRepository(rw, rw, kms) require.NoError(t, err) - require.NoError(t, conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") const numPerScope = 10 var projs []string @@ -1030,7 +1030,7 @@ func TestRepository_TerminateCompletedSessions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(AllocSession()).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSession(); return &i }(), "1=1") args := tt.setup() got, err := repo.TerminateCompletedSessions(context.Background()) diff --git a/internal/session/state_test.go b/internal/session/state_test.go index c19a0c7b5..766d7e860 100644 --- a/internal/session/state_test.go +++ b/internal/session/state_test.go @@ -124,7 +124,7 @@ func TestState_Delete(t *testing.T) { assert, require := assert.New(t), require.New(t) var initialState State - err := rw.LookupWhere(context.Background(), &initialState, "session_id = ? and state = ?", tt.state.SessionId, tt.state.Status) + err := rw.LookupWhere(context.Background(), &initialState, "session_id = ? and state = ?", []interface{}{tt.state.SessionId, tt.state.Status}) require.NoError(err) deleteState := allocState() @@ -146,7 +146,7 @@ func TestState_Delete(t *testing.T) { } assert.Equal(tt.wantRowsDeleted, deletedRows) foundState := allocState() - err = rw.LookupWhere(context.Background(), &foundState, "session_id = ? and start_time = ?", tt.state.SessionId, initialState.StartTime) + err = rw.LookupWhere(context.Background(), &foundState, "session_id = ? and start_time = ?", []interface{}{tt.state.SessionId, initialState.StartTime}) require.Error(err) assert.True(errors.IsNotFoundError(err)) }) diff --git a/internal/session/testing_test.go b/internal/session/testing_test.go index 8f6ee6061..12a9bf24c 100644 --- a/internal/session/testing_test.go +++ b/internal/session/testing_test.go @@ -64,7 +64,7 @@ func Test_TestConnectionState(t *testing.T) { rw := db.New(conn) var initialState ConnectionState - err := rw.LookupWhere(context.Background(), &initialState, "connection_id = ? and state = ?", cs.ConnectionId, cs.Status) + err := rw.LookupWhere(context.Background(), &initialState, "connection_id = ? and state = ?", []interface{}{cs.ConnectionId, cs.Status}) require.NoError(err) assert.NotEmpty(initialState.StartTime) } diff --git a/internal/target/repository.go b/internal/target/repository.go index fb965b68c..f15279d89 100644 --- a/internal/target/repository.go +++ b/internal/target/repository.go @@ -110,7 +110,7 @@ func (r *Repository) LookupTarget(ctx context.Context, publicIdOrName string, op lookupErr = read.LookupById(ctx, &target) default: target.PublicId = "" - lookupErr = read.LookupWhere(ctx, &target, strings.Join(where, " and "), whereArgs...) + lookupErr = read.LookupWhere(ctx, &target, strings.Join(where, " and "), whereArgs) } if lookupErr != nil { return errors.Wrap(ctx, lookupErr, op, errors.WithMsg(fmt.Sprintf("failed for %s", publicIdOrName))) @@ -380,7 +380,7 @@ func (r *Repository) CreateTarget(ctx context.Context, target Target, opt ...Opt db.StdRetryCnt, db.ExpBackoff{}, func(read db.Reader, w db.Writer) error { - targetTicket, err := w.GetTicket(t) + targetTicket, err := w.GetTicket(ctx, t) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/target/repository_credential_source.go b/internal/target/repository_credential_source.go index 8d158b885..486e4f278 100644 --- a/internal/target/repository_credential_source.go +++ b/internal/target/repository_credential_source.go @@ -102,7 +102,7 @@ func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId st db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -194,7 +194,7 @@ func (r *Repository) DeleteTargetCredentialSources(ctx context.Context, targetId db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -320,7 +320,7 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -421,7 +421,7 @@ func (r *Repository) changes(ctx context.Context, targetId string, cls []*Creden var changes []*change for rows.Next() { var chg changeQueryResult - if err := r.reader.ScanRows(rows, &chg); err != nil { + if err := r.reader.ScanRows(ctx, rows, &chg); err != nil { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed")) } changes = append(changes, &change{ diff --git a/internal/target/repository_host_source.go b/internal/target/repository_host_source.go index 013097c76..18a29f868 100644 --- a/internal/target/repository_host_source.go +++ b/internal/target/repository_host_source.go @@ -65,7 +65,7 @@ func (r *Repository) AddTargetHostSources(ctx context.Context, targetId string, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -161,7 +161,7 @@ func (r *Repository) DeleteTargetHostSources(ctx context.Context, targetId strin db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } @@ -285,7 +285,7 @@ func (r *Repository) SetTargetHostSources(ctx context.Context, targetId string, db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { msgs := make([]*oplog.Message, 0, 2) - targetTicket, err := w.GetTicket(target) + targetTicket, err := w.GetTicket(ctx, target) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket")) } diff --git a/internal/target/tcp/immutable_fields_test.go b/internal/target/tcp/immutable_fields_test.go index 2b7082968..ad78928f8 100644 --- a/internal/target/tcp/immutable_fields_test.go +++ b/internal/target/tcp/immutable_fields_test.go @@ -218,7 +218,7 @@ func TestTargetHostSet_ImmutableFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() - err := rw.LookupWhere(context.Background(), orig, "target_id = ? and host_set_id = ?", new.TargetId, new.HostSetId) + err := rw.LookupWhere(context.Background(), orig, "target_id = ? and host_set_id = ?", []interface{}{new.TargetId, new.HostSetId}) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) @@ -226,7 +226,7 @@ func TestTargetHostSet_ImmutableFields(t *testing.T) { assert.Equal(0, rowsUpdated) after := new.Clone() - err = rw.LookupWhere(context.Background(), after, "target_id = ? and host_set_id = ?", new.TargetId, new.HostSetId) + err = rw.LookupWhere(context.Background(), after, "target_id = ? and host_set_id = ?", []interface{}{new.TargetId, new.HostSetId}) require.NoError(err) assert.True(proto.Equal(orig.(*target.TargetHostSet), after.(*target.TargetHostSet))) }) diff --git a/internal/target/tcp/repository_host_source_test.go b/internal/target/tcp/repository_host_source_test.go index acaa1aa49..0c6c922a3 100644 --- a/internal/target/tcp/repository_host_source_test.go +++ b/internal/target/tcp/repository_host_source_test.go @@ -98,8 +98,8 @@ func TestRepository_AddTargetHostSets(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - require.NoError(conn.Where("1=1").Delete(allocTargetHostSet()).Error) - require.NoError(conn.Where("1=1").Delete(tcp.NewTestTarget("")).Error) + db.TestDeleteWhere(t, conn, func() interface{} { i := allocTargetHostSet(); return &i }(), "1 = 1") + db.TestDeleteWhere(t, conn, tcp.NewTestTarget(""), "1 = 1") ctx := context.Background() projTarget := tcp.TestTarget(ctx, t, conn, staticProj.PublicId, "static-proj") diff --git a/internal/target/tcp/repository_tcp_target_test.go b/internal/target/tcp/repository_tcp_target_test.go index e522eae06..cb4bafec7 100644 --- a/internal/target/tcp/repository_tcp_target_test.go +++ b/internal/target/tcp/repository_tcp_target_test.go @@ -258,7 +258,7 @@ func TestRepository_UpdateTcpTarget(t *testing.T) { newScopeId: proj.PublicId, wantErr: true, wantRowsUpdate: 0, - wantErrMsg: "target.(Repository).UpdateTarget: failed for 1: db.DoTx: target.(Repository).UpdateTarget: target.(Repository).update: db.DoTx: target.(Repository).update: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100", + wantErrMsg: "record not found, search issue: error #1100", wantIsError: errors.RecordNotFound, }, { diff --git a/internal/target/tcp/repository_test.go b/internal/target/tcp/repository_test.go index e7474b271..eecf1bf2e 100644 --- a/internal/target/tcp/repository_test.go +++ b/internal/target/tcp/repository_test.go @@ -215,7 +215,7 @@ func TestRepository_ListTargets(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) ctx := context.Background() - require.NoError(conn.Where("1=1").Delete(tcp.NewTestTarget("")).Error) + db.TestDeleteWhere(t, conn, tcp.NewTestTarget(""), "1=1") testGroups := []target.Target{} for i := 0; i < tt.createCnt; i++ { switch { @@ -249,7 +249,7 @@ func TestRepository_ListRoles_Multiple_Scopes(t *testing.T) { repo, err := target.NewRepository(rw, rw, testKms) require.NoError(t, err) - require.NoError(t, conn.Where("1=1").Delete(tcp.NewTestTarget("")).Error) + db.TestDeleteWhere(t, conn, tcp.NewTestTarget(""), "1=1") ctx := context.Background() const numPerScope = 10